/* Starbound Reading — "Reading takes you places."
   A premium editorial reading journey. One plain-CSS file, in this order:
   tokens · fonts · base · type · marks & devices · layout · header · footer ·
   home sections · inner pages · responsive · motion & preferences.
   Palette = the Starbound Brand Guide (info/, 2026-09-29): white foundation, Midnight Navy,
   Galactic Teal, Nebula Purple, Sunset Coral, Solar Gold, Aurora Green. No tints, no new hues. */

/* 1. Tokens ------------------------------------------------------------- */
:root {
  --navy: #0b1938;
  --purple: #683fa0;
  --teal: #00a896;
  --coral: #ff6b6b;
  --gold: #ff9f1c;
  --orange: #ff9f1c;
  --green: #6dbe45;
  --mist: #f8fafc;
  --white: #ffffff;
  --paper: #f1f5f9;
  --ink: #33363a;

  --line: rgba(11, 25, 56, .16);
  --line-strong: rgba(11, 25, 56, .42);
  --line-on-navy: rgba(255, 255, 255, .22);

  /* The brand's three typefaces: Outfit Bold for headings, Nunito Sans for body copy,
     Caveat for the occasional highlight. All self-hosted (static/fonts, OFL). */
  --font-display: "Outfit", "Segoe UI", Arial, sans-serif;
  --font-text: "Nunito Sans", "Segoe UI", Arial, sans-serif;
  --font-accent: "Caveat", "Segoe Print", "Bradley Hand", cursive;

  /* One text size. Every paragraph, list, quote, caption and note on the site uses
     --fs-body, so a section reads as its header plus one size of text. Labels (the
     small capitals above headings, grades, attributions) share --fs-label, and Caveat
     highlights share --fs-accent. Do not give body copy its own size. */
  --fs-body: clamp(1.0625rem, 1rem + .25vw, 1.1875rem);
  --fs-label: .8rem;
  --fs-accent: clamp(1.7rem, 1.4rem + 1.1vw, 2.4rem);

  --gutter: clamp(20px, 4.5vw, 64px);
  --gap: clamp(16px, 2.4vw, 40px);
  --w-wide: 1400px;
  --w-page: 1180px;
  --measure: 62ch;

  --ease: cubic-bezier(.2, .7, .2, 1);
  --fast: 160ms;
}

/* Crawlable breadcrumbs and long-form Mission Control reading. */
.breadcrumbs { padding-block: 16px; }
.breadcrumbs ol { display: flex; flex-wrap: wrap; gap: 8px; padding: 0; margin: 0; list-style: none; font-size: .9rem; }
.breadcrumbs li + li::before { content: "/"; margin-right: 8px; }
.breadcrumbs a { display: inline-block; padding-block: 6px; }
.article-copy .shell { max-width: 760px; }
.article-copy h2 { font-size: clamp(1.4rem, 1.2rem + 1vw, 2rem); margin-top: 1.7em; }
.article-related { margin-top: 32px; }
@media (max-width: 899px) {
  .site-nav :focus-visible, .nav-toggle[aria-expanded="true"]:focus-visible { outline-color: var(--gold); }
}

/* 2. Fonts (self-hosted variable files) ---------------------------------- */
@font-face { font-family: "Outfit"; src: url("../fonts/outfit-variable.woff2") format("woff2"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Nunito Sans"; src: url("../fonts/nunito-sans-variable.woff2") format("woff2"); font-weight: 200 1000; font-style: normal; font-display: swap; }
@font-face { font-family: "Nunito Sans"; src: url("../fonts/nunito-sans-variable-italic.woff2") format("woff2"); font-weight: 200 1000; font-style: italic; font-display: swap; }
@font-face { font-family: "Caveat"; src: url("../fonts/caveat-variable.woff2") format("woff2"); font-weight: 400 700; font-style: normal; font-display: swap; }

/* 3. Base ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html, body { overflow-x: clip; }
body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font: 400 var(--fs-body)/1.65 var(--font-text);
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; }
ul, ol { margin: 0; padding-left: 1.2em; }
figure { margin: 0; }
button { font: inherit; color: inherit; }
[id] { scroll-margin-top: 96px; }

:focus-visible { outline: 2px solid var(--purple); outline-offset: 3px; }
.on-navy :focus-visible, .site-footer :focus-visible { outline-color: var(--gold); }

.visually-hidden, .nav-toggle-label {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: fixed; top: 12px; left: 12px; z-index: 100;
  background: var(--navy); color: #fff; padding: 12px 18px;
  font: 600 .95rem/1 var(--font-text); text-decoration: none; transform: translateY(-200%);
}
.skip-link:focus { transform: none; outline: 2px solid var(--gold); outline-offset: 2px; }

/* 4. Type ---------------------------------------------------------------- */
h1, h2, h3, .display-xl, .display-l {
  font-family: var(--font-display);
  color: var(--navy);
  margin: 0;
  font-weight: 700;
  text-wrap: balance;
}
.display-xl {
  font-size: clamp(3.1rem, 1.8rem + 6vw, 7.2rem); line-height: .98;
  letter-spacing: -.03em;
}
.display-l {
  font-size: clamp(2.1rem, 1.3rem + 3.4vw, 4.4rem); line-height: 1.05;
  letter-spacing: -.025em;
}
h1 { font-size: clamp(2.4rem, 1.5rem + 3.8vw, 4.9rem); line-height: 1.02; letter-spacing: -.025em; }
h2 { font-size: clamp(1.8rem, 1.4rem + 1.8vw, 2.9rem); line-height: 1.1; letter-spacing: -.02em; }
h3 { font-size: clamp(1.3rem, 1.15rem + .6vw, 1.7rem); line-height: 1.2; letter-spacing: -.01em; }
p { margin: 0; max-width: var(--measure); text-wrap: pretty; }
p + p { margin-top: 1em; }
h2 + p, h3 + p, .display-l + p { margin-top: .8em; }
/* .lead and .small no longer change the size: they are kept as hooks only, so the
   first paragraph of a section is the same size as the rest (see --fs-body). */
.lead { max-width: var(--measure); }
.small { font-size: inherit; }
.kicker {
  display: block; margin: 0 0 14px;
  font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple);
}
.on-navy .kicker { color: var(--gold); }
.on-navy, .on-navy h1, .on-navy h2, .on-navy h3, .on-navy .display-l, .on-navy .lead, .on-navy p { color: #fff; }
.em { font-family: var(--font-accent); font-weight: 700; font-size: 1.3em; line-height: 1; }

/* Buttons and links.
   ONE button, per the Brand Guide: Galactic Teal is the colour of "interactive states and
   key buttons". Every "find out more / explore / get in touch" action is a .btn and looks
   exactly the same everywhere, WhatsApp and email included: teal, Midnight Navy lettering
   (5.7:1), softly rounded like the guide's controls, with no arrow. Teal holds 4.1:1 against
   white and reads clearly on the navy sky, so the same button works on every band. Hover
   turns it navy (white on the sky), so it never disappears into the band it sits on. */
.btn {
  display: inline-flex; align-items: center; gap: .55em; padding: .9em 1.4em .88em;
  background: var(--teal); color: var(--navy); border: 2px solid var(--teal); border-radius: 12px;
  font: 700 1rem/1.1 var(--font-display); letter-spacing: .01em; text-decoration: none; text-align: left;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease), color var(--fast) var(--ease), translate 220ms var(--ease), box-shadow 260ms var(--ease);
}
.btn:hover { background: var(--navy); border-color: var(--navy); color: #fff; }
.btn:hover, .site-nav .nav-contact:hover { box-shadow: 0 12px 28px -12px rgba(0, 168, 150, .7); }
:is(.on-navy, .site-footer) .btn:hover { background: #fff; border-color: #fff; color: var(--navy); }
.link {
  display: inline-block; padding-block: .35em; color: var(--navy); font-weight: 600; text-decoration: underline;
  text-decoration-thickness: 2px; text-underline-offset: .32em; text-decoration-color: var(--coral);
  transition: color var(--fast) var(--ease), text-decoration-color var(--fast) var(--ease);
}
.link:hover { color: var(--purple); text-decoration-color: var(--purple); }
/* Inside a sentence: no block padding, so the link sits on the text's own baseline grid
   instead of opening up the line it falls in. */
.link--inline { display: inline; padding-block: 0; }
.on-navy .link { color: #fff; text-decoration-color: var(--gold); }
.on-navy .link:hover { color: var(--gold); }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 28px; margin-top: 32px; }
/* "Enquire about <programme>": the site's one button, opening to a choice of WhatsApp
   or email (templates/_contact.html). */
.enquire > summary { list-style: none; cursor: pointer; width: max-content; max-width: 100%; }
.enquire > summary::-webkit-details-marker { display: none; }
.enquire[open] > summary { background: var(--navy); border-color: var(--navy); color: #fff; }
.on-navy .enquire[open] > summary { background: #fff; border-color: #fff; color: var(--navy); }
.enquire__options { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 12px; }
/* An open enquiry grows downwards; the buttons beside it stay level with its top. */
.actions:has(> .enquire) { align-items: flex-start; }
.practical__actions, .attend__actions { grid-column: 1 / -1; margin-top: clamp(24px, 3vw, 40px); }

/* 5. Marks and brand devices --------------------------------------------- */
.mark { display: block; }
.u { position: relative; display: inline-block; }
.u > .mark--underline { position: absolute; left: -2%; width: 104%; bottom: -.14em; height: .34em; color: var(--coral); pointer-events: none; }
.circled { position: relative; display: inline-block; padding: 0 .12em; }
.circled > .mark--circle { position: absolute; left: -6%; top: -16%; width: 114%; height: 136%; color: var(--coral); pointer-events: none; }
.mark--arrow { width: 3.2em; height: 1.7em; color: var(--coral); }
.star { width: 1em; height: 1em; color: var(--gold); }

/* Programme numerals: outlined Outfit. Numbers on this site mean one thing only,
   "programme N of six", so this device is reserved for the six programmes and never
   used to count page sections, which visitors read as programme numbers. */
.chapter__head { display: flex; align-items: baseline; gap: clamp(12px, 2vw, 26px); margin-bottom: clamp(28px, 4vw, 56px); }
.programme__num {
  font: 700 clamp(3rem, 2.2rem + 4vw, 6.8rem)/.85 var(--font-display);
  letter-spacing: -.04em; color: transparent; -webkit-text-stroke: 1.2px var(--navy);
}
.on-navy .programme__num { -webkit-text-stroke-color: #fff; }
@supports not (-webkit-text-stroke: 1px #000) { .programme__num { color: var(--navy); } .on-navy .programme__num { color: #fff; } }
.chapter__head .kicker { margin: 0; }

/* Programme logos: supplied artwork, shown as-is. Each file's viewBox is a square fitted
   to its own drawing, so one fixed box gives all six the same visual size. Navy lettering on
   a transparent ground, so light bands only. alt="" in the markup: the programme name
   beside it already says what the wordmark says. */
.programme-logo { display: block; flex: none; width: 136px; height: 136px; }

/* Contact links (scrape-resistant; see templates/_contact.html + site.js) */
.contact-link { text-decoration: none; }
.contact-rev { unicode-bidi: bidi-override; direction: rtl; display: inline-block; }
/* Exactly one of these two is visible. With JS the link offers "Show number"; without
   it - disabled OR site.js failed to load - the reversed value shows instead, so the
   link is never empty. */
html.has-js .contact-rev { display: none; }
html:not(.has-js) .contact-reveal { display: none; }
.contact-prefix { margin-right: .3em; }
.contact-link .contact-value { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .3em; text-decoration-color: var(--coral); }
.contact-link:hover .contact-value { text-decoration-color: var(--purple); }
.on-navy .contact-link .contact-value, .site-footer .contact-link .contact-value { text-decoration-color: var(--gold); }
.contact-link.btn .contact-value, .contact-link.btn:hover .contact-value { text-decoration: none; }
.contact-link.btn .contact-rev { margin-left: .5em; }

/* Night sky ----------------------------------------------------------------
   The brand navy as a sky: a static dust layer on the section itself, and two star
   layers on its pseudo-elements that twinkle out of phase. White and brand gold only;
   the gold ones are four-point sparkles so the five-point star stays the one
   destination star. Tiles are 480/640/820 wide so the layers never line up into a
   visible grid. Pure CSS data URIs: no markup, no requests, and nothing the CSP has to
   allow beyond the img-src data: it already permits. isolation + z-index -1 keeps the
   stars above the section background and below its content without touching z-index
   on any child. */
:root {
  --sky-dust: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='480' height='360' viewBox='0 0 480 360'%3E%3Ccircle cx='431' cy='241' r='0.6' fill='%23fff' opacity='0.48'/%3E%3Ccircle cx='8' cy='31' r='0.8' fill='%23fff' opacity='0.37'/%3E%3Ccircle cx='35' cy='262' r='0.7' fill='%23fff' opacity='0.41'/%3E%3Ccircle cx='406' cy='246' r='0.7' fill='%23fff' opacity='0.28'/%3E%3Ccircle cx='411' cy='188' r='0.5' fill='%23fff' opacity='0.41'/%3E%3Ccircle cx='101' cy='64' r='0.9' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='52' cy='227' r='0.9' fill='%23fff' opacity='0.24'/%3E%3Ccircle cx='60' cy='114' r='0.6' fill='%23fff' opacity='0.24'/%3E%3Ccircle cx='152' cy='228' r='0.5' fill='%23fff' opacity='0.26'/%3E%3Ccircle cx='288' cy='192' r='0.9' fill='%23fff' opacity='0.27'/%3E%3Ccircle cx='415' cy='25' r='0.8' fill='%23fff' opacity='0.26'/%3E%3Ccircle cx='96' cy='258' r='0.6' fill='%23fff' opacity='0.23'/%3E%3Ccircle cx='305' cy='38' r='0.7' fill='%23fff' opacity='0.32'/%3E%3Ccircle cx='45' cy='121' r='0.8' fill='%23fff' opacity='0.32'/%3E%3Ccircle cx='126' cy='46' r='0.8' fill='%23fff' opacity='0.28'/%3E%3Ccircle cx='285' cy='203' r='0.6' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='417' cy='51' r='0.8' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='103' cy='132' r='0.7' fill='%23fff' opacity='0.28'/%3E%3Ccircle cx='19' cy='339' r='0.5' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='281' cy='256' r='0.6' fill='%23fff' opacity='0.25'/%3E%3Ccircle cx='62' cy='243' r='0.7' fill='%23fff' opacity='0.30'/%3E%3Ccircle cx='162' cy='119' r='0.8' fill='%23fff' opacity='0.41'/%3E%3Ccircle cx='315' cy='16' r='0.8' fill='%23fff' opacity='0.24'/%3E%3Ccircle cx='74' cy='32' r='0.5' fill='%23fff' opacity='0.25'/%3E%3Ccircle cx='361' cy='168' r='0.6' fill='%23fff' opacity='0.25'/%3E%3Ccircle cx='376' cy='126' r='0.8' fill='%23fff' opacity='0.48'/%3E%3Ccircle cx='396' cy='315' r='0.9' fill='%23fff' opacity='0.46'/%3E%3Ccircle cx='404' cy='162' r='0.7' fill='%23fff' opacity='0.35'/%3E%3Ccircle cx='454' cy='87' r='0.7' fill='%23fff' opacity='0.30'/%3E%3Ccircle cx='13' cy='350' r='0.9' fill='%23fff' opacity='0.46'/%3E%3Ccircle cx='370' cy='84' r='0.6' fill='%23fff' opacity='0.37'/%3E%3Ccircle cx='152' cy='293' r='0.7' fill='%23fff' opacity='0.28'/%3E%3Ccircle cx='242' cy='11' r='0.6' fill='%23fff' opacity='0.31'/%3E%3Ccircle cx='57' cy='290' r='0.8' fill='%23fff' opacity='0.47'/%3E%3Ccircle cx='444' cy='55' r='0.7' fill='%23fff' opacity='0.34'/%3E%3Ccircle cx='364' cy='320' r='0.8' fill='%23fff' opacity='0.31'/%3E%3Ccircle cx='221' cy='184' r='0.7' fill='%23fff' opacity='0.27'/%3E%3Ccircle cx='218' cy='324' r='0.7' fill='%23fff' opacity='0.32'/%3E%3Ccircle cx='339' cy='127' r='0.7' fill='%23fff' opacity='0.49'/%3E%3Ccircle cx='241' cy='224' r='0.7' fill='%23fff' opacity='0.40'/%3E%3Ccircle cx='167' cy='214' r='0.8' fill='%23fff' opacity='0.37'/%3E%3Ccircle cx='388' cy='135' r='0.7' fill='%23fff' opacity='0.47'/%3E%3C/svg%3E");
  --sky-near: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='440' viewBox='0 0 640 440'%3E%3Ccircle cx='608' cy='164' r='1.3' fill='%23fff' opacity='0.87'/%3E%3Ccircle cx='354' cy='81' r='0.9' fill='%23fff' opacity='0.94'/%3E%3Ccircle cx='506' cy='175' r='1.3' fill='%23fff' opacity='0.60'/%3E%3Ccircle cx='131' cy='247' r='1.1' fill='%23fff' opacity='0.86'/%3E%3Ccircle cx='130' cy='214' r='1.3' fill='%23fff' opacity='0.75'/%3E%3Ccircle cx='576' cy='166' r='1.2' fill='%23fff' opacity='0.68'/%3E%3Ccircle cx='186' cy='387' r='1.0' fill='%23fff' opacity='0.61'/%3E%3Ccircle cx='628' cy='349' r='1.2' fill='%23fff' opacity='0.77'/%3E%3Ccircle cx='235' cy='109' r='1.3' fill='%23fff' opacity='0.78'/%3E%3Ccircle cx='191' cy='332' r='1.1' fill='%23fff' opacity='0.61'/%3E%3Ccircle cx='88' cy='368' r='0.9' fill='%23fff' opacity='0.68'/%3E%3Ccircle cx='136' cy='310' r='1.3' fill='%23fff' opacity='0.90'/%3E%3Ccircle cx='543' cy='173' r='1.1' fill='%23fff' opacity='0.89'/%3E%3Ccircle cx='276' cy='356' r='1.2' fill='%23fff' opacity='0.82'/%3E%3Ccircle cx='191' cy='367' r='1.0' fill='%23fff' opacity='0.84'/%3E%3Ccircle cx='362' cy='284' r='1.4' fill='%23fff' opacity='0.60'/%3E%3C/svg%3E");
  --sky-far: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='820' height='560' viewBox='0 0 820 560'%3E%3Ccircle cx='788' cy='532' r='1.3' fill='%23fff' opacity='0.95'/%3E%3Ccircle cx='407' cy='482' r='1.2' fill='%23fff' opacity='0.97'/%3E%3Ccircle cx='799' cy='57' r='1.7' fill='%23fff' opacity='0.72'/%3E%3Ccircle cx='292' cy='459' r='1.7' fill='%23fff' opacity='0.92'/%3E%3Ccircle cx='444' cy='355' r='1.1' fill='%23fff' opacity='0.77'/%3E%3Ccircle cx='545' cy='461' r='1.3' fill='%23fff' opacity='0.79'/%3E%3Ccircle cx='262' cy='158' r='1.2' fill='%23fff' opacity='0.83'/%3E%3Cpath d='M179 162Q178.8 167.9 185 168Q178.8 167.9 179 174Q178.8 167.9 173 168Q178.8 167.9 179 162Z' fill='%23ff9f1c' opacity='0.91'/%3E%3Cpath d='M103 294Q103.4 300.4 109 300Q103.4 300.4 103 306Q103.4 300.4 97 300Q103.4 300.4 103 294Z' fill='%23ff9f1c' opacity='0.90'/%3E%3Cpath d='M459 363Q458.7 369.5 465 369Q458.7 369.5 459 376Q458.7 369.5 453 369Q458.7 369.5 459 363Z' fill='%23ff9f1c' opacity='0.79'/%3E%3Cpath d='M577 363Q576.8 368.5 582 368Q576.8 368.5 577 373Q576.8 368.5 572 368Q576.8 368.5 577 363Z' fill='%23ff9f1c' opacity='0.82'/%3E%3C/svg%3E");
}
.sky { position: relative; isolation: isolate; background: var(--sky-dust) 0 0 / 480px 360px repeat, var(--navy); }
.sky:not(.site-footer) { overflow: hidden; overflow: clip; }
.sky::before, .sky::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.sky::before { background: var(--sky-near) 0 0 / 640px 440px repeat; }
.sky::after { background: var(--sky-far) 120px 60px / 820px 560px repeat; }
/* Shooting stars rise along the swoosh's own angle: launching, not falling. site.js adds
   one per sky, never on the footer and never for reduced motion. The tail fading into
   the head is the trajectory device, the one place gradients are allowed. */
.shooting-star { position: absolute; z-index: -1; left: 10%; top: 70%; width: clamp(90px, 12vw, 170px); height: 2px; border-radius: 2px; opacity: 0; pointer-events: none; rotate: -18deg; transform-origin: 100% 50%; background: linear-gradient(90deg, rgba(255, 159, 28, 0), var(--gold)); }
.shooting-star::after { content: ""; position: absolute; right: -3px; top: -2px; width: 6px; height: 6px; border-radius: 50%; background: #fff; box-shadow: 0 0 8px 2px rgba(255, 159, 28, .8); }
/* Two skies back to back (home: the statement passage, then the journey) keep one
   continuous night, parted by the site's own hairline rather than merging. */
.band.sky + .band.sky { border-top: 1px solid var(--line-on-navy); }
.ss-2 { left: 34%; top: 58%; }
.ss-3 { left: 20%; top: 86%; }
.ss-4 { left: 52%; top: 40%; }
.ss-5 { left: 66%; top: 66%; }
.ss-6 { left: 8%; top: 48%; }

/* On the sky: every element that sits on navy needs a colour that holds contrast
   there. Purple fails on navy (2.2:1), so it is swapped for gold or teal (5.6:1). */
.on-navy .hero__word, .on-navy .page-head__pull { color: var(--gold); }
.on-navy .page-head__note { color: rgba(255, 255, 255, .88); }
.on-navy .station__dot { border-color: rgba(255, 255, 255, .85); background: var(--navy); }
.on-navy .station--live .station__dot { border-color: var(--gold); background: var(--gold); }
.on-navy .station__name { color: #fff; }
.on-navy .station__grade { color: var(--teal); }
.on-navy .stations { border-left-color: rgba(255, 255, 255, .35); }

/* 6. Layout -------------------------------------------------------------- */
.shell { width: min(var(--w-page), 100% - 2 * var(--gutter)); margin-inline: auto; }
.shell--wide { width: min(var(--w-wide), 100% - 2 * var(--gutter)); }
.grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); }
.band { padding-block: clamp(56px, 8vw, 128px); }
.band--paper { background: var(--paper); }
.band--navy { background: var(--navy); }
.rule { border: 0; border-top: 1px solid var(--line); margin: 0; }

/* 7. Header --------------------------------------------------------------- */
.site-header { position: sticky; top: 0; z-index: 50; background: var(--white); border-bottom: 1px solid var(--line); }
.masthead { display: flex; align-items: center; justify-content: space-between; gap: 24px; min-height: 80px; }
.brand { display: inline-flex; align-items: center; gap: 12px; padding: 6px 0; text-decoration: none; }
.brand-mark { width: auto; height: 38px; }
.brand-word { width: auto; height: 34px; }
.site-nav { display: flex; align-items: center; gap: clamp(18px, 2.6vw, 40px); }
.site-nav a { position: relative; display: inline-block; padding: 12px 0; font: 600 .95rem/1 var(--font-text); color: var(--navy); text-decoration: none; }
.site-nav a .mark--underline { position: absolute; left: -2px; right: -2px; bottom: 5px; height: .42em; color: var(--coral); opacity: 0; transition: opacity var(--fast) var(--ease); }
.site-nav a:hover .mark--underline, .site-nav a:focus-visible .mark--underline, .site-nav a[aria-current="page"] .mark--underline { opacity: 1; }
.site-nav .nav-contact { padding: .8em 1.15em .75em; background: var(--teal); color: var(--navy); border: 2px solid var(--teal); border-radius: 12px; font-family: var(--font-display); font-weight: 700; margin-left: 8px; transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease), color var(--fast) var(--ease), translate 220ms var(--ease), box-shadow 260ms var(--ease); }
.site-nav .nav-contact:hover { background: var(--navy); border-color: var(--navy); color: #fff; }
.site-nav .nav-contact .mark--underline { display: none; }
.site-nav .nav-contact[aria-current="page"] { background: var(--navy); border-color: var(--navy); color: #fff; }
.nav-toggle { display: none; }
/* Six items since the Home tab joined: keep every label on one line and tighten the
   spacing just above the mobile-menu breakpoint so the row still fits. */
.site-nav a { white-space: nowrap; }
@media (min-width: 900px) and (max-width: 1099px) {
  .site-nav { gap: 16px; }
  .site-nav a { font-size: .88rem; }
  .site-nav .nav-contact { margin-left: 0; padding-inline: .9em; }
}

/* 8. Footer ---------------------------------------------------------------- */
.site-footer { position: relative; background: var(--navy); color: #fff; margin-top: clamp(72px, 10vw, 150px); padding: clamp(40px, 5vw, 72px) 0 28px; }
.site-footer .seam { position: absolute; left: 0; right: 0; bottom: 100%; width: 100%; height: clamp(40px, 7vw, 110px); fill: var(--navy); display: block; transform: translateY(1px); pointer-events: none; }
.footer-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); row-gap: 40px; position: relative; }
.footer-brand { grid-column: 1 / 5; }
.footer-brand img { width: auto; height: 132px; }
img.footer-lockup { height: clamp(210px, 20vw, 280px); }
.footer-brand p { margin-top: 20px; max-width: 34ch; color: rgba(255, 255, 255, .78); }
.footer-nav { grid-column: 6 / 8; display: flex; flex-direction: column; align-items: flex-start; }
.footer-contact { grid-column: 9 / 13; }
/* A page that ends on a band (paper, navy or plain) needs no margin above the footer:
   the wave then cuts into the band's own bottom padding, rather than floating below a
   strip of bare white (user, 2026-10-03: "dead white space" under Mission Control). */
main:has(> .band:last-child) + .site-footer { margin-top: 0; }
.footer-label { display: block; margin-bottom: 14px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--gold); }
.footer-nav a { display: block; padding: 9px 0; font: 600 var(--fs-body)/1.3 var(--font-text); color: #fff; text-decoration: none; }
.footer-nav a:hover { text-decoration: underline; text-underline-offset: 5px; text-decoration-color: var(--gold); }
.footer-contact .contact-link { display: block; padding: 8px 0; font: 600 var(--fs-body)/1.4 var(--font-text); color: #fff; }
.footer-contact .contact-link .contact-value { text-decoration-color: var(--gold); }
.footer-contact > span { display: block; margin-top: 8px; color: rgba(255, 255, 255, .78); }
.footer-base { margin-top: clamp(40px, 5vw, 64px); padding-top: 18px; border-top: 1px solid var(--line-on-navy); display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 24px; font-size: .82rem; color: rgba(255, 255, 255, .72); }
.footer-base .turnstile-notice { flex-basis: 100%; margin-top: 6px; font-size: .82rem; line-height: 1.6; }
.turnstile-notice a { color: inherit; text-underline-offset: 3px; }

/* 9. Home chapters --------------------------------------------------------- */
/* Hero */
.hero { position: relative; overflow: hidden; padding-block: clamp(36px, 6vw, 88px) clamp(48px, 7vw, 110px); }
.hero__kicker { margin-bottom: clamp(24px, 4vw, 48px); }
.hero__title { position: relative; z-index: 2; }
.hero__word { color: var(--purple); white-space: nowrap; position: relative; }
.hero__title .w:not(.hero__word) { display: inline-block; }
.hero__copy { position: relative; z-index: 2; margin-top: clamp(28px, 4vw, 48px); }
.hero__copy .lead { margin-bottom: 1em; }
.hero__copy p { max-width: 58ch; }
/* Justified (user, 2026-10-01). Hyphenation evens out the word spacing, which matters
   most on the narrow phone column. */
.hero__text p { text-align: justify; hyphens: auto; -webkit-hyphens: auto; }
.hero__more { margin-top: 18px; }
.hero__art { display: block; position: relative; z-index: 1; width: 100%; height: auto; margin-top: clamp(16px, 4vw, 32px); }
.hero__more a { margin-right: 22px; }

/* Why Starbound exists (the founders' passage) */
/* The founders' photo slot (templates/home.html): shown only once the photo exists. */
.origin__photo { display: block; width: 100%; height: auto; border-radius: var(--card-radius, 20px); margin: 0 0 clamp(24px, 3vw, 36px); }
.origin__copy { margin-top: clamp(24px, 3vw, 40px); }
/* The founders' words, in the same voice as .quote but sized for this narrower column
   rather than the full-width pull quote in Observed experience. */
.founders-quote { margin: 0; }
.founders-quote p { max-width: 40ch; padding-left: 18px; border-left: 3px solid var(--gold); font-style: italic; font-weight: 600; color: var(--navy); }
.founders-quote cite { display: block; margin-top: 16px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); font-style: normal; }


/* The journey */
.journey__copy { margin-top: clamp(40px, 5vw, 72px); }
/* Left to right across the page, justified, as in the home hero (user, 2026-10-01). */
.journey__copy p { max-width: none; text-align: justify; hyphens: auto; -webkit-hyphens: auto; }
.stations { --path-h: clamp(140px, 16vw, 220px); list-style: none; margin: clamp(24px, 3vw, 32px) 0 0; padding: 0; position: relative; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); column-gap: var(--gap); }
/* Each station sits where the arc actually passes under its column. Solved off the
   curve in .stations::before rather than eyeballed, and kept here rather than in a
   style attribute so the CSP never needs 'unsafe-inline' for styles.
   --y is a UNITLESS ratio, not a percentage: calc() cannot multiply a length by a
   percentage, and a percentage here makes the whole padding-top declaration invalid,
   which silently flattens every station onto one line and lets the arc cut through
   the text. Solved at each DOT's centre (column left edge + 9px), not the column
   centre: the dot is a block at the start of the <li>, so a centre-based solve leaves
   the arc drifting further from every marker as it climbs. */
.station:nth-child(1) { --y: .980; --i: 0; }
.station:nth-child(2) { --y: .949; --i: 1; }
.station:nth-child(3) { --y: .876; --i: 2; }
.station:nth-child(4) { --y: .752; --i: 3; }
.station:nth-child(5) { --y: .568; --i: 4; }
.station:nth-child(6) { --y: .314; --i: 5; }
.stations::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: var(--path-h);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 200' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0' stop-color='%23683fa0'/%3E%3Cstop offset='.35' stop-color='%2300a896'/%3E%3Cstop offset='.7' stop-color='%23ff9f1c'/%3E%3Cstop offset='1' stop-color='%23ff6b6b'/%3E%3C/linearGradient%3E%3ClinearGradient id='h' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0' stop-color='%2300a896'/%3E%3Cstop offset='.5' stop-color='%23ff9f1c'/%3E%3Cstop offset='1' stop-color='%23ff6b6b'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M60 199Q740 196 1200 36' fill='none' stroke='url(%23h)' stroke-width='1.5' stroke-linecap='round' opacity='.6'/%3E%3Cpath d='M0 196Q700 190 1200 10' fill='none' stroke='url(%23g)' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat;
  background-size: 100% 100%; pointer-events: none;
}
.station { position: relative; padding-top: calc(var(--path-h) * var(--y) - 9px); }
/* display:block is load-bearing: this is a <span>, and once the 720px rule returns it
   to position:static it would fall back to inline, where width/height are ignored and
   the marker collapses into a sliver instead of a dot on the arc. */
.station__dot { display: block; width: 18px; height: 18px; border: 2px solid var(--navy); border-radius: 50%; background: var(--white); margin-bottom: 14px; }
.station--live .station__dot { background: var(--gold); }
/* Each programme's logo above its name, one size for all six. The home journey is a
   light band (since 2026-10-05), so these are the original-colour logos. */
/* The logo spells the name (the name itself is screen-reader only), so it is ~35%
   larger than when the name sat beneath it, capped at its column. */
.station__logo { display: block; width: min(100%, clamp(140px, 9vw + 56px, 196px)); height: auto; aspect-ratio: 1; margin-bottom: 10px; }
.station__name { display: block; font: 700 clamp(1.15rem, 1rem + .6vw, 1.5rem)/1.1 var(--font-display); color: var(--navy); }
.station__grade { display: block; margin-top: 4px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); }
.station__desc { margin-top: 10px; }
/* Each logo links to its programme's details; it lifts a little under the pointer. */
.station__link { display: inline-block; border-radius: 12px; transition: translate 220ms var(--ease), scale 220ms var(--ease); }
.station__link:hover { translate: 0 -4px; scale: 1.04; }

/* South Africa's reading challenge */
.challenge__num { font: 700 clamp(5.6rem, 3.4rem + 11vw, 15rem)/.82 var(--font-display); color: var(--navy); letter-spacing: -.05em; }
.challenge__num .u > .mark--underline { bottom: -.06em; height: .16em; }
/* The second statistic sits under the first in the same column, a step smaller so the
   two read as a pair rather than competing, and divided by the site's hairline. */
.challenge__num--second { margin-top: clamp(32px, 4vw, 56px); padding-top: clamp(28px, 3.5vw, 48px); border-top: 1px solid var(--line); font-size: clamp(4rem, 2.6rem + 7vw, 10.5rem); }
.challenge__caption { margin-top: 22px; max-width: 30ch; color: var(--navy); font-weight: 600; }
.challenge__sources { margin-top: 28px; color: var(--ink); }
.challenge__sources a { color: var(--navy); display: inline-block; padding-block: .3em; }
.challenge__why { margin-bottom: 18px; }
/* CAPS mapping sits in the home journey under the station arc (moved 2026-10-01). It
   keeps the journey's open, card-free look, so the card is undone here and the note is
   set off by the site's hairline instead. */
.caps p { max-width: 62ch; }
.caps__col + .caps__col { margin-top: 28px; }
@media (min-width: 900px) { .caps__col + .caps__col { margin-top: 0; } }
.journey .caps { grid-column: 1 / -1; margin-top: clamp(40px, 5vw, 72px); background: none; border: 0; border-top: 1px solid var(--line); border-radius: 0; box-shadow: none; padding: 22px 0 0; }

/* Inside Starbound */
.inside { overflow: hidden; }
.inside__window {
  /* Never wider than the screen (user, 2026-10-01): the word is ~4.45em wide, so the
     size is capped at the space between the gutters divided by 4.6, and it stays on
     one line instead of breaking as "adventur / e" on phones. */
  font: 900 min(clamp(4rem, 1.5rem + 15vw, 15.5rem), calc((100vw - 2 * var(--gutter)) / 4.6))/.86 var(--font-display); letter-spacing: -.05em; white-space: nowrap;
  color: transparent; -webkit-background-clip: text; background-clip: text;
  background-color: var(--navy);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 420' preserveAspectRatio='xMidYMid slice'%3E%3Crect width='1200' height='420' fill='%230b1938'/%3E%3Cg fill='none' stroke-linecap='round'%3E%3Cpath d='M-40 300C260 286 620 210 1240 -40' stroke='%23683fa0' stroke-width='30'/%3E%3Cpath d='M-40 360C270 346 630 270 1240 20' stroke='%2300a896' stroke-width='30'/%3E%3Cpath d='M-40 420C280 406 640 330 1240 80' stroke='%23ff9f1c' stroke-width='30'/%3E%3Cpath d='M-40 480C290 466 650 390 1240 140' stroke='%23ff6b6b' stroke-width='30'/%3E%3C/g%3E%3Cpath d='M1060 52l9 19 21 3-15 15 4 21-19-10-19 10 4-21-15-15 21-3z' fill='%23ff9f1c'/%3E%3C/svg%3E");
  background-size: cover; background-position: center; display: block; margin: 0 -.03em;
}
@supports not (background-clip: text) { .inside__window { color: var(--navy); background: none; } }
.inside__copy { margin-top: clamp(24px, 3vw, 40px); }
.tactile { list-style: none; margin: clamp(24px, 3vw, 40px) 0 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 18px; max-width: 26ch; }
/* --n is the word's place in the list: the motion block uses it to let the words arrive
   one after another, the way a session is built up. */
.tactile li { --r: 0deg; --n: 8; display: inline-block; rotate: var(--r); padding: .15em .1em; font: 700 var(--fs-accent)/1.15 var(--font-accent); color: var(--navy); }
.tactile li:nth-child(1) { --r: -3deg; --n: 0; }
.tactile li:nth-child(2) { --r: 2deg; --n: 1; }
.tactile li:nth-child(3) { --r: -1deg; --n: 2; }
.tactile li:nth-child(4) { --r: 3deg; --n: 3; }
.tactile li:nth-child(5) { --r: -2deg; --n: 4; }
.tactile li:nth-child(6) { --r: 1.5deg; --n: 5; }
.tactile li:nth-child(7) { --r: -2.5deg; --n: 6; }
.tactile li:nth-child(8) { --r: 2deg; --n: 7; }
.tactile li:nth-child(2n) { color: var(--purple); }
/* The scene: the Launchpad photo, with the words a session is made of pinned round its
   edges like handwritten labels and the supplied UFO (static/Iconography/UFO.svg, viewBox
   tightened to the drawing, artwork untouched) hovering over its top corner, beaming
   down on the child. The side padding is the margin the labels hang out into, so they
   never push past the gutters on a phone. Label places are percentages of the scene,
   kept clear of the child's face; "sound" sits by the sound phone. */
.inside__scene { position: relative; width: 100%; max-width: 500px; margin: clamp(56px, 8vw, 72px) auto 0; padding: 0 13%; }
.inside__photo { display: block; width: 100%; height: auto; border-radius: 20px; rotate: 1.5deg; box-shadow: 0 26px 50px -24px rgba(11, 25, 56, .55); }
.inside__scene .inside__ufo { position: absolute; z-index: 3; top: -11%; right: -1%; width: 34%; height: auto; rotate: -8deg; }
.inside__sky { display: none; }
/* A soft gold cone from under the UFO to the child. */
.inside__beam {
  position: absolute; z-index: 1; top: 3%; right: 6%; width: 52%; height: 40%; pointer-events: none;
  clip-path: polygon(70% 0, 86% 0, 40% 100%, 0 82%);
  background: linear-gradient(200deg, rgba(255, 214, 130, .9), rgba(255, 214, 130, .35) 65%, rgba(255, 207, 120, 0));
  mix-blend-mode: screen;
}
.inside__scene .tactile { position: absolute; z-index: 2; inset: 0; margin: 0; max-width: none; display: block; }
.inside__scene .tactile li {
  position: absolute; top: var(--y); left: var(--x, auto); right: var(--x2, auto);
  padding: .02em .38em .08em; background: var(--white); border-radius: 6px; line-height: 1;
  font-size: clamp(1.5rem, 1.2rem + .95vw, 2.2rem); white-space: nowrap;
  box-shadow: 0 6px 14px -8px rgba(11, 25, 56, .5);
}
.inside__scene .tactile li:nth-child(1) { --x2: 0; --y: 31%; }
.inside__scene .tactile li:nth-child(2) { --x: 0; --y: 21%; }
.inside__scene .tactile li:nth-child(3) { --x: 0; --y: 46%; }
.inside__scene .tactile li:nth-child(4) { --x2: 0; --y: 47%; }
.inside__scene .tactile li:nth-child(5) { --x: 2%; --y: 62%; }
.inside__scene .tactile li:nth-child(6) { --x2: 0; --y: 64%; }
.inside__scene .tactile li:nth-child(7) { --x: 0; --y: 92%; }
.inside__scene .tactile li:nth-child(8) { --x2: 0; --y: 90%; }

/* Astro and Nova: the programme guides */
.guides__title { max-width: 18ch; }
/* Astro and Nova at the Launchpad spaceport, beside the section title. */
.guides__art { display: block; width: 100%; max-width: 560px; height: auto; margin: clamp(24px, 4vw, 40px) auto 0; }
.guides__copy { margin-top: clamp(24px, 3vw, 40px); }
.guides__beat { margin-top: .6em; font: 700 var(--fs-accent)/1.15 var(--font-accent); color: var(--navy); }
/* Not a quotation from anyone, so no quote marks and no cite: it is the feeling the
   guides are there to create, set off from the sentence that introduces it. */
.guides__pull { margin-top: 1.1em; padding-left: 18px; border-left: 2px solid var(--gold); font: 700 var(--fs-accent)/1.15 var(--font-accent); color: var(--navy); max-width: 26ch; }
.guides__close { margin-top: clamp(36px, 4.5vw, 64px); padding-top: clamp(20px, 2.5vw, 32px); border-top: 1px solid var(--line-strong); font: 700 var(--fs-accent)/1.15 var(--font-accent); color: var(--navy); max-width: 30ch; }

/* Observed experience */
.quote { margin: 0; }
.quote p { max-width: 40ch; padding-left: 18px; border-left: 3px solid var(--gold); font-style: italic; font-weight: 600; color: var(--navy); }
.quote cite { display: block; margin-top: 16px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); font-style: normal; }

/* 10. Inner pages --------------------------------------------------------- */
.page-head { padding-block: clamp(40px, 6vw, 96px) clamp(32px, 5vw, 72px); position: relative; overflow: hidden; }
.page-head h1 { max-width: 14ch; }
.page-head .lead { margin-top: clamp(20px, 3vw, 36px); }
.page-head__art { display: block; width: min(80%, 420px); height: auto; margin: clamp(20px, 4vw, 32px) auto 0; }
.page-head--schools > .grid > .lead { max-width: none; text-align: justify; hyphens: auto; -webkit-hyphens: auto; }
.prose h2 { margin-top: 1.6em; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: 1.5em; }
.prose ul { margin-top: .6em; }
.prose li + li { margin-top: .35em; }
.aside-note { border-top: 1px solid var(--line-strong); padding-top: 18px; }
.aside-note .kicker { margin-bottom: 10px; }

/* Programmes page */
.programme + .programme { margin-top: clamp(56px, 8vw, 112px); }
.programme__meta { border-top: 1px solid var(--line-strong); padding-top: 18px; }
.programme__meta dl { margin: 0; }
.programme__meta dt { font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); margin-top: 16px; }
.programme__meta dt:first-child { margin-top: 0; }
.programme__meta dd { margin: 4px 0 0; }
.develops { columns: 2; column-gap: var(--gap); margin-top: .6em; padding-left: 1.1em; }
.develops li { break-inside: avoid; }

/* Approach page */
.principles { counter-reset: principle; }
.principle { position: relative; padding: clamp(28px, 4vw, 44px) 0; border-top: 1px solid var(--line); }
.principle:first-child { border-top: 0; padding-top: 0; }
.principle__photo { display: block; width: 100%; max-width: 480px; height: auto; margin: 18px 0 22px; border-radius: 16px; box-shadow: 0 18px 36px -22px rgba(11, 25, 56, .5); }
.principle__num { font: 700 clamp(2.2rem, 1.6rem + 2.4vw, 4rem)/.9 var(--font-display); color: transparent; -webkit-text-stroke: 1px var(--navy); letter-spacing: -.03em; }
@supports not (-webkit-text-stroke: 1px #000) { .principle__num { color: var(--navy); } }

/* About us */
.founder + .founder { margin-top: clamp(64px, 9vw, 128px); }
.founder__name { max-width: 12ch; }
/* Both founders' names stay on one line on wide screens (user, 2026-10-05). */
@media (min-width: 900px) { .founder__name--one-line { max-width: none; white-space: nowrap; } }
/* "Nathalie Devenish-Doman" is too long for its column between 900 and ~1400px at
   the full heading size, so it scales with the viewport there instead of wrapping. */
@media (min-width: 900px) and (max-width: 1399px) { .founder__name--long { font-size: 3.7vw; } }
/* The name follows its role line directly; `.prose h2` spacing is for headings inside body copy. */
.prose .kicker + .founder__name { margin-top: 0; }
.founder__role { margin-top: 12px; }
.founder__books { margin-top: 20px; font: 700 var(--fs-accent)/1.15 var(--font-accent); color: var(--purple); max-width: 34ch; }
.portrait { position: relative; aspect-ratio: 4 / 5; background: var(--paper); clip-path: polygon(0 6%, 100% 0, 96% 100%, 4% 94%); display: grid; place-items: center; }
.portrait img { width: 100%; height: 100%; object-fit: cover; }
.portrait__initial { position: relative; z-index: 1; font: 700 clamp(6rem, 4rem + 8vw, 12rem)/1 var(--font-display); color: transparent; -webkit-text-stroke: 1.5px var(--navy); }
.portrait__note { margin-top: 12px; color: var(--ink); }
/* About: the founders' shared why, a navy statement after their two stories. */
.why__title { max-width: 18ch; }
.why__copy { margin-top: clamp(24px, 3vw, 40px); }
.why__copy p { max-width: 56ch; }
.why__art { display: block; width: min(100%, 520px); height: auto; margin: clamp(28px, 4vw, 40px) auto 0; }
.on-navy .why__welcome { padding-left: 18px; border-left: 3px solid var(--gold); font-weight: 600; }
.creed { padding-block: clamp(48px, 7vw, 96px); }
.creed p { max-width: 40ch; }

/* Contact */
.paths { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); row-gap: 40px; }
.path { position: relative; padding-top: 22px; border-top: 2px solid var(--navy); }
.path h2 { font-size: clamp(1.6rem, 1.3rem + 1.4vw, 2.4rem); }
.path__kicker { margin-top: 1.6em; }
.path__options { list-style: none; padding: 0; margin: 20px 0 0; display: flex; flex-direction: column; gap: 6px; }
.path__options li { display: flex; gap: 12px; align-items: baseline; }
.path__options li::before { content: "—"; color: var(--coral); }
.channels { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); row-gap: 28px; }
.channel { border-top: 1px solid var(--line-strong); padding-top: 18px; }
/* Sized to fit the revealed value: hello@starboundreading.co.za is one long unbreakable
   token, and at the old display size it ran out of its 4-column box and printed over
   the next column between roughly 720 and 1300px. */
.channel .contact-link { display: block; font: 600 var(--fs-body)/1.4 var(--font-text); color: var(--navy); overflow-wrap: anywhere; }
.channel .contact-link .contact-value { text-decoration-thickness: 2px; }
/* :not(.kicker) so the label keeps the site-wide kicker scale instead of 0.95rem. */
.channel > p:not(.kicker) { margin-top: 10px; }
.channel .place { font-weight: 600; color: var(--navy); }

/* 404 */
.lost { padding-block: clamp(64px, 10vw, 140px); position: relative; overflow: hidden; }


/* Inner-page heads: kicker + h1 left, lead (or story) right and lower */
.page-head__top { grid-column: 1 / -1; }
.page-head__story .lead { margin-bottom: 1em; }
.page-head__story p { max-width: 58ch; }
.programme__sketch { width: clamp(90px, 9vw, 130px); color: var(--navy); margin-bottom: 20px; }
.programme .display-l { max-width: 16ch; }

/* Programmes page: the full journey as an editorial route list */
.route { list-style: none; margin: clamp(32px, 5vw, 64px) 0 0; padding: 0; border-top: 2px solid var(--navy); }
.route__stop { position: relative; padding: clamp(20px, 3vw, 32px) 0; border-bottom: 1px solid var(--line); }
.route__num { font: 700 clamp(1.8rem, 1.4rem + 1.6vw, 3rem)/.9 var(--font-display); color: transparent; -webkit-text-stroke: 1px var(--navy); letter-spacing: -.03em; }
@supports not (-webkit-text-stroke: 1px #000) { .route__num { color: var(--navy); } }
.route__name { margin-top: 10px; }
.route__title { display: block; font: 700 clamp(1.4rem, 1.2rem + 1vw, 2.1rem)/1.1 var(--font-display); color: var(--navy); }
.route__grade { display: block; margin-top: 6px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); }
.route__desc { margin-top: 12px; max-width: 44ch; }
.route__status { display: inline-flex; align-items: center; margin-top: 12px; color: var(--navy); }
.route__star { width: 14px; height: 14px; }
.notsure__title { max-width: 18ch; }
.notsure__copy { margin-top: clamp(24px, 3vw, 40px); }
.notsure__copy p { max-width: 46ch; }

/* Approach page */
.principles { list-style: none; margin: 0; padding: 0; }
.training .display-l { max-width: 16ch; }
.training__aside { border-top: 1px solid var(--line-on-navy); padding-top: 24px; margin-top: 32px; }
.training__aside-kicker { margin-top: 28px; }

/* About us: closing statement */
.creed__title { max-width: 18ch; }
.creed__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 28px; margin-top: 28px; }

/* Contact: guidance */
.include__text h2 { max-width: 18ch; }
.include__note { margin-top: 32px; }

/* 11. Responsive ----------------------------------------------------------- */
/* Mobile-first: grids stack. Compositions switch on at 720 and 900. */
.grid > * { grid-column: 1 / -1; }
.hero__copy { margin-top: clamp(32px, 6vw, 48px); }
.hero__word { display: block; width: max-content; max-width: 100%; }
.stations { --path-h: 0px; display: block; padding-left: 28px; border-left: 2px solid var(--navy); }
.stations::before { display: none; }
.station { padding: 0 0 26px; }
.station__dot { position: absolute; left: -38px; top: 4px; margin: 0; }
.station:last-child { padding-bottom: 0; }
.stations .station__desc { max-width: 40ch; }
.footer-brand, .footer-nav, .footer-contact { grid-column: 1 / -1; }
.footer-brand img { height: 104px; }
  img.footer-lockup { height: clamp(190px, 46vw, 240px); }
.paths > li, .channels > * { grid-column: 1 / -1; }
.develops { columns: 1; }

@media (max-width: 899px) {
  .masthead { min-height: 68px; }
  .brand-mark { height: 32px; }
  .brand-word { height: 28px; }
  .nav-toggle {
    display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 10px 8px; background: transparent; border: 0;
    font: 700 .8rem/1 var(--font-display); letter-spacing: .16em; text-transform: uppercase; color: var(--navy); cursor: pointer;
  }
  .nav-toggle-label { position: static !important; width: auto; height: auto; margin: 0; clip: auto; overflow: visible; }
  .nav-toggle-lines { position: relative; width: 24px; height: 2px; background: currentColor; display: block; transition: background var(--fast) var(--ease); }
  .nav-toggle-lines::before, .nav-toggle-lines::after { content: ""; position: absolute; left: 0; width: 24px; height: 2px; background: currentColor; transition: transform var(--fast) var(--ease); }
  .nav-toggle-lines::before { top: -7px; }
  .nav-toggle-lines::after { top: 7px; }
  .nav-toggle[aria-expanded="true"] { position: relative; z-index: 60; color: #fff; }
  .nav-toggle[aria-expanded="true"] .nav-toggle-lines { background: transparent; }
  .nav-toggle[aria-expanded="true"] .nav-toggle-lines::before { transform: translateY(7px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] .nav-toggle-lines::after { transform: translateY(-7px) rotate(-45deg); }
  .site-nav { position: fixed; inset: 0; z-index: 55; background: var(--navy); color: #fff; flex-direction: column; align-items: flex-start; justify-content: flex-start; gap: 0; padding: 96px var(--gutter) 40px; overflow-y: auto; overscroll-behavior: contain; }
  html.has-js .site-nav:not([data-open="true"]) { display: none; }
  html:not(.has-js) .site-nav { position: static; inset: auto; background: transparent; color: var(--navy); flex-direction: row; flex-wrap: wrap; gap: 8px 22px; padding: 0 0 14px; width: 100%; justify-content: flex-start; }
  html:not(.has-js) .masthead { flex-wrap: wrap; }
  html:not(.has-js) .nav-toggle { display: none; }
  .site-nav a { color: inherit; font: 700 clamp(1.9rem, 6vw, 2.6rem)/1.15 var(--font-display); padding: 10px 0; }
  html:not(.has-js) .site-nav a { font: 600 1rem/1 var(--font-text); }
  .site-nav a .mark--underline { color: var(--gold); bottom: 2px; height: .32em; }
  .site-nav .nav-contact { margin: 28px 0 0; padding: .9em 1.4em; background: var(--teal); border-color: var(--teal); color: var(--navy); font: 700 1rem/1 var(--font-display); }
  html.has-js .site-nav .nav-contact:hover { background: #fff; border-color: #fff; color: var(--navy); }
  html:not(.has-js) .site-nav .nav-contact { margin: 0; font-size: .95rem; }
  .site-nav__foot { margin-top: auto; padding-top: 32px; font: 700 var(--fs-accent)/1.15 var(--font-accent); color: rgba(255, 255, 255, .8); display: flex; align-items: center; gap: 12px; }
  html:not(.has-js) .site-nav__foot { display: none; }
  body.menu-open { overflow: hidden; }
}

@media (min-width: 720px) {
  /* 720-899px wraps the six stations 3 + 3, and a single rising arc cannot thread a
     wrapped grid. The arc and its offsets only come back at 900px, where all six
     stations share one row. */
  .stations { --path-h: 0px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 40px; padding-left: 0; border-left: 0; }
  .stations::before { display: none; }
  .station { padding: 0; }
  .station__dot { position: static; margin: 0 0 14px; }
  .footer-brand { grid-column: 1 / 7; }
  .footer-nav { grid-column: 7 / 10; }
  .footer-nav--b { grid-column: 10 / 13; }
  .footer-contact { grid-column: 1 / 7; }
  .paths > li { grid-column: span 6; }
  .channels > * { grid-column: span 4; }
  .develops { columns: 2; }
}

@media (min-width: 900px) {
  .site-nav__foot { display: none; }
  .hero__word { display: inline-block; width: auto; }
  .hero__kicker { grid-column: 1 / -1; grid-row: 1; }
  .hero__title { grid-column: 1 / 8; grid-row: 2; align-self: center; }
  .hero__art { grid-column: 7 / 13; grid-row: 1 / span 2; align-self: center; justify-self: end; width: 88%; margin: 0; }
  /* Left-aligned under the headline (user, 2026-10-01): one reading edge from the title
     down through the copy, and no dead space beside it. Line length is held by the
     58ch cap on its paragraphs. */
  .hero__copy { grid-column: 1 / -1; grid-row: 3; margin-top: clamp(32px, 4vw, 56px); }
  /* One block, edge to edge across the page (user, 2026-10-01). */
  .hero__text p { max-width: none; }

  .origin .chapter__head { grid-column: 1 / -1; }
  .origin__lead { grid-column: 1 / 6; }
  .origin__copy { grid-column: 7 / 13; margin-top: 0; }


  .journey__intro { grid-column: 1 / 8; }
  .journey__path { grid-column: 1 / -1; }
  /* The arc starts just under the heading: its low left end sits below "Welcome to the
     Starbound universe." and the rising right end climbs into the empty columns beside
     it (the heading stops at column 8). */
  .journey .stations { margin-top: calc(var(--path-h) * -.3); }
  .journey__copy { grid-column: 1 / -1; }
  .stations { --path-h: clamp(140px, 16vw, 220px); grid-template-columns: repeat(6, minmax(0, 1fr)); row-gap: 0; }
  .stations::before { display: block; }
  .station { padding: calc(var(--path-h) * var(--y) - 9px) 0 0; }

  .challenge__lead { grid-column: 1 / 6; }
  .challenge__copy { grid-column: 7 / 13; margin-top: clamp(16px, 3vw, 48px); }
  .journey .caps { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(32px, 5vw, 80px); align-items: start; }

  .inside__window { grid-column: 1 / -1; }
  .inside__copy { grid-column: 1 / 7; }
  /* The photo starts level with the opening line, a little left of the far edge. */
  .inside__aside { grid-column: 7 / 13; grid-row: 3; margin-top: clamp(24px, 3vw, 40px); }
  .inside__copy { grid-row: 3; }

  .guides .chapter__head { grid-column: 1 / -1; }
  .guides__title { grid-column: 1 / 8; grid-row: 2; }
  .guides__art { grid-column: 7 / 13; grid-row: 2; align-self: end; margin: 0; }
  /* Both columns start level, and the closing line and button follow straight on under
     the left column instead of waiting below the longer right one (user, 2026-10-01).
     The last 1fr row soaks up whichever side is taller. */
  .guides > .grid { grid-template-rows: auto auto auto auto auto 1fr; }
  .guides__copy--a { grid-column: 1 / 7; grid-row: 3; }
  .guides__copy--b { grid-column: 8 / 13; grid-row: 3 / 7; }
  .guides__close { grid-column: 1 / 7; grid-row: 4; }
  .guides__actions { grid-column: 1 / 7; grid-row: 5; }

  .observed__copy { grid-column: 1 / 7; }
  .observed__art { grid-column: 8 / 13; grid-row: 1; align-self: center; margin: 0; }
  .quote { grid-column: 1 / 8; margin-top: clamp(32px, 5vw, 56px); }

  .page-head__top { grid-column: 1 / 9; }
  .page-head > .grid > .lead, .page-head__story { grid-column: 7 / 13; margin-top: clamp(40px, 6vw, 96px); }
  /* For Schools: the intro runs edge to edge under the headline, justified, as in the
     home hero (user, 2026-10-01). */
  .page-head--schools > .grid > .lead { grid-column: 1 / -1; margin-top: clamp(28px, 4vw, 48px); }
  /* Reviews: the line sits under "Little Readers. Big Strides.", left-aligned (user, 2026-10-05). */
  .page-head--voices > .grid > .lead { grid-column: 1 / 9; margin-top: clamp(20px, 3vw, 36px); }
  .page-head--voices .page-head__top { grid-row: 1; }
  .page-head--voices .voices-head__art { grid-column: 9 / 13; grid-row: 1 / span 2; align-self: center; margin: 0; }
  /* For Schools: Astro and Nova beside the headline (user, 2026-10-01). */
  .page-head--schools .page-head__top { grid-row: 1; }
  .page-head--schools .page-head__art { grid-column: 8 / 12; grid-row: 1; align-self: center; width: 100%; margin: 0; }
  .why__kicker, .why__title { grid-column: 1 / 10; }
  .why__copy { grid-column: 7 / 13; grid-row: 3; }
  /* Beside the copy, in the columns it leaves empty (user, 2026-10-05). */
  .why__art { grid-column: 1 / 7; grid-row: 3; align-self: center; width: 100%; margin: clamp(24px, 3vw, 40px) 0 0; }
  /* Our approach: the head carries the whole approach since 2026-10-03, so its copy
     follows the headline closely instead of leaving a dead block beside it. */
  .page-head--approach .page-head__top { grid-column: 1 / 9; }
  .page-head--approach .page-head__story { grid-column: 6 / 13; grid-row: 2; margin-top: clamp(28px, 3.5vw, 56px); }
  /* Astro and Nova in the empty columns beside the copy (Approach, Launchpad, Boost,
     Mission Control; user, 2026-10-05), level with the copy's first line. */
  .page-head__art--side { grid-column: 1 / 6; grid-row: 2; align-self: start; width: 100%; max-width: 480px; margin: clamp(40px, 6vw, 96px) 0 0; }
  .page-head--approach .page-head__art--side { grid-column: 1 / 5; margin-top: clamp(28px, 3.5vw, 56px); }
  .prose { grid-column: 1 / 8; }
  .prose--right { grid-column: 5 / 12; }
  .aside-note { grid-column: 9 / 13; }
  .programme .chapter__head { grid-column: 1 / -1; }
  .programme__body { grid-column: 1 / 8; }
  .programme__meta { grid-column: 9 / 13; margin-top: clamp(24px, 4vw, 64px); }
  .programme__meta--left { grid-column: 1 / 4; grid-row: 2; }
  .programme__body--right { grid-column: 5 / 12; grid-row: 2; }
  .journey-full__intro { grid-column: 1 / 8; }
  .route { grid-column: 1 / -1; }
  .route__stop { display: grid; grid-template-columns: 90px 1.1fr 1.6fr .8fr; column-gap: var(--gap); align-items: start; }
  .route--unnumbered .route__stop { grid-template-columns: 1.1fr 1.6fr .8fr; }
  .route__name, .route__desc, .route__status { margin-top: 6px; }
  .notsure__title { grid-column: 1 / 9; }
  .notsure__copy { grid-column: 7 / 13; }
  .training__main { grid-column: 1 / 8; }
  /* Top-aligned with "Our training" (user, 2026-10-05); it used to start lower. */
  .training__aside { grid-column: 9 / 13; align-self: start; border-top: 0; border-left: 1px solid var(--line-on-navy); padding: 0 0 0 var(--gap); margin-top: 0; }
  .creed__kicker { grid-column: 3 / 11; }
  .creed__title { grid-column: 3 / 11; }
  .creed__actions { grid-column: 3 / 11; }
  .include__text { grid-column: 1 / 8; }
  .include__note { grid-column: 9 / 13; margin-top: clamp(32px, 5vw, 80px); }
  .principle { display: grid; grid-template-columns: 110px 1fr 1fr; column-gap: var(--gap); }
  .principle__num { grid-column: 1; }
  .principle > h2 { grid-column: 2; max-width: 14ch; }
  .principle > div { grid-column: 3; }
  /* With a photo: it sits under the heading, the text runs beside both. */
  .principle--photo { grid-template-rows: auto 1fr; }
  .principle--photo > :is(.principle__num, h2) { grid-row: 1; }
  .principle--photo > div { grid-row: 1 / 3; }
  .principle--photo .principle__photo { grid-column: 2; grid-row: 2; margin: 24px 0 0; }
  .founder--a .founder__text { grid-column: 1 / 8; }
  .founder--a .founder__figure { grid-column: 9 / 13; margin-top: clamp(24px, 4vw, 64px); }
  .founder--b .founder__figure { grid-column: 1 / 5; order: 0; }
  .founder--b .founder__text { grid-column: 6 / 13; order: 1; margin-top: clamp(24px, 4vw, 64px); }
  .paths > li { grid-column: span 5; }
  .paths > li:nth-child(2) { grid-column: 7 / 13; }
  .paths > li { grid-column: span 6; }
  .channels > * { grid-column: span 4; }
  .lost__text { grid-column: 1 / 8; }
}

@media (min-width: 1120px) {
  .hero__title { grid-column: 1 / 8; }
}

/* 12. Motion and preferences ------------------------------------------------- */
/* Everything here is enhancement, and all of it sits inside prefers-reduced-motion:
   no-preference. With reduced motion requested nothing moves and every element renders
   in its final state; without JS nothing is ever hidden (every hidden starting state
   needs html.has-js, and scroll-triggered ones also need a class site.js only adds to
   elements that are still below the fold, so nothing on screen ever flashes). Only
   opacity, transforms and clip-path animate, which the compositor handles without
   repainting the page. */
/* Big screens: the UFO hovers beside "adventure" (there is room to its right from
   1200px), its beam falling towards the photo; the one on the photo steps aside. Rows
   are set outright because the UFO shares the word's row. */
@media (min-width: 1200px) {
  .inside .chapter__head { grid-row: 1; }
  .inside__window { grid-row: 2; }
  .inside__sky { display: block; position: relative; z-index: 1; grid-column: 10 / 13; grid-row: 2 / 4; justify-self: end; align-self: start; width: clamp(150px, 12vw, 200px); margin-top: .5vw; }
  .inside__sky .inside__ufo { display: block; width: 100%; height: auto; rotate: -8deg; }
  .inside__sky::after {
    content: ""; position: absolute; z-index: -1; top: 62%; left: -10%; width: 75%; height: 190%; pointer-events: none;
    clip-path: polygon(62% 0, 82% 0, 45% 100%, 0 88%);
    background: linear-gradient(195deg, rgba(255, 198, 100, .55), rgba(255, 198, 100, .12) 70%, rgba(255, 198, 100, 0));
  }
  .inside__scene .inside__ufo, .inside__beam { display: none; }
}
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes drift { 0%, 100% { translate: 0 0; rotate: 0deg; } 50% { translate: 6px -12px; rotate: -1.2deg; } }
@keyframes beam { 0%, 100% { opacity: .75; } 50% { opacity: 1; } }
@keyframes rise { from { opacity: 0; translate: 0 .55em; } to { opacity: 1; translate: none; } }
@keyframes pulse-ring { 0% { box-shadow: 0 0 0 0 rgba(255, 159, 28, .6); } 70%, 100% { box-shadow: 0 0 0 13px rgba(255, 159, 28, 0); } }
@keyframes twinkle { 0%, 100% { opacity: 1; } 50% { opacity: .18; } }
@keyframes shoot {
  0% { opacity: 0; translate: 0 0; }
  2% { opacity: 1; }
  9% { opacity: 0; translate: 38vw -12.3vw; }
  100% { opacity: 0; translate: 38vw -12.3vw; }
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }

  /* The sky: two star layers twinkling out of phase, paused while off screen */
  .sky::before { animation: twinkle 2.6s ease-in-out infinite; }
  .sky::after { animation: twinkle 4s ease-in-out -1.4s infinite; }
  /* Pushed a second time: well under half the first build's cycle lengths, so a streak
     crosses an open sky every couple of seconds instead of every three. Six variants
     (site.js assigns up to three per sky) keep several streaks on screen at once
     without two ever following the same line at the same moment. */
  .ss-1 { animation: shoot 6.2s var(--ease) 1.2s infinite; }
  .ss-2 { animation: shoot 7.6s var(--ease) 3.4s infinite; }
  .ss-3 { animation: shoot 9.2s var(--ease) 2s infinite; }
  .ss-4 { animation: shoot 7s var(--ease) 4.6s infinite; }
  .ss-5 { animation: shoot 8.4s var(--ease) .6s infinite; }
  .ss-6 { animation: shoot 6.8s var(--ease) 5.2s infinite; }
  /* Nothing animates on a sky that is off screen: the layers and the streaks hold
     until it comes back. */
  html.has-js .sky:not(.is-live)::before, html.has-js .sky:not(.is-live)::after,
  html.has-js .sky:not(.is-live) .shooting-star { animation-play-state: paused; }

  /* Hero: the words rise in turn, then the copy */
  html.has-js .hero__kicker { animation: rise 540ms var(--ease) 45ms both; }
  html.has-js .hero__title .w { animation: rise 650ms var(--ease) both; }
  .hero__title .w1 { animation-delay: 120ms; }
  .hero__title .w2 { animation-delay: 220ms; }
  .hero__title .w3 { animation-delay: 320ms; }
  .hero__title .w4 { animation-delay: 440ms; }
  html.has-js .hero__copy { animation: rise 650ms var(--ease) 760ms both; }
  /* The hero image arrives with the headline, then drifts gently, as if in flight. */
  html.has-js .hero__art { animation: rise 700ms var(--ease) 300ms both, drift 5s ease-in-out 1s infinite; }
  html.has-js .hero.sky:not(.is-live) .hero__art { animation-play-state: paused; }
  /* Page heads: copy rises in */
  html.has-js .page-head .shell > *, html.has-js .lost .shell > * { animation: rise 650ms var(--ease) 60ms both; }
  html.has-js .page-head .shell > :nth-child(2), html.has-js .lost .shell > :nth-child(2) { animation-delay: 200ms; }
  html.has-js .page-head .shell > :nth-child(3) { animation-delay: 320ms; }

  /* The journey: the arc draws across the sky and the six stations light up in turn,
     each as the line reaches it. Running programmes keep a slow gold pulse. */
  /* Transitions live only on the revealed state: hiding is instant (the element is off
     screen), and only the reveal animates. Put them on the armed state instead and the
     staggered delays would be spent fading OUT, so a quick scroll would find nothing
     left to reveal. */
  html.has-js .stations.is-armed::before { clip-path: inset(0 100% 0 0); }
  /* Drawn at constant speed, so each station can be timed to the moment the line reaches
     its column: 150ms + 1400ms x column position (0, .17, .35, .52, .69, .86). */
  html.has-js .stations.is-armed.is-in::before { clip-path: inset(0 0 0 0); transition: clip-path 1400ms linear 150ms; }
  html.has-js .stations.is-armed > .station { opacity: 0; translate: 0 14px; }
  html.has-js .stations.is-armed.is-in > .station { opacity: 1; translate: none; transition: opacity 500ms var(--ease), translate 580ms var(--ease); transition-delay: calc(var(--i) * 240ms + 165ms); }
  .station--live .station__dot { animation: pulse-ring 2.1s ease-out 2s infinite; }

  /* Scroll reveals: blocks and list items rise in as they enter the viewport; items
     that sit side by side get a small stagger so they do not arrive as one slab */
  html.has-js .reveal { opacity: 0; translate: 0 28px; }
  html.has-js .reveal.is-in { opacity: 1; translate: none; transition: opacity 520ms var(--ease), translate 620ms var(--ease); transition-delay: var(--d, 0ms); }
  :is(.paths, .channels, .gains__list) > .reveal:nth-child(2) { --d: 80ms; }
  :is(.paths, .channels, .gains__list) > .reveal:nth-child(3) { --d: 160ms; }
  :is(.paths, .channels, .gains__list) > .reveal:nth-child(n+4) { --d: 240ms; }

  /* The hand-drawn marks draw themselves as their passage arrives, the way a hand would
     draw them: the underline under 81%, the circle around "educator", the arrows from
     sound to somewhere new, the notebook sketches. pathLength="100" on every mark path
     (templates/_marks.html) makes one rule enough, whatever the path's real length. The
     header's underline sits outside any revealed block, so it still fades in on hover. */
  html.has-js .reveal.is-in .mark path { stroke-dasharray: 100; stroke-dashoffset: 100; animation: draw 650ms var(--ease) 150ms forwards; }
  html.has-js .reveal.is-in .mark path + path { animation-delay: 380ms; }

  /* Inside Starbound: the words a session is made of arrive one after another */
  html.has-js .reveal.is-in .tactile li { animation: rise 500ms var(--ease) both; animation-delay: calc(var(--n) * 65ms + 260ms); }
  /* The UFO hovers over the photo and its beam breathes with it. */
  .inside__ufo { animation: drift 4s ease-in-out infinite; }
  .inside__beam, .inside__sky::after { animation: beam 4s ease-in-out infinite; }
  /* Astro and Nova stand still in the "Astro and Nova" and Reviews sections (user,
     2026-10-05): .guides__art and .observed__art no longer drift. */
  .mission__art { animation: drift 4.2s ease-in-out infinite; animation-delay: -.8s; }

  /* The header underline is drawn, not faded: the same hand as the marks in the page */
  .site-nav a .mark--underline path { stroke-dasharray: 100; stroke-dashoffset: 100; transition: stroke-dashoffset 280ms var(--ease); }
  .site-nav a .mark--underline path + path { transition-delay: 65ms; }
  .site-nav a:hover .mark--underline path, .site-nav a:focus-visible .mark--underline path,
  .site-nav a[aria-current="page"] .mark--underline path { stroke-dashoffset: 0; }

  /* Buttons lift toward the light */
  .btn:hover, .site-nav .nav-contact:hover { translate: 0 -2px; }
}
@media (prefers-reduced-motion: reduce) {
  /* Safety net for anything that animates outside the block above */
  *, *::before, *::after { animation-duration: .01ms !important; animation-delay: 0ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}
@media print {
  .sky { background: none; color: #000; }
  .sky::before, .sky::after, .shooting-star { display: none; }
  .reveal, .stations > .station { opacity: 1 !important; translate: none !important; }
}
@media (prefers-contrast: more) {
  :root { --line: rgba(11, 25, 56, .5); --line-strong: rgba(11, 25, 56, .8); }
}
@media (forced-colors: active) {
  .btn, .nav-toggle { forced-color-adjust: none; background: ButtonFace; color: ButtonText; border-color: ButtonText; }
  .site-nav a[aria-current="page"] { text-decoration: underline; text-underline-offset: 6px; }
  .inside__window { color: CanvasText; background: none; }
  .programme__num, .route__num, .principle__num, .portrait__initial { color: CanvasText; }
  .site-footer .seam { display: none; }
  .site-footer { border-top: 1px solid CanvasText; }
}
@media print {
  body { color: #000; }
  .band--navy, .site-footer { background: #fff !important; color: #000 !important; }
  .on-navy, .on-navy h1, .on-navy h2, .on-navy p, .site-footer a { color: #000 !important; }
  .inside__window { color: #000; background: none; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .8em; }
}

/* 13. Pages added with the September 2026 content deck ----------------------
   Focus runs · programme write-ups · fees · Mission Control ·
   policies · parent references. Same vocabulary as above: hairlines, outlined
   numerals, approved palette only. No cards, pills, shadows or gradient panels. */

/* A run of focus areas: reads as a sentence, not a row of chips */
.focus { margin-top: 1.4em; max-width: 56ch; }
.focus__label { display: block; margin-bottom: 8px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); }
.on-navy .focus__label { color: var(--gold); }
.focus__item + .focus__item::before { content: " · "; color: var(--coral); font-weight: 700; padding: 0 .1em; }

/* Programmes page: the six programmes, one identical entry each. Every entry opens on a
   navy rule so the eye sees where one programme ends and the next begins. */
.entry__list { margin-top: 0; }
.entry { padding: clamp(20px, 3vw, 32px) 0 clamp(40px, 5vw, 64px); border-top: 2px solid var(--navy); }
.entry__head { display: grid; grid-template-columns: clamp(170px, 16vw + 40px, 260px) 1fr; column-gap: clamp(16px, 2vw, 28px); align-items: center; }
.entry__head .programme-logo { grid-row: 1; }
/* Programmes page: the logos carry the names, so they are shown ~40% larger than elsewhere. */
.entry__head .programme-logo { width: 100%; height: auto; aspect-ratio: 1; }
.entry h2 { font-size: clamp(1.5rem, 1.25rem + 1.2vw, 2.2rem); }
.entry .kicker { margin-bottom: 10px; }
.entry__summary { grid-column: 1 / -1; margin-top: .6em; font-weight: 600; color: var(--navy); max-width: 44ch; }
.entry__body { margin-top: 1.2em; }
.entry__body > p:first-child { margin-top: 0; }

.curriculum__text h2 { max-width: 18ch; }

/* Programmes page: opens on the programmes themselves (no page head since 2026-10-03),
   with the welcome to neurodivergent readers set off under the heading. */
.programmes__intro { grid-column: 1 / -1; margin-bottom: clamp(28px, 4vw, 48px); }
.programmes__welcome { padding-left: 18px; border-left: 3px solid var(--gold); font-weight: 600; color: var(--navy); max-width: 62ch; }

/* Programmes page fees: one card per programme, logo beside its own table. */
.fee-list { grid-column: 1 / -1; display: grid; gap: clamp(14px, 1.8vw, 22px); }
.fee-card__head { display: flex; align-items: center; gap: 18px; }
.fee-card__head .kicker { margin: 0; }
.fee-card__body { margin-top: 18px; }
.fee-card__lead { font-weight: 600; color: var(--navy); }
.fee-card h4 { margin: clamp(22px, 3vw, 32px) 0 0; font: 700 var(--fs-body)/1.3 var(--font-display); color: var(--navy); }
.fee-card h4 + p { margin-top: .4em; }
.fees__terms { grid-column: 1 / -1; }

/* Launchpad: the three practical answers */
.practical__item { border-top: 1px solid var(--line-strong); padding-top: 18px; }
.practical__item + .practical__item { margin-top: 36px; }
.practical__answer { font-weight: 600; color: var(--navy); max-width: 30ch; }
.practical__answer + p { margin-top: .7em; }
.page-head__pull { margin-top: 1.2em; font-weight: 600; color: var(--purple); max-width: 40ch; }
.page-head__note { margin-top: 1.2em; padding-left: 14px; border-left: 2px solid var(--gold); max-width: 46ch; }

.session__develops { border-top: 1px solid var(--line-strong); padding-top: 18px; margin-top: 40px; }
.session__develops .kicker { margin-bottom: 12px; }
.session__photo { display: block; width: 100%; height: auto; margin: clamp(24px, 3vw, 36px) 0 0; border-radius: 16px; box-shadow: 0 18px 36px -22px rgba(11, 25, 56, .5); }

/* Ways to attend */
.ways { list-style: none; margin: 0; padding: 0; border-top: 2px solid var(--navy); }
.way { padding: clamp(18px, 2.5vw, 28px) 0; border-bottom: 1px solid var(--line); }
.way__name { display: block; font: 700 clamp(1.25rem, 1.1rem + .8vw, 1.7rem)/1.15 var(--font-display); color: var(--navy); }
.way__size { display: block; margin-top: 6px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); }
.way__note { margin-top: 10px; max-width: 46ch; }

/* Fees. Plain editorial table: these are commitments, so they stay legible. */
.rates { width: 100%; border-collapse: collapse; margin-top: 18px; text-align: left; }
.rates th, .rates td { padding: 14px 0; border-bottom: 1px solid var(--line); vertical-align: baseline; }
.rates th { font: 600 var(--fs-body)/1.4 var(--font-text); color: var(--navy); padding-right: var(--gap); width: 34%; }
/* Qualified with td so these beat the `.rates th, .rates td` padding reset above -
   otherwise the gap collapses and the amount runs straight into its note
   ("R912.50 per termPlus the once-off registration fee"). */
.rates td.rates__amount { font: 600 var(--fs-body)/1.4 var(--font-text); color: var(--navy); white-space: nowrap; padding-right: var(--gap); }
.rates td.rates__note { color: var(--ink); padding-left: 0; }
/* On a phone the three columns squeeze the note to ~78px and it rags one word per
   line. Fees are what a parent reads most carefully, so the row stacks instead. */
@media (max-width: 719px) {
  .rates, .rates tbody, .rates tr, .rates th, .rates td { display: block; }
  .rates tr { padding: 16px 0; border-bottom: 1px solid var(--line); }
  .rates th, .rates td { padding: 0; border-bottom: 0; }
  .rates th { width: auto; }
  .rates td.rates__amount { padding-right: 0; margin-top: 4px; white-space: normal; }
  .rates td.rates__note { margin-top: 6px; }
}
.fees__group h3, .fees__private h3 { margin-bottom: .5em; }
.fees__private { margin-top: clamp(40px, 5vw, 72px); }
.fees__caveat { margin-top: 16px; color: var(--ink); }
.fees__basis { margin-bottom: 18px; font-weight: 600; color: var(--navy); }
.fees__note { margin-top: 36px; }
.fees__note-kicker { margin-top: 1.6em; }

.institutions__note { border-top: 1px solid var(--line-on-navy); padding-top: 22px; margin-top: 36px; }

/* Boost page */
.helps__title { max-width: 16ch; }
.helps__scope { margin-top: 36px; }
.steps { list-style: none; margin: 0; padding: 0; border-top: 2px solid var(--navy); }
.step { padding: clamp(20px, 3vw, 34px) 0; border-bottom: 1px solid var(--line); }
.step__num { display: block; font: 700 clamp(1.6rem, 1.3rem + 1.2vw, 2.4rem)/1 var(--font-display); color: var(--purple); letter-spacing: .02em; }
.step h3 { margin-top: 10px; }
.step p { margin-top: .6em; max-width: 52ch; }

/* For parents: three ways to start */
.options { list-style: none; margin: clamp(28px, 4vw, 48px) 0 0; padding: 0; border-top: 2px solid var(--navy); }
.option { padding: clamp(24px, 3.5vw, 40px) 0; border-bottom: 1px solid var(--line); }
.option :is(h2, h3) { margin-top: 0; font-size: clamp(1.5rem, 1.25rem + 1.2vw, 2.2rem); }
.option__who { margin-top: .5em; font-weight: 600; color: var(--purple); max-width: 40ch; }
.option__who + p { margin-top: .7em; }
.option .actions { margin-top: 24px; }

.plain { list-style: none; padding: 0; margin: 0 0 1em; }
.plain li { display: flex; gap: 12px; align-items: baseline; }
.plain li::before { content: "—"; color: var(--coral); }
.honest__text h2 { max-width: 14ch; }
.honest__art { display: block; width: min(80%, 380px); height: auto; margin: clamp(28px, 4vw, 40px) auto 0; }

/* For schools */
.gains__list { list-style: none; margin: 0; padding: 0; border-top: 2px solid var(--navy); }
.gains__list li { padding: clamp(14px, 2vw, 22px) 0; border-bottom: 1px solid var(--line); font-weight: 600; color: var(--navy); }
/* Session photos under the list. Phones: two rows of two (the near-square pair, then
   the wide one beside the tall one), each photo's width its share of its row's aspect
   ratios so both in a row stand the same height. From 600px: one row, shared the same
   way. Nothing is cropped. */
.gains__photos { --g: clamp(10px, 1.4vw, 18px); grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: var(--g); margin-top: clamp(32px, 4.5vw, 64px); }
.gains__photos img { display: block; min-width: 0; height: auto; border-radius: 16px; box-shadow: 0 18px 36px -22px rgba(11, 25, 56, .5); }
.gains__photos img:nth-child(1) { flex: 0 0 calc((100% - var(--g)) * .4983); }
.gains__photos img:nth-child(2) { flex: 0 0 calc((100% - var(--g)) * .5017); }
.gains__photos img:nth-child(3) { flex: 0 0 calc((100% - var(--g)) * .6495); }
.gains__photos img:nth-child(4) { flex: 0 0 calc((100% - var(--g)) * .3505); }
@media (min-width: 600px) {
  .gains__photos { flex-wrap: nowrap; }
  .gains__photos img:nth-child(1) { flex: 1.0273 1 0; }
  .gains__photos img:nth-child(2) { flex: 1.0344 1 0; }
  .gains__photos img:nth-child(3) { flex: 1.1504 1 0; }
  .gains__photos img:nth-child(4) { flex: .6208 1 0; }
}
.hosting__meta { margin-top: 36px; }
/* Scoped with .on-navy so these beat `.on-navy p`, which otherwise forces them to full
   white and flattens the disclaimer into the claim it is qualifying. */
.on-navy .heard__caveat { margin-top: 1em; color: rgba(255, 255, 255, .72); }

/* Mission Control */
.topics { list-style: none; margin: clamp(28px, 4vw, 48px) 0 0; padding: 0; border-top: 2px solid var(--navy); }
.topic { padding: clamp(16px, 2.2vw, 26px) 0; border-bottom: 1px solid var(--line); }
.topic__num { display: block; font: 700 1.1rem/1 var(--font-display); color: var(--purple); letter-spacing: .04em; }
.topic__title { margin-top: 8px; font-size: clamp(1.25rem, 1.1rem + .9vw, 1.8rem); }
.topic__summary { margin-top: 6px; max-width: 52ch; }
/* Written topics (2026-10-03): a preview, then the rest under "Read more". */
.topic__time { margin-top: 10px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); }
.topic__body { margin-top: 18px; }
.topic__body p { max-width: 62ch; }
.topic__more { margin-top: 1em; }
.topic__more > summary { display: inline-flex; align-items: center; gap: 8px; list-style: none; cursor: pointer; padding: 6px 0; font: 700 var(--fs-body)/1.3 var(--font-display); color: var(--navy); text-decoration: underline; text-decoration-color: var(--coral); text-decoration-thickness: 2px; text-underline-offset: 5px; }
.topic__more > summary::-webkit-details-marker { display: none; }
.topic__more > summary::after { content: ""; width: .5em; height: .5em; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform var(--fast) var(--ease); }
.topic__more[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.topic__more > summary:hover { color: var(--purple); }
.topic__close, .topic__more[open] .topic__open { display: none; }
.topic__more[open] .topic__close { display: inline; }
.topic__more[open] > summary { margin-bottom: .4em; }
.topic__more h4 { margin: 1.6em 0 0; font: 700 var(--fs-body)/1.3 var(--font-display); color: var(--navy); }
.topic__more h4 + p { margin-top: .4em; }
.topic__cta { margin-top: 1.6em; font-weight: 600; color: var(--navy); }
.topic__more .actions { margin-top: 18px; }
.heard__aside { border-top: 1px solid var(--line-on-navy); padding-top: 22px; margin-top: 36px; }
.heard__text p { max-width: 54ch; }

/* Enrolment and policies */
.policies { list-style: none; margin: 0; padding: 0; }
.policy { padding: clamp(26px, 3.5vw, 44px) 0; border-top: 1px solid var(--line); }
.policy:first-child { border-top: 0; padding-top: 0; }
.policy__num { display: block; font: 700 clamp(1.8rem, 1.4rem + 1.6vw, 3rem)/.9 var(--font-display); color: transparent; -webkit-text-stroke: 1px var(--navy); letter-spacing: -.03em; }
@supports not (-webkit-text-stroke: 1px #000) { .policy__num { color: var(--navy); } }
.policy h3 { margin-top: 10px; }
.policy__body { margin-top: .8em; }
.policy__body p { max-width: 62ch; }

/* Parent voices (only ever rendered once consent is confirmed) */
.voices__list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); row-gap: 36px; }
.voice { grid-column: 1 / -1; border-top: 1px solid var(--line-strong); padding-top: 20px; }
.voice blockquote { margin: 0; }
.voice p { font-style: italic; color: var(--navy); max-width: 46ch; }
.voice cite { display: block; margin-top: 14px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); font-style: normal; }
.voices__more { margin-top: clamp(28px, 4vw, 44px); }
.voices__list { margin-top: clamp(32px, 4vw, 56px); }
/* The line that introduces the quotes, so it reads as a lead-in rather than body copy. */
.observed__intro { margin-top: 1.4em; font-weight: 600; color: var(--navy); }
/* Astro and Nova at the observatory, beside the reviews' introduction. */
.observed__art { display: block; width: 100%; max-width: 520px; height: auto; margin: clamp(28px, 4vw, 40px) auto 0; }

.references { list-style: none; margin: 0; padding: 0; }
.reference { padding: clamp(28px, 4vw, 52px) 0; border-top: 1px solid var(--line); }
.reference:first-child { border-top: 0; padding-top: 0; }
.reference__num { display: block; font: 700 clamp(1.8rem, 1.4rem + 1.6vw, 3rem)/.9 var(--font-display); color: transparent; -webkit-text-stroke: 1px var(--navy); letter-spacing: -.03em; }
@supports not (-webkit-text-stroke: 1px #000) { .reference__num { color: var(--navy); } }
.reference__quote { margin: 14px 0 0; }
.reference__quote p { max-width: 58ch; }
.reference__quote p + p { margin-top: 1em; }
.reference__cite { display: block; margin-top: 16px; font: 700 var(--fs-label)/1.3 var(--font-display); letter-spacing: .15em; text-transform: uppercase; color: var(--purple); font-style: normal; }

/* Home: Mission Control invitation */
.mission__text .display-l { max-width: 16ch; }
.mission__seq { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin: 28px 0 0; font: 700 var(--fs-accent)/1.15 var(--font-accent); color: var(--navy); }
.mission__seq .mark--arrow { width: 2.2em; height: 1.1em; }
.mission__art { display: block; width: min(100%, 380px); height: auto; margin-top: clamp(28px, 4vw, 40px); }

/* Footer: second navigation column */
.footer-nav--b { margin-top: 0; }

@media (min-width: 900px) {
  .footer-brand { grid-column: 1 / 4; }
  .footer-nav { grid-column: 4 / 7; }
  .footer-nav--b { grid-column: 7 / 10; }
  .footer-contact { grid-column: 10 / 13; }

  .entry__list { grid-column: 1 / -1; }
  /* The two columns centre on each other, so the right-hand copy sits in the middle
     of its block instead of hanging from the top. */
  .entry { display: grid; grid-template-columns: 1fr 1.6fr; column-gap: var(--gap); align-items: center; }
  /* The logo stands above the grade and summary here, so it can be large without
     squeezing the summary into a narrow strip beside it; all three share one centre. */
  .entry__head { grid-column: 1; grid-template-columns: 1fr; align-items: start; justify-items: center; text-align: center; }
  .entry__head .programme-logo { grid-row: auto; width: min(100%, 300px); margin-bottom: 18px; }
  .entry__summary { grid-column: 1; margin-inline: auto; }
  .entry__body { grid-column: 2; margin-top: 0; }

  .fee-card { display: grid; grid-template-columns: 200px 1fr; column-gap: var(--gap); align-items: start; }
  .fee-card__head { flex-direction: column; text-align: center; gap: 14px; }
  .fee-card__body { margin-top: 0; }
  .fees--all .fees__terms { grid-column: 1 / -1; }
  .curriculum__text { grid-column: 1 / 8; }
  .curriculum__note { grid-column: 9 / 13; margin-top: clamp(24px, 4vw, 56px); }

  /* Deliberately NOT three equal columns: that is the generic three-feature row the
     previous build was rejected for. The session length leads at full width, and the
     two supporting answers sit in a narrower right rail. */
  .practical__item { margin-top: 0; }
  .practical__item--lead { grid-column: 1 / 7; grid-row: 1 / span 2; }
  .practical__item--a { grid-column: 8 / 13; grid-row: 1; }
  .practical__item--b { grid-column: 8 / 13; grid-row: 2; margin-top: clamp(28px, 4vw, 48px); }
  .session__copy { grid-column: 1 / 8; }
  .session__develops { grid-column: 9 / 13; margin-top: clamp(24px, 4vw, 64px); border-top: 0; border-left: 1px solid var(--line-strong); padding: 0 0 0 var(--gap); }
  .attend .chapter__head { grid-column: 1 / -1; }
  .ways { grid-column: 1 / -1; }
  .way { display: grid; grid-template-columns: 1.2fr 1fr 2fr; column-gap: var(--gap); align-items: baseline; }
  .way__size, .way__note { margin-top: 0; }

  .fees .chapter__head { grid-column: 1 / -1; }
  .fees__group { grid-column: 1 / 8; }
  .fees__private { grid-column: 1 / 8; }
  .fees__note { grid-column: 9 / 13; margin-top: 0; }
  .fees--boost .fees__group { grid-column: 1 / 8; }

  .institutions__text { grid-column: 1 / 8; }
  .institutions__note { grid-column: 9 / 13; border-top: 0; border-left: 1px solid var(--line-on-navy); padding: 0 0 0 var(--gap); margin-top: clamp(32px, 5vw, 72px); }

  .helps__text { grid-column: 1 / 8; }
  .helps__scope { grid-column: 9 / 13; margin-top: clamp(32px, 5vw, 80px); }
  .how-boost .chapter__head { grid-column: 1 / -1; }
  .steps { grid-column: 1 / -1; }
  .step { display: grid; grid-template-columns: 90px 1fr 1.6fr; column-gap: var(--gap); align-items: start; }
  .step h3 { margin-top: 0; }
  .step p { margin-top: 0; }

  .option { display: grid; grid-template-columns: 1fr 1.4fr; column-gap: var(--gap); align-items: start; }
  .option__who { grid-column: 1; margin-top: .4em; }
  .option > p:not(.option__who), .option .actions { grid-column: 2; }
  .option > h3 { grid-column: 1; }
  .option .actions { margin-top: 18px; }

  .enquiring__text { grid-column: 1 / 8; }
  .enquiring__note { grid-column: 9 / 13; margin-top: clamp(32px, 5vw, 80px); }
  .honest__text { grid-column: 1 / 9; }
  .honest__art { grid-column: 9 / 13; grid-row: 1; align-self: center; width: 100%; margin: 0; }

  .gains .chapter__head { grid-column: 1 / -1; }
  .gains__list { grid-column: 1 / -1; columns: 2; column-gap: clamp(32px, 5vw, 80px); }
  .gains__list li { break-inside: avoid; }
  /* The card is taller than the copy; 1fr on the second row takes up the difference,
     so the header's row keeps its natural height and the copy stays close beneath it. */
  .hosting > .grid { grid-template-rows: auto 1fr; }
  .hosting .chapter__head { grid-column: 1 / 8; grid-row: 1; }
  .hosting__text { grid-column: 1 / 8; grid-row: 2; }
  /* Top-aligned with the section's "Hosting Launchpad on site" header (user,
     2026-10-01): it spans the header's row and the copy's. Scoped to .hosting so it
     beats the generic card margin set on .programme__meta further down. */
  .hosting .hosting__meta { grid-column: 9 / 13; grid-row: 1 / span 2; margin-top: 0; }

  .topic { display: grid; grid-template-columns: 70px 1fr 1.8fr; column-gap: var(--gap); align-items: start; }
  .topic__title { margin-top: 0; }
  .topic__body { margin-top: 0; }
  .heard__text { grid-column: 1 / 8; }
  .heard__aside { grid-column: 9 / 13; border-top: 0; border-left: 1px solid var(--line-on-navy); padding: 0 0 0 var(--gap); margin-top: clamp(32px, 5vw, 72px); }

  .policy { display: grid; grid-template-columns: 110px 1fr 1.6fr; column-gap: var(--gap); align-items: start; }
  .policy h3 { margin-top: 0; max-width: 14ch; }
  .policy__body { margin-top: 0; }

  .voices__list { grid-column: 1 / -1; margin-top: clamp(40px, 5vw, 72px); }
  .voice { grid-column: span 6; }
  .voices__more { grid-column: 1 / -1; }

  .reference { display: grid; grid-template-columns: 110px 1fr; column-gap: var(--gap); align-items: start; }
  .reference__quote, .reference__cite { grid-column: 2; }
  .reference__quote { margin-top: 0; }

  .mission__text { grid-column: 1 / 8; }
  .mission__aside { grid-column: 8 / 13; align-self: center; }
  .mission__art { margin: 0 auto; }
  .mission__aside .mission__seq { justify-content: center; }
}

/* 14. Cards and pills (Starbound Brand Guide, adopted 2026-09-29) ----------------
   The guide groups content in rounded white cards with a hairline edge and a soft
   shadow, and tags things with pill labels. This supersedes the earlier "no cards, no
   pills, no shadows" rule, at the user's instruction. Cards are used where content is a
   set of like items or a side note; running prose stays open on the band. The navy
   night-sky sections are deliberately left as they were. */
:root {
  --card-edge: rgba(11, 25, 56, .09);
  --card-shadow: 0 1px 2px rgba(11, 25, 56, .04), 0 14px 34px -18px rgba(11, 25, 56, .22);
  --card-pad: clamp(20px, 2.6vw, 34px);
  --card-radius: 20px;
}
:is(.entry, .option, .way, .step, .topic, .policy, .principle, .reference, .gains__list li,
    .voice, .path, .channel, .practical__item, .aside-note, .programme__meta, .session__develops,
    .caps, .fees__group, .fees__private, .quote, .founders-quote, .fee-card) {
  background: var(--white); border: 1px solid var(--card-edge); border-radius: var(--card-radius);
  box-shadow: var(--card-shadow); padding: var(--card-pad);
}
/* Lists of cards: the hairlines that used to divide the items become gaps. */
:is(.entry__list, .options, .ways, .steps, .topics, .policies, .principles, .references, .gains__list) {
  display: grid; gap: clamp(14px, 1.8vw, 22px); border: 0;
}
.entry + .entry, .practical__item + .practical__item { margin-top: 0; }
.entry__list .entry { margin: 0; }
.practical__item--b, .practical__item--a { margin-top: clamp(14px, 1.8vw, 22px); }
.principle:first-child, .policy:first-child, .reference:first-child { padding-top: var(--card-pad); }
.caps, .session__develops, .aside-note, .programme__meta { margin-top: clamp(28px, 4vw, 48px); }
/* Quotes in cards keep their gold rule on the text itself. */
.quote, .founders-quote { padding-left: calc(var(--card-pad) - 6px); }
.voice p, .quote p, .founders-quote p { max-width: none; }
/* Home: "Why Starbound exists" is a night sky (since 2026-10-05). Skies stay card-free,
   so the founders' quote is open on the navy: white words on the gold rule, gold
   attribution (purple fails on navy). */
.on-navy .founders-quote { background: none; border: 0; border-radius: 0; box-shadow: none; padding: 0; }
.on-navy .founders-quote p { color: #fff; padding-left: 18px; }
.on-navy .founders-quote cite { color: var(--gold); }
.voices__list { gap: clamp(14px, 1.8vw, 22px); }
.voices__list .voice { margin: 0; }

/* Pills: the guide's rounded tags, for grade bands, group sizes and focus areas. Purple
   lettering, because the guide's own contrast table passes teal only for large text. */
.entry .kicker, .way__size {
  display: inline-block; width: max-content; padding: .45em .95em .4em; border: 1.5px solid rgba(104, 63, 160, .35);
  border-radius: 999px; color: var(--purple); letter-spacing: .1em;
}
.focus__label { margin-bottom: 10px; }
.focus { display: flex; flex-wrap: wrap; gap: 8px; }
.focus .focus__label { flex-basis: 100%; }
.focus__item { display: inline-block; padding: .35em .9em; border-radius: 999px; background: var(--paper); border: 1px solid var(--card-edge); color: var(--navy); font-weight: 600; line-height: 1.3; }
.focus__item + .focus__item::before { content: none; }

/* For parents: each option opens with its programme's icon. */
.option__logo { width: 140px; height: 140px; margin-bottom: 14px; }

@media (min-width: 900px) {
  .gains__list { grid-template-columns: repeat(2, minmax(0, 1fr)); columns: auto; }
  .voice { grid-column: auto; }
  /* Three reviews on the home page (HOME_TESTIMONIALS in app.py), so one row of three. */
  .voices__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .session__develops { border: 1px solid var(--card-edge); padding: var(--card-pad); margin-top: 0; align-self: start; }
  .option { grid-template-columns: 190px 1fr 1.4fr; }
  .option__logo { grid-column: 1; width: 190px; height: 190px; margin: 0; }
  .option > h3, .option__who { grid-column: 2; }
  .option > p:not(.option__who), .option .actions { grid-column: 3; }
  /* Name and "who it is for" sit together; the description spans both rows beside
     them, so a long description never pushes the two apart. */
  .option { grid-template-rows: auto 1fr auto; }
  .option__logo { grid-row: 1 / -1; }
  .option > h3 { grid-row: 1; }
  .option__who { grid-row: 2; align-self: start; }
  .option > p:not(.option__who) { grid-row: 1 / span 2; }
  .option .actions { grid-row: 3; margin-top: 18px; }
  .fees__group, .fees__private { align-self: start; }
  .aside-note, .programme__meta, .caps { align-self: start; }
}

/* The journey arc's full pull-up under its heading, once the screen is wide enough for
   the arc's rising end to clear "universe." (see the 900px block). */
@media (min-width: 1200px) {
  .journey .stations { margin-top: calc(var(--path-h) * -.72); }
}

/* ── social links ───────────────────────────────────────────────────────────
   Facebook and Instagram (templates/_social.html): icon + name, plain links, one
   body size. Gold underline on navy, coral on paper, like the contact links. */
.social { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 28px; }
.social__link { display: inline-flex; align-items: center; gap: 10px; padding: 8px 0; font: 600 var(--fs-body)/1.4 var(--font-text); color: var(--navy); text-decoration: none; }
.social__link .social__name { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .3em; text-decoration-color: var(--coral); }
.social__link:hover .social__name { text-decoration-color: var(--purple); }
.social__icon { flex: none; width: 22px; height: 22px; }
.site-footer .social__link { color: #fff; }
.site-footer .social__link .social__name { text-decoration-color: var(--gold); }
/* Scoped to .footer-contact so it beats `.footer-contact > span` (margin-top: 8px),
   which was squeezing "Follow us" up against the e-mail line (user, 2026-10-05). */
.footer-contact > .footer-label--follow { margin-top: 36px; margin-bottom: 4px; }
.channel .social { margin-top: 4px; }
/* Masthead: icons only on desktop, after "Chat to us" behind a hairline,
   with the names kept for screen readers. In the mobile menu they show in full. */
.site-nav .social--nav { flex-wrap: nowrap; gap: 14px; padding-left: clamp(14px, 1.6vw, 22px); border-left: 1px solid var(--line); }
.site-nav .social--nav .social__link { display: inline-flex; padding: 10px 0; color: var(--navy); transition: color var(--fast) var(--ease); }
.site-nav .social--nav .social__link:hover { color: var(--purple); }
.site-nav .social--nav .social__icon { width: 20px; height: 20px; }
@media (min-width: 900px) {
  .site-nav .social--nav .social__name { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
}
/* The icons cost the row about 70px, so the tight range above the mobile menu
   starts higher and squeezes a little harder than it did before they joined. */
@media (min-width: 1100px) and (max-width: 1239px) {
  .site-nav { gap: 22px; }
  .site-nav .nav-contact { margin-left: 0; }
}
@media (min-width: 900px) and (max-width: 1099px) {
  .masthead { gap: 16px; }
  .site-nav { gap: 13px; }
  .site-nav a { font-size: .84rem; }
  .site-nav .nav-contact { padding-inline: .75em; }
  .site-nav .social--nav { gap: 10px; padding-left: 12px; }
  .site-nav .social--nav .social__icon { width: 18px; height: 18px; }
  .brand-mark { height: 32px; }
  .brand-word { height: 28px; }
}
@media (max-width: 899px) {
  .site-nav .social--nav { gap: 4px 28px; margin-top: 24px; padding-left: 0; border-left: 0; }
  .site-nav .social--nav .social__link { color: inherit; font: 600 var(--fs-body)/1.4 var(--font-text); }
  .site-nav .social--nav .social__link:hover { color: inherit; }
  .site-nav .social--nav .social__name { text-decoration-color: var(--gold); }
  html:not(.has-js) .site-nav .social--nav { margin-top: 0; }
  html:not(.has-js) .site-nav .social--nav .social__name { text-decoration-color: var(--coral); }
}

/* Launchpad and For schools: the shared Launchpad fee card fills the row, and the
   page's own note sits full width beneath it (2026-10-05). */
.fees--card .fees__note { grid-column: 1 / -1; margin-top: clamp(14px, 1.8vw, 22px); }

/* WhatsApp icons (masthead and footer, 2026-10-05). They go through the contact
   masking; the reversed fallback number is hidden here because it is printed in the
   footer and on the contact page. */
.social__link--wa .contact-rev { display: none !important; }
/* .footer-contact .contact-link sets block + padding for the text links; undo it here. */
/* Footer: the phone, WhatsApp and e-mail lines are an icon plus the value, styled like the lines
   around it (user, 2026-10-05: an icon, not a button). */
.footer-contact .footer-wa { display: flex; align-items: center; gap: 10px; }
.footer-wa .social__icon { width: 22px; height: 22px; flex: none; }
@media (max-width: 899px) {
  /* Three links do not fit one phone-width row. */
  .site-nav .social--nav { flex-wrap: wrap; }
  /* The current-page "Chat to us" (on /contact) was navy on the navy menu. */
  .site-nav .nav-contact[aria-current="page"] { background: #fff; border-color: #fff; color: var(--navy); }
}

/* Reviews header: Astro and Nova cheering side by side (2026-10-05). */
.voices-head__art { display: flex; justify-content: center; align-items: flex-end; gap: clamp(8px, 1.5vw, 20px); margin: clamp(24px, 4vw, 36px) auto 0; max-width: 420px; }
.voices-head__art img { display: block; width: 46%; height: auto; }
