/* ==========================================================================
   The Project Hope — site stylesheet
   Single file, no build step. Edit here; every page picks it up.

   Contents
     1. Tokens          design system variables
     2. Reset & base    element defaults, typography
     3. Accessibility   skip link, focus, reduced motion
     4. Layout          wrappers, sections, grids
     5. Header & nav
     6. Buttons & links
     7. Components      cards, credentials, forms, quotes
     8. Page sections   hero, banner, vision, gallery, contact
     9. Footer
    10. Utilities

   Rules that are not negotiable (see .claude/skills/hope-brand-system):
     - Never put text on --coral, --sage or --gold. Fills only.
     - Every colour pairing is contrast-verified. Recompute before adding one.
     - Headings max out at font-weight 700; Times has no heavier cut.
   ========================================================================== */


/* --- Tinos, self-hosted ---------------------------------------------------
   Times New Roman is the client's decision and is present on Windows, macOS
   and iOS. Tinos is the metric-compatible substitute for Android and Linux,
   which is most of this audience, so it cannot be dropped.

   It is served from this origin rather than from Google. The third-party
   route cost two DNS lookups, two TLS handshakes and a render-blocking
   stylesheet before a single word could be painted. Only latin and latin-ext
   are shipped: the site is in English, and the Greek, Cyrillic and Vietnamese
   subsets Google serves would never be reached.

   Tinos is designed by Steve Matteson and licensed under the SIL Open Font
   License 1.1. The licence ships beside the files, at assets/fonts/OFL.txt.
   -------------------------------------------------------------------------- */
@font-face{
  font-family:'Tinos';
  font-style:italic;
  font-weight:400;
  font-display:swap;
  src:url('../fonts/tinos-400-italic-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family:'Tinos';
  font-style:italic;
  font-weight:400;
  font-display:swap;
  src:url('../fonts/tinos-400-italic-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Tinos';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url('../fonts/tinos-400-normal-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family:'Tinos';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url('../fonts/tinos-400-normal-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Tinos';
  font-style:normal;
  font-weight:700;
  font-display:swap;
  src:url('../fonts/tinos-700-normal-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family:'Tinos';
  font-style:normal;
  font-weight:700;
  font-display:swap;
  src:url('../fonts/tinos-700-normal-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* 1. TOKENS ================================================================
   Quiet-luxury palette, from design/HANDOFF.md. Every ratio below was
   computed, not estimated.

   THREE VALUES DEVIATE FROM THE HANDOFF, because the handoff's own contrast
   rule and its token roles disagreed with each other:

   - Eyebrows. The handoff gives #6E8A73 for "eyebrow labels, sage text on
     light". Eyebrows are 12-13px bold, which is not large text, so they need
     4.5:1 — #6E8A73 reaches only 3.57:1 on ivory. --sage-deep is therefore
     #3E5A44 (7.19:1), which is what the handoff's own rule 4 prescribes for
     sage that must read as text. #6E8A73 is kept as --sage-mid, fills only.

   - Gold on deep teal. The handoff states 8.3:1; the real figure for
     #C8A96B on #174F59 is 4.06:1, which fails for small text. --gold-on-teal
     is #D3BA88 (4.85:1) for eyebrow-sized type on teal grounds.

   - Link hover. #A8873F is 3.19:1 on ivory, below 4.5 for body-size links.
     --gold-link-hover is #7E6229 (5.40:1 ivory, 5.08:1 sunk).
   ========================================================================== */
:root{
  /* This design is light only. Saying so stops a phone or desktop in dark mode
     from repainting form controls, scrollbars and the <select> dark, which left
     dark text boxes sitting in a cream page. */
  color-scheme:light;

  /* Ground */
  --cream:#FAF8F3;             /* Warm Ivory — page background */
  --sunk:#F4F1EA;              /* Stone Sunk — alternate sections */
  --white:#FFFFFF;

  /* Ink */
  --charcoal:#252A29;          /* 13.72:1 on ivory */
  --muted:#5C6260;             /* Steel — 5.87:1 on ivory */

  /* Identity */
  --teal:#174F59;              /* 8.61:1 on ivory */
  --teal-deep:#0F3B43;         /* 11.46:1 on ivory; 12.16:1 with white */
  --teal-wash:#EAF0F0;

  /* Growth */
  --sage:#91A995;              /* fill only — 2.38:1, never text */
  --sage-mid:#6E8A73;          /* fill / large decorative only — 3.57:1 */
  --sage-deep:#3E5A44;         /* 7.19:1 on ivory — the text-safe sage */
  --sage-wash:#EFF2EE;

  /* Action */
  --coral:#C97868;             /* Dusty Terracotta — fill only, 3.11:1 */
  --coral-deep:#A9503C;        /* 5.07:1 ivory · 4.77:1 sunk · 5.39:1 w/ white */
  --coral-wash:#F7EAE6;

  /* Certification — reserved for verifiable credentials */
  --gold:#C8A96B;              /* Champagne — fill only, 2.12:1 */
  --gold-deep:#8A6D2F;         /* 4.59:1 on ivory — gold as text */
  --gold-on-teal:#D3BA88;      /* 4.85:1 on --teal — small text on teal */
  --gold-link-hover:#7E6229;   /* 5.40:1 on ivory */
  --gold-accent:#755A24;       /* Training's accent. --gold-deep is 4.59:1 on
                                  ivory but only 4.15:1 on coral-wash and
                                  4.23:1 on teal-wash, and the eyebrow it
                                  colours is 13px -- normal text, 4.5:1. This
                                  clears 5.51:1 on the worst ground used. */

  --line:#E9E6DE;              /* Soft Stone — borders, hairlines */
  --stone-muted:#CFCABE;       /* breadcrumbs on dark — 5.59:1 on teal */
  --error:#A8452F;

  /* Times New Roman first; Tinos is metric-identical and covers Android,
     which has no Times New Roman at all. */
  --font:"Times New Roman",Tinos,"Liberation Serif",Times,serif;

  --s3:.75rem; --s4:1rem; --s5:1.5rem; --s6:2rem;
  --s7:2.25rem; --s8:3rem; --s9:4rem;

  --r-sm:8px; --r-md:14px; --r-lg:22px; --r-pill:999px;

  --e1:0 1px 2px rgba(23,79,89,.06),0 2px 8px rgba(23,79,89,.05);
  --e2:0 4px 12px rgba(23,79,89,.08),0 12px 28px rgba(23,79,89,.07);

  /* The handoff specifies min(100% - 40px, 1140px), and its artboards are
     1200px wide — so in the design a 1140px container fills the frame almost
     edge to edge. On a real 1600-1920px display the same number leaves very
     wide empty margins, which is not what the design looks like. Widened so
     the proportions match the intent rather than the literal value.
     Line length is unaffected: measure is capped separately on .lede and
     body copy, so text never runs longer than it should. */
  /* The accent a page signs itself with. Therapy, the portal and the home
     page keep the teal the whole site is built on; the three pages that
     answer different questions get their own, so a reader who has been
     round the site once can tell which room they are standing in before
     they have read the heading. Each is a text-safe -deep value, so the
     accent is legal anywhere the palette is, not only as a fill. */
  --accent:var(--teal);

  --wrap:1320px;
  --head-h:97px;
}

/* 2. RESET & BASE ========================================================== */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;
  background:var(--cream);
  color:var(--charcoal);
  font-family:var(--font);
  /* Times has a small x-height, so the base starts a step above 1rem */
  font-size:clamp(1.0625rem,1rem + .3vw,1.1875rem);
  line-height:1.58;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4{font-family:var(--font); font-weight:700; margin:0; text-wrap:pretty}
/* Balancing is measurably expensive — ~540ms of Style & Layout on the long
   home page — and it only earns its cost on large display type where a
   single orphaned word is visible. Restricted to h1/h2 for that reason. */
h1,h2{text-wrap:balance}
h1{font-size:clamp(2.4rem,1.5rem + 3.8vw,3.7rem); line-height:1.05}
h2{font-size:clamp(1.95rem,1.3rem + 2.5vw,2.9rem); line-height:1.12; color:var(--teal)}
h3{font-size:clamp(1.2rem,1.08rem + .55vw,1.45rem); line-height:1.25}
h4{font-size:1.05rem; line-height:1.4}
p{margin:0; max-width:65ch}
/* Base link colour. Only scoped rules existed (.prose a, .chan a ...), so any link
   outside them fell back to browser blue -- off-brand on light grounds and 1.03:1
   on a teal band. Every scoped rule outranks this. */
a{color:var(--teal); text-underline-offset:3px}
img{max-width:100%; display:block}
ul,ol{margin:0}
code{font-family:ui-monospace,Consolas,monospace; font-size:.9em; background:var(--sunk); padding:.1em .35em; border-radius:4px}

/* 3. ACCESSIBILITY ========================================================= */
.skip{
  position:absolute; left:-9999px; top:0; z-index:100;
  background:var(--teal); color:#fff; padding:.75rem 1.25rem;
  border-radius:0 0 var(--r-sm) 0; font-weight:700; text-decoration:none;
}
/* :focus-visible, not :focus: it appears for keyboard users, who need it (WCAG 2.4.1),
   and never flashes up for someone using a mouse. */
.skip:focus-visible{left:0}
:focus-visible{outline:3px solid var(--teal); outline-offset:2px; border-radius:2px}
/* Sticky header must never cover the element you just jumped to (WCAG 2.4.11) */
[id]{scroll-margin-top:calc(var(--head-h) + 1rem)}
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
  .js [data-reveal]{opacity:1 !important; transform:none !important}
}

/* 4. LAYOUT ================================================================ */
.wrap{width:min(100% - 2.5rem,var(--wrap)); margin-inline:auto}
/* Sections carried 96px top and bottom at desktop width, which on the home
   page alone was 1388px of padding -- 19% of the page. Halved-and-a-bit to
   57.6px. Nothing is removed; the page simply stops holding its content at
   arm's length. */
.section{padding-block:clamp(2.25rem,4.2vw,3.6rem)}
.section--sunk{background:var(--sunk)}
.section--wash{background:var(--teal-wash)}
.section--sage{background:var(--sage-wash)}

[data-accent="gold"]{--accent:var(--gold-accent)}  /* Training  — 5.51:1 worst */
[data-accent="sage"]{--accent:var(--sage-deep)}   /* School    — 7.19:1 ivory */
[data-accent="clay"]{--accent:var(--coral-deep)}  /* Why it matters — 5.07:1 */

/* The reach section is frozen by instruction, and the accent system would
   otherwise have recoloured its eyebrow from sage to teal. Pinned back, so
   that section renders pixel-for-pixel as it did before this pass. */
.reach .eyebrow{color:var(--sage-deep)}
.eyebrow{
  font-size:.8125rem; font-weight:700; letter-spacing:.12em;
  text-transform:uppercase; color:var(--accent); margin:0 0 var(--s3);
}
.lede{font-size:clamp(1.06rem,1.02rem + .35vw,1.3rem); color:var(--muted); line-height:1.5;
  max-width:64ch}

.grid{display:grid; gap:var(--s5); grid-template-columns:repeat(auto-fit,minmax(270px,1fr)); margin-top:var(--s7)}
.grid--tight{gap:var(--s4); grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}

/* --- how many columns, given how many cards ------------------------------
   auto-fit fills the row with as many tracks as fit, which at desktop width
   is four, five or six. Nine cards then land as six and three; six land as
   five and one, one card marooned beside four empty columns. That is what
   made these sections look broken rather than airy.

   So the column count is chosen from the number of cards instead, picking a
   divisor where one exists and a near-divisor otherwise. :has(> :nth-child(N):
   last-child) is "exactly N children" -- the Nth child is also the last.
   Below 900px the auto-fit rule above still governs, which is what should
   happen: on a phone these stack whatever the count. */
@media (min-width:900px){
  .grid:has(> :nth-child(2):last-child),
  .grid:has(> :nth-child(4):last-child)   {grid-template-columns:repeat(2,minmax(0,1fr))}
  .grid:has(> :nth-child(3):last-child),
  .grid:has(> :nth-child(5):last-child),
  .grid:has(> :nth-child(6):last-child),
  .grid:has(> :nth-child(9):last-child)   {grid-template-columns:repeat(3,minmax(0,1fr))}
  .grid:has(> :nth-child(7):last-child),
  .grid:has(> :nth-child(8):last-child)   {grid-template-columns:repeat(4,minmax(0,1fr))}

  /* The tight variant carries smaller cards, so it takes one more column
     wherever the count allows it. */
  .grid--tight:has(> :nth-child(4):last-child)   {grid-template-columns:repeat(4,minmax(0,1fr))}
  .grid--tight:has(> :nth-child(8):last-child)   {grid-template-columns:repeat(4,minmax(0,1fr))}
  .grid--tight:has(> :nth-child(9):last-child)   {grid-template-columns:repeat(3,minmax(0,1fr))}

  .steps:has(> :nth-child(6):last-child)  {grid-template-columns:repeat(3,minmax(0,1fr))}
  .steps:has(> :nth-child(4):last-child)  {grid-template-columns:repeat(2,minmax(0,1fr))}
  .steps:has(> :nth-child(5):last-child)  {grid-template-columns:repeat(3,minmax(0,1fr))}
  .steps:has(> :nth-child(7):last-child)  {grid-template-columns:repeat(4,minmax(0,1fr))}

  .doors:has(> :nth-child(2):last-child)  {grid-template-columns:repeat(2,minmax(0,1fr))}
}
.two{display:grid; gap:clamp(2rem,5vw,4rem); grid-template-columns:1fr; align-items:start}
@media(min-width:880px){
  .two{grid-template-columns:1fr 1fr}
  .two--narrow{grid-template-columns:.85fr 1.15fr}
  /* Founder row, per the design handoff: minmax(0,.42fr) minmax(0,1fr), centred.
     The photograph fills its column instead of being pinned to 320px — that cap was
     the .42fr column measured at the design's 1140px canvas, and --wrap is 1320px
     here, so the column outgrew the picture and left the difference as dead space
     beside the face. Centred, because the text column is always the taller of the
     two and a photograph hung from the top leaves the hole all in one place. */
  .two:has(.portrait){grid-template-columns:minmax(320px,.42fr) minmax(0,1fr)}
  .two:has(.portrait) .portrait{max-width:none}
  /* Centred on the home founder row only, where the two columns are close in height.
     On About the text column is a full CV, and centring strands the photograph in the
     middle of it, far from the name it belongs to. */
  #founder .two{align-items:center}
}

/* 5. HEADER & NAV ========================================================== */
.head{
  position:sticky; top:0; z-index:50;
  background:rgba(249,247,242,.94); backdrop-filter:blur(10px);
  border-bottom:1px solid var(--line);
}
/* One row: mark, navigation, call to action. The nav used to be twelve links
   forced across a second row with space-between, which spread them the full
   1320px and read as a ruler rather than a menu. Grouped, it is five items and
   two disclosures, and fits beside the logo down to 1180px.

   The disclosures are <details>, so they open with no JavaScript at all; main.js
   only adds closing on Escape, on an outside click, and one-open-at-a-time.
   Click to open, never hover: a menu that appears because a pointer drifted
   past is exactly the unpredictability this audience should not meet. */
.head__in{
  display:flex; align-items:center; gap:var(--s5);
  min-height:var(--head-h); position:relative;
}
.logo{text-decoration:none; margin-right:auto; display:flex; align-items:center; color:var(--teal)}
.logo img{height:64px; width:auto; flex:none}
@media(min-width:1180px){ .logo img{height:72px} }

.nav__list{list-style:none; margin:0; padding:0}
.nav__list a:not(.btn),.nav__drop > summary{
  position:relative; display:flex; align-items:center; gap:.35rem;
  font-size:1rem; color:var(--charcoal); text-decoration:none;
  padding:.6rem .7rem; border-radius:var(--r-sm); min-height:44px; cursor:pointer;
}
.nav__drop > summary{list-style:none; font-family:var(--font); user-select:none}
.nav__drop > summary::-webkit-details-marker{display:none}
.nav__caret{width:14px; height:14px; flex:none; transition:transform .2s ease-out}
.nav__drop[open] > summary .nav__caret{transform:rotate(180deg)}

/* Panel rows: a bold name and one plain line saying what is behind it. */
.nav__panel ul{list-style:none; margin:0; padding:0; display:grid; gap:.15rem}
.nav .nav__panel a:not(.btn){flex-direction:column; align-items:flex-start; text-align:left; gap:.1rem; padding:.6rem .75rem}
.nav__panel a strong{color:var(--teal); font-size:1rem}
.nav__panel a span{color:var(--muted); font-size:.9rem; line-height:1.4}
.nav__panel a:hover,.nav__panel a:focus-visible{background:var(--teal-wash)}
.nav__panel a[aria-current] strong{text-decoration:underline; text-decoration-color:var(--gold-deep);
  text-decoration-thickness:2px; text-underline-offset:4px}
/* Families and professionals are never blended (CLAUDE.md, constraint 5), so the
   two columns carry their own labels and the professional one its own colour. */
.nav__label{font-size:.75rem; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--teal); margin:0 0 .35rem; padding:0 .75rem}
.nav__col--pro .nav__label{color:var(--sage-deep)}
.nav__col--alt .nav__label{color:var(--coral-deep)}   /* 5.39:1 on white */
.nav__col--pro .nav__panel a strong,.nav__col--pro a strong{color:var(--sage-deep)}

@media(min-width:1180px){
  .nav{display:block}
  .nav__list{display:flex; align-items:center; gap:.1rem}
  .nav__list > li > a:not(.btn)::after,.nav__drop > summary::after{
    content:""; position:absolute; left:.7rem; right:.7rem; bottom:.3rem; height:2px;
    background:var(--teal); transform:scaleX(0); transform-origin:left center;
    transition:transform .2s ease-out;
  }
  .nav__drop > summary::after{right:1.9rem}
  .nav__list > li > a:not(.btn):hover,.nav__drop > summary:hover{color:var(--teal)}
  .nav__list > li > a:not(.btn):hover::after,.nav__drop > summary:hover::after{transform:scaleX(1)}
  /* --gold is 2.12:1 on the header ground, below the 3:1 a state indicator
     needs. --gold-deep is 4.55:1 and still reads as gold. */
  .nav__list > li > a:not(.btn)[aria-current],.nav__drop.is-current > summary{color:var(--teal); font-weight:700}
  .nav__list > li > a:not(.btn)[aria-current]::after,.nav__drop.is-current > summary::after{
    transform:scaleX(1); background:var(--gold-deep)}
  .nav__home,.nav__cta,.nav__contact{display:none}
  .nav__portal{margin-left:.5rem; padding-left:.5rem; border-left:1px solid var(--line)}

  .nav__group{position:relative}
  .nav__panel{
    position:absolute; top:calc(100% + .55rem); left:-.25rem; z-index:60;
    background:var(--white); border:1px solid var(--line); border-radius:var(--r-md);
    box-shadow:var(--e2); padding:.75rem; min-width:17rem;
  }
  .nav__panel--split{display:grid; grid-template-columns:repeat(2,minmax(15.5rem,1fr)); gap:.25rem 1rem; min-width:34rem}
  .nav__col + .nav__col{border-left:1px solid var(--line); padding-left:1rem}
  /* Opens on hover (main.js) or click. User-initiated, transform and opacity
     only, 10px of travel at most: the panel settles in from just above, and its
     rows follow one after another so the eye is led down the list. */
  .nav__panel{transform-origin:top left}
  .nav__drop[open] > .nav__panel{animation:navDrop .26s cubic-bezier(.2,.8,.25,1) both}
  .nav__drop[open] .nav__label,
  .nav__drop[open] .nav__panel li{animation:navRow .32s cubic-bezier(.2,.8,.25,1) both}
  .nav__drop[open] .nav__col:nth-child(2) .nav__label{animation-delay:.05s}
  .nav__drop[open] .nav__panel li:nth-child(1){animation-delay:.05s}
  .nav__drop[open] .nav__panel li:nth-child(2){animation-delay:.1s}
  .nav__drop[open] .nav__panel li:nth-child(3){animation-delay:.15s}
  .nav__drop[open] .nav__col:nth-child(2) li:nth-child(1){animation-delay:.1s}
  .nav__drop[open] .nav__col:nth-child(2) li:nth-child(2){animation-delay:.15s}
  /* A small notch ties the panel to the word that opened it. */
  .nav__panel::before{content:""; position:absolute; top:-7px; left:1.6rem; width:12px; height:12px;
    background:var(--white); border-left:1px solid var(--line); border-top:1px solid var(--line); transform:rotate(45deg)}
  .nav__panel a:not(.btn){transition:background-color .18s ease}
  .nav__panel a:not(.btn) strong{transition:color .18s ease}
  .nav__panel a:not(.btn) span{transition:color .18s ease}
}
@keyframes navDrop{from{opacity:0; transform:translateY(-10px) scale(.98)} to{opacity:1; transform:none}}
@keyframes navRow{from{opacity:0; transform:translateY(6px)} to{opacity:1; transform:none}}
@media(prefers-reduced-motion:reduce){
  .nav__drop[open] > .nav__panel,.nav__drop[open] .nav__label,.nav__drop[open] .nav__panel li{animation:none}
  .nav__caret{transition:none}
}

/* The menu button is an icon: three bars that fold into a cross when the menu is
   open. Its words ("Open menu" / "Close menu") are its accessible name, set by
   main.js. The bars travel 7px and rotate -- transform only, on a tap. */
.nav-toggle{
  display:none; align-items:center; justify-content:center;
  width:48px; height:48px; padding:0; border:0; border-radius:14px;
  background:var(--teal); color:#fff; cursor:pointer; box-shadow:var(--e1);   /* bars 9.13:1 */
  transition:background-color .2s ease, transform .2s ease;
}
.nav-toggle:active{transform:scale(.94)}
.nav-toggle__bars{position:relative; display:block; width:22px; height:16px}
.nav-toggle__bars span{position:absolute; left:0; right:0; height:2px; border-radius:2px; background:currentColor;
  transition:transform .32s cubic-bezier(.2,.8,.25,1), opacity .2s ease}
.nav-toggle__bars span:nth-child(1){top:0}
.nav-toggle__bars span:nth-child(2){top:7px}
.nav-toggle__bars span:nth-child(3){top:14px}
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(2){opacity:0; transform:scaleX(.3)}
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
@media(prefers-reduced-motion:reduce){.nav-toggle__bars span{transition:none}}

/* Phones and tablets. The drawer is only a drawer once main.js has said it can
   open it (.navjs, set by the menu code itself -- not .js, which the motion code
   removes under reduced motion). Without it the menu is simply the list, in the
   flow under the logo, so every page stays reachable with scripts blocked. */
@media(max-width:1179px){
  /* .head raises specificity past .btn{display:inline-flex}, which comes later. */
  .head .btn--head{display:none}
  /* The header's load-in animation replays whenever an element leaves display:none,
     which made every open of the drawer a half-second fade. A menu opens at once. */
  .js .head__in > .nav{animation:none}
  .head__in{flex-wrap:wrap}
  html:not(.navjs) .head{position:relative}
  .nav{width:100%; padding-bottom:var(--s3)}
  .navjs .nav-toggle{display:inline-flex}
  .navjs .nav{
    display:none; position:absolute; left:0; right:0; top:100%; padding:var(--s3);
    background:var(--cream); border-bottom:1px solid var(--line); box-shadow:var(--e2);
    max-height:calc(100dvh - var(--head-h)); overflow-y:auto;
  }
  .navjs .nav.is-open{display:block}
  .nav__list > li > a:not(.btn),.nav__drop > summary{
    padding:.9rem 1rem; font-size:1.1rem; border-bottom:1px solid var(--line); border-radius:0;
  }
  .nav__drop > summary{justify-content:space-between}
  .nav__list > li > a:not(.btn)[aria-current]{background:var(--teal-wash); font-weight:700; color:var(--teal)}
  .nav__drop.is-current > summary{color:var(--teal); font-weight:700}
  .nav__panel{padding:.35rem 0 .75rem .75rem; border-bottom:1px solid var(--line)}
  .nav__col + .nav__col{margin-top:.75rem}
  .nav__label{margin-top:.5rem}
  .nav__cta{padding-top:var(--s3)}
  .nav__cta .btn{width:100%; border-bottom:0}
}

.progress{
  position:fixed; inset:0 0 auto 0; height:3px; background:var(--gold-deep);
  transform:scaleX(0); transform-origin:left center; z-index:60;
}

/* 6. BUTTONS & LINKS ======================================================= */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:.5rem;
  min-height:48px; padding:.8rem 1.6rem; border-radius:var(--r-pill);
  font-family:var(--font); font-weight:700; font-size:1rem;
  text-decoration:none; border:2px solid transparent; cursor:pointer;
  transition:background-color .2s,color .2s,transform .2s,box-shadow .2s;
}
.btn--primary{background:var(--teal); color:#fff; box-shadow:var(--e1)}
.btn--primary:hover{background:var(--gold); color:var(--teal-deep);
  transform:translateY(-2px); box-shadow:var(--e2)}
.btn--primary:active{transform:translateY(0)}
.btn--ghost{background:transparent; color:var(--teal); border-color:var(--teal)}
.btn--ghost:hover{background:var(--teal-wash)}
.btn--wa{background:var(--sage-deep); color:#fff}
.btn--wa:hover{background:var(--teal); transform:translateY(-2px)}
.btn[disabled],.btn[aria-busy="true"]{opacity:.7; cursor:not-allowed; transform:none}

.prose a{color:var(--teal); text-underline-offset:3px}
.prose a:hover{color:var(--gold-link-hover)}

/* 7. COMPONENTS ============================================================ */
.card{
  background:var(--white); border:1px solid var(--line); border-radius:var(--r-md);
  padding:var(--s6); box-shadow:var(--e1);
  display:flex; flex-direction:column; gap:var(--s3);
  transition:transform .2s,box-shadow .2s,border-color .2s;
}
.card:hover{transform:translateY(-6px); box-shadow:var(--e2); border-color:var(--teal)}
.card__plate{width:52px; height:52px; border-radius:var(--r-md); background:var(--teal-wash); display:grid; place-items:center; color:var(--teal)}
.card--b .card__plate{background:var(--sage-wash); color:var(--sage-deep)}
.card--c .card__plate{background:var(--coral-wash); color:var(--coral-deep)}
.card p{font-size:.98rem; color:var(--muted)}
/* Forward link. Was scoped to .card; the doors and the Why-it-matters index
   use it too, so it is now a standalone component. Without this the links in
   those sections fell back to the browser's default blue. */
.more{font-weight:700; color:var(--teal); text-decoration:none; padding-top:var(--s3);
  display:inline-flex; gap:.4rem; align-items:center}
.card .more{margin-top:auto}
.door--sage .more{color:var(--sage-deep)}
.door--gold .more{color:var(--gold-deep)}
.more:hover,.more:focus-visible{color:var(--gold-link-hover)}
.more::after{content:"\2192"; transition:transform .2s}
.more:hover::after,.more:focus-visible::after{transform:translateX(3px)}

.mini{background:var(--white); border:1px solid var(--line); border-radius:var(--r-md); padding:var(--s5)}
.mini h3{font-size:1.05rem; color:var(--teal); margin-bottom:.3rem}
.mini p{font-size:.95rem; color:var(--muted)}

.path{
  background:var(--white); border:1px solid var(--line); border-radius:var(--r-md);
  border-left:5px solid var(--teal); padding:var(--s6); box-shadow:var(--e1);
  display:flex; flex-direction:column; gap:var(--s3);
  transition:transform .2s,box-shadow .2s;
}
.path--pro{border-left-color:var(--sage-deep)}
.path:hover{transform:translateY(-4px); box-shadow:var(--e2)}
.path__who{font-size:.8rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase; color:var(--teal)}
.path--pro .path__who{color:var(--sage-deep)}
.path p{color:var(--muted); font-size:1rem}
.path .btn{align-self:flex-start; margin-top:var(--s3)}

/* Credential block — gold is reserved for verifiable certification */
.cred{
  background:var(--white); border:1px solid var(--line); border-top:4px solid var(--gold);
  border-radius:var(--r-md); padding:clamp(1.5rem,4vw,2.5rem); box-shadow:var(--e1);
  display:grid; gap:clamp(1.5rem,4vw,2.5rem); grid-template-columns:1fr; align-items:center;
}
@media(min-width:760px){.cred{grid-template-columns:auto 1fr}}
.cred__seal{
  width:120px; height:120px; border-radius:50%; background:#FDF8E8;
  border:2px solid var(--gold); display:grid; place-items:center; text-align:center;
  color:var(--gold-deep); font-weight:700; line-height:1.15; justify-self:start;
}
.cred__seal b{display:block; font-size:1.7rem}
.cred__seal span{font-size:.62rem; letter-spacing:.08em; text-transform:uppercase}
.cred h3{color:var(--teal)}
/* This list measures the card, not the window. The card is full width on About but half
   width beside the portrait on Home, so a viewport query gave Home two 181px tracks —
   every value wrapped under its own label and the odd third fact was stranded. Stacked is
   the base case, so a browser without container queries still reads cleanly.
   19rem fits a label and its longest value inline; 37rem fits two such pairs. */
.cred__body{container-type:inline-size}
.cred__meta{list-style:none; margin:1.1rem 0 0; padding:0; display:grid; gap:.5rem; grid-template-columns:1fr; font-size:.95rem}
.cred__meta li{display:flex; flex-direction:column; gap:.1rem}
.cred__meta dfn{font-style:normal; color:var(--muted)}
.cred__meta b{font-variant-numeric:tabular-nums}
@container (min-width:19rem){.cred__meta li{flex-direction:row; gap:.5rem; align-items:baseline}.cred__meta dfn{min-width:8.5em}}
@container (min-width:37rem){.cred__meta{grid-template-columns:1fr 1fr; gap:.5rem 1.5rem}}
/* Three facts in two tracks always strand one, however wide the card gets. */
.cred__meta:has(> li:nth-child(3):last-child){grid-template-columns:1fr}
/* Beside a portrait the card shares the prose measure (p is 65ch), so its right edge
   lines up with the paragraph above instead of running on past it. */
.two .cred{max-width:65ch}
.cred__link{display:inline-flex; align-items:center; gap:.45rem; margin-top:1.1rem; color:var(--teal); font-weight:700; text-decoration:underline; text-underline-offset:3px}
.cred__link:hover{color:var(--gold-link-hover)}

.auths{display:grid; gap:var(--s4); grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); margin-top:var(--s6)}
.auth{background:var(--white); border:1px solid var(--line); border-left:4px solid var(--gold); border-radius:var(--r-sm); padding:var(--s5)}
.auth h3{font-size:1.02rem; color:var(--gold-deep); margin-bottom:.2rem}
.auth p{font-size:.93rem; color:var(--muted)}

.ticks{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:var(--s3)}
.ticks li{display:flex; gap:.7rem; align-items:flex-start}
.ticks svg{flex:none; width:22px; height:22px; color:var(--sage-deep); margin-top:.28em}

.steps{display:grid; gap:var(--s5); grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); margin-top:var(--s7)}
.step{background:var(--white); border:1px solid var(--line); border-radius:var(--r-md); padding:var(--s5)}
.step__n{width:40px; height:40px; border-radius:50%; background:var(--teal); color:#fff; display:grid; place-items:center; font-weight:700; margin-bottom:var(--s3)}
.step h3{font-size:1.05rem; color:var(--teal); margin-bottom:.3rem}
.step p{font-size:.95rem; color:var(--muted)}

.quote{background:var(--white); border:1px solid var(--line); border-radius:var(--r-md); padding:var(--s6); display:flex; flex-direction:column; gap:var(--s4)}
.quote blockquote{margin:0; font-size:1.08rem; font-style:italic}
.quote figcaption{font-size:.93rem; color:var(--muted)}

.post{background:var(--white); border:1px solid var(--line); border-radius:var(--r-md); padding:var(--s5); display:flex; flex-direction:column; gap:.5rem}
.post .kind{font-size:.75rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--sage-deep)}
.post h3{font-size:1.08rem; color:var(--teal)}
.post p{font-size:.94rem; color:var(--muted)}

/* Placeholder marker — this site never fabricates facts.
   Styled in 37.8: a dashed terracotta box on every one of them made a
   finished site read as broken, and there are three dozen. */
.note{border-left:4px solid var(--gold); background:#FDF8E8; border-radius:0 var(--r-sm) var(--r-sm) 0; padding:var(--s4) var(--s5); font-size:.95rem; color:#5C4A12; max-width:70ch}
.note strong{color:var(--gold-deep)}

/* 8. PAGE SECTIONS ========================================================= */
/* Hero. Deliberately sparse: eyebrow, headline, one line, two choices,
   and a way down. Everything the page used to stack above the fold now
   sits below it. A first screen with fifteen things on it asks the
   visitor to make a decision before they have read anything. */
.hero{padding-block:clamp(2.5rem,5.6vw,4.4rem) clamp(2rem,4.2vw,3.2rem)}
.hero h1{max-width:15ch}
.hero__lede{margin-top:var(--s4); max-width:46ch}
.hero__acts{display:flex; flex-wrap:wrap; gap:var(--s4);
  margin-top:clamp(1.4rem,3vw,2rem)}

/* Scroll cue. Static — a looping bounce would violate the motion budget,
   and this audience is exactly who that budget protects. It moves only
   on hover, which the visitor initiates. */
.cue{display:inline-flex; align-items:center; gap:.5rem;
  margin-top:clamp(2.5rem,6vw,4rem); font-size:.85rem; font-weight:700;
  letter-spacing:.1em; text-transform:uppercase; color:var(--muted);
  text-decoration:none}
.cue svg{width:18px; height:18px; transition:transform .25s cubic-bezier(.2,.7,.3,1)}
.cue:hover,.cue:focus-visible{color:var(--teal-deep)}
.cue:hover svg,.cue:focus-visible svg{transform:translateY(3px)}

/* Credentials band — a thin strip between hero and content, not a block
   competing inside the hero itself. */
.band{background:var(--white); border-block:1px solid var(--line);
  padding-block:clamp(1rem,2.5vw,1.4rem)}
.band .trust{margin-top:0; padding-top:0; border-top:0}

.fork{display:grid; gap:var(--s5); grid-template-columns:1fr; margin-top:var(--s7)}
@media(min-width:820px){.fork{grid-template-columns:1fr 1fr}}

.trust{display:flex; flex-wrap:wrap; gap:var(--s3) var(--s6); margin:0; padding:0; list-style:none; justify-content:space-between}
.trust li{display:flex; align-items:center; gap:.55rem; font-weight:700; font-size:.95rem; color:var(--teal)}
.trust svg{flex:none; width:20px; height:20px; color:var(--gold-deep)}

/* Page banner for inner pages */
.banner{background:var(--teal-wash); border-bottom:1px solid var(--line); padding-block:clamp(2rem,4vw,3.05rem)}
.banner h1{font-size:clamp(2rem,1.3rem + 2.8vw,3rem); color:var(--teal)}
.banner p{margin-top:var(--s4)}
/* Banner, two columns. The heading and lede held the left half of a 1320px
   wrap and the right half was empty on every page. The right column now carries
   what a visitor most needs from that page -- only facts the page itself states. */
.banner__grid{display:grid; gap:var(--s5) var(--s7); grid-template-columns:1fr; align-items:center}
@media(min-width:960px){.banner__grid{grid-template-columns:minmax(0,1.5fr) minmax(18rem,.75fr)}}
.glance{background:var(--white); border:1px solid var(--line); border-radius:var(--r-md);
  box-shadow:var(--e1); padding:var(--s5) var(--s5) var(--s3)}
.banner .glance p,.banner .glance__title{margin:0}
.glance__title{font-size:.75rem; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--teal)}
.glance ul{list-style:none; margin:.6rem 0 0; padding:0}
.glance li{display:grid; gap:.05rem; align-content:start; position:relative; padding:.6rem 0 .6rem 1.15rem; border-top:1px solid var(--line)}
.glance li:first-child{border-top:0}
/* Gold as a fill, never as text. */
.glance li::before{content:""; position:absolute; left:.1rem; top:1.05rem; width:.42rem; height:.42rem;
  background:var(--gold); transform:rotate(45deg)}
.glance strong{color:var(--charcoal); font-size:1rem; line-height:1.35}
.glance span{color:var(--muted); font-size:.93rem; line-height:1.45}
/* A dark banner colours its links gold-on-teal; inside a white panel that would be
   1.88:1. Teal on white is 9.13:1. */
.glance a,.banner--deep .glance a{color:var(--teal); text-decoration-color:rgba(23,79,89,.4)}
.banner--deep .glance :focus-visible{outline-color:var(--teal)}
/* Volunteer: the photograph is the right-hand column rather than a strip between
   the heading and the first sentence. */
/* Doubled class: the base .banner__media rule comes later in the file. */
.banner__media.banner__media--side{margin:0; aspect-ratio:4/3; max-height:none}
@media(max-width:959px){.banner__media.banner__media--side{aspect-ratio:16/9; max-height:260px}}
.crumbs{font-size:.9rem; color:var(--muted); margin-bottom:var(--s4)}
.crumbs a{color:var(--teal)}

.photo{
  aspect-ratio:4/3; border-radius:var(--r-md); border:2px dashed var(--teal);
  background:var(--teal-wash); display:grid; place-items:center; text-align:center;
  padding:var(--s5); color:var(--teal);
}
.photo--portrait{aspect-ratio:3/4}
.photo span{font-weight:700; max-width:28ch}

.vision{background:var(--teal); color:#fff; border-radius:var(--r-lg); padding:clamp(1.75rem,5vw,3.5rem)}
.vision h2{color:#fff}
.vision p{color:#DCEAEC}
.vision .eyebrow{color:#BFD9C6}
.vision .btn--primary{background:#fff; color:var(--teal)}
.vision .btn--primary:hover{background:var(--coral-deep); color:#fff}
.vision .btn--ghost{color:#fff; border-color:rgba(255,255,255,.6)}
.vision .btn--ghost:hover{background:rgba(255,255,255,.12)}
.vision .tbd{background:rgba(0,0,0,.30); border-color:#F5C4B7; color:#FFD9CF}
.vision__acts{display:flex; flex-wrap:wrap; gap:var(--s4); margin-top:var(--s6)}
.vision a:not(.btn){color:var(--gold-on-teal)}   /* 4.85:1 on teal */
.vision :focus-visible{outline-color:#fff}

/* What the centre provides free — cards inside the teal vision panel.
   Contrast on the composited background (10% white over --teal, #356F7A):
   #fff 5.67:1, #EAF3F4 5.03:1. Both pass AA. Do not lighten the panel
   further without recomputing — every gain in panel lightness is a loss
   of contrast for the text on it. */
.gives{display:grid; gap:var(--s4); margin-top:var(--s6);
  grid-template-columns:repeat(auto-fit,minmax(215px,1fr))}
.give{background:rgba(255,255,255,.10); border:1px solid rgba(255,255,255,.22);
  border-radius:var(--r-md); padding:var(--s5)}
.give__ic{width:40px; height:40px; border-radius:var(--r-sm); display:grid;
  place-items:center; background:rgba(255,255,255,.14); color:#fff; margin-bottom:var(--s4)}
.give h3{color:#fff; font-size:1.05rem}
.vision .give p{color:#EAF3F4; font-size:.94rem; margin-top:.35rem}

/* Evidence figures — big number, then what it means. Numbers use --teal
   (7.4:1 on --white); never --sage/--coral/--gold, which are fills only. */
.stats{display:grid; gap:var(--s4); margin-top:var(--s7);
  grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.stat{background:var(--white); border:1px solid var(--line); border-left:4px solid var(--teal);
  border-radius:var(--r-md); padding:var(--s5)}
.stat b{display:block; font-size:clamp(2rem,5vw,2.9rem); line-height:1.05; color:var(--teal);
  font-weight:700; letter-spacing:0}
.stat span{display:block; margin-top:var(--s3); font-size:.95rem; color:var(--charcoal)}
.stat cite{display:block; margin-top:var(--s3); font-size:.82rem; color:var(--muted); font-style:normal}

/* Source list. Small, but present — an unsourced statistic on a donations
   page is worth less than no statistic at all. */
.cites{margin-top:var(--s6); padding-top:var(--s5); border-top:1px solid var(--line);
  font-size:.85rem; color:var(--muted); line-height:1.65}
.cites li{margin-top:var(--s3)}
.cites a{color:var(--teal-deep)}

/* The handoff's 5-cell asymmetric gallery: a tall feature cell on the left
   spanning both rows, then a 2x2 of smaller frames. Collapses to two
   columns, then one, on narrow screens. */
.gal{display:grid; gap:var(--s4); margin-top:var(--s7); grid-template-columns:1fr}
@media(min-width:600px){.gal{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:900px){
  .gal{grid-template-columns:minmax(0,2fr) minmax(0,1fr) minmax(0,1fr);
       grid-auto-rows:168px}
  .gal > *:first-child{grid-row:span 2}
}
.gal div{aspect-ratio:1; border-radius:var(--r-md); border:2px dashed var(--sage-deep); background:var(--sage-wash); display:grid; place-items:center; text-align:center; padding:var(--s4); color:var(--sage-deep); font-weight:700; font-size:.92rem}

.contact{display:grid; gap:clamp(2rem,5vw,3.5rem); grid-template-columns:1fr}
@media(min-width:880px){.contact{grid-template-columns:.9fr 1.1fr}}
.channels{display:flex; flex-direction:column; gap:var(--s4)}
.chan{background:var(--white); border:1px solid var(--line); border-radius:var(--r-md); padding:var(--s5); display:flex; gap:var(--s4); align-items:flex-start}
/* A flex or grid child defaults to min-width:auto, so it never shrinks below
   its longest unbreakable word. The email address is one 26-character token,
   which pushed the contact panel 23px past a 320px viewport -- still a real
   screen width on older Android, which is much of this audience. */
.chan,.chan > *{min-width:0}
.chan a,.chan p{overflow-wrap:anywhere}
.enquiry,.enquiry .field,.enquiry .field > *{min-width:0}

.chan__ic{width:44px; height:44px; flex:none; border-radius:var(--r-sm); background:var(--sage-wash); color:var(--sage-deep); display:grid; place-items:center}
.chan h3{font-size:1.02rem; color:var(--teal)}
.chan p{font-size:.95rem; color:var(--muted); margin-top:.15rem}
.chan a{color:var(--teal); font-weight:700}

/* Forms — visible labels always; placeholders are not labels */
form.enquiry{background:var(--white); border:1px solid var(--line); border-radius:var(--r-md); padding:var(--s6)}
.field{display:flex; flex-direction:column; gap:.4rem; margin-bottom:var(--s4)}
label{font-weight:700; font-size:.98rem}
label .opt{font-weight:400; color:var(--muted)}
input,textarea,select{
  font-family:inherit; font-size:1rem; min-height:48px; padding:.7rem .9rem;
  background:var(--sunk); border:1.5px solid #D8D3C8; border-radius:var(--r-sm);
  color:var(--charcoal); width:100%;
}
textarea{min-height:120px; resize:vertical}
input:focus,textarea:focus,select:focus{outline:none; border-color:var(--teal); box-shadow:0 0 0 3px rgba(31,95,107,.18)}
input[aria-invalid="true"],textarea[aria-invalid="true"]{border-color:var(--error); background:var(--coral-wash)}
.hint{font-size:.9rem; color:var(--muted)}
/* Errors are text, never colour alone, and never a shake animation */
.err{font-size:.9rem; color:var(--error); font-weight:700}
.err:empty{display:none}
.form-status{margin-top:var(--s4); padding:var(--s4); border-radius:var(--r-sm); font-weight:700}
.form-status:empty{display:none; padding:0}
.form-status--ok{background:var(--sage-wash); color:var(--sage-deep); border:1px solid var(--sage-deep)}
.form-status--bad{background:var(--coral-wash); color:var(--error); border:1px solid var(--error)}
form.enquiry .btn{width:100%; margin-top:var(--s3)}
/* Honeypot — hidden from people, visible to naive bots */
.hp{position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden}

/* 9. FOOTER ================================================================ */
.foot{background:var(--teal); color:#fff; padding-block:var(--s8) var(--s6); margin-top:var(--s9)}
.foot a{color:#CFE6EA}
.foot__grid{display:grid; gap:var(--s6); grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.foot h3{font-size:.98rem; margin-bottom:var(--s3); color:#fff}
.foot ul{list-style:none; padding:0; display:flex; flex-direction:column; gap:.5rem; font-size:.95rem}
.foot p{font-size:.95rem; color:#CFE6EA}
.foot__bar{margin-top:var(--s7); padding-top:var(--s5); border-top:1px solid rgba(255,255,255,.2); font-size:.9rem; color:#CFE6EA; display:flex; flex-wrap:wrap; gap:var(--s4); justify-content:space-between}

/* 10. UTILITIES ============================================================ */
.mt1{margin-top:.85rem} .mt2{margin-top:1.5rem} .mt3{margin-top:2.15rem}
/* Centring a block is not enough on its own: p has max-width:65ch, so a
   centred paragraph is a narrow box pinned to the left edge and anything
   inside it — a button, especially — centres within that box rather than on
   the page. Auto-margin every direct child so .center actually centres. */
.center{text-align:center}
.center > *{margin-inline:auto}
.stack > * + *{margin-top:var(--s4)}

/* Reveal: visible at rest. JS opts elements into starting hidden, so if the
   script never runs nothing is ever invisible. */
[data-reveal]{opacity:1}
/* Hidden only until .in arrives. The shown state deliberately sets no transform:
   ".in{transform:none}" outranked .card:hover and cancelled every hover lift on
   a revealed card. With the rule on :not(.in), hover owns transform again. */
.js [data-reveal]{transition:opacity .5s ease-out, transform .5s ease-out; transition-delay:0s}
.js [data-reveal]:not(.in){opacity:0; transform:translateY(14px)}
/* Members of a group come in one after another. */
.js [data-reveal].in{transition-delay:calc(var(--i, 0) * 55ms)}

/* 11. HELPER CLASSES ======================================================= */
/* These replace inline styles so the pages pass html-validate and so a
   Content-Security-Policy without 'unsafe-inline' for style would still work. */
.mx-auto{margin-inline:auto}
.mb2{margin-bottom:1.15rem}
.t-teal{color:var(--teal)}
.h-sub{font-size:1.45rem}
.h-form{font-size:1.5rem}
.fs-sm{font-size:.95rem}
.map{aspect-ratio:16/7}
.foot__bar--bare{margin-top:0; border-top:0; padding-top:0}

/* 12. VIEW TRANSITIONS ===================================================== */
/* Cross-document page transitions, native and framework-free. Chromium and
   Safari 18.2+ honour this; everything else simply navigates normally, so it
   is pure progressive enhancement.

   Deliberately a CROSS-FADE ONLY — no slide, no scale. Movement between pages
   is the part that causes vestibular problems; a change in opacity does not.
   Kept short (220ms) so it never feels like waiting. */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root){
  animation-duration:.22s;
  animation-timing-function:ease;
}

/* The header is visually identical across pages, so hold it still rather than
   cross-fading it with the rest — otherwise it appears to flicker. */
.head{ view-transition-name:site-header; }

@media (prefers-reduced-motion: reduce){
  @view-transition { navigation: none; }
}

/* 13. REGISTRATION FORMS =================================================== */
fieldset{
  border:1px solid var(--line); border-radius:var(--r-sm);
  padding:var(--s5); margin:0 0 var(--s5);
}
legend{
  font-weight:700; font-size:.98rem; padding:0 .5rem; color:var(--teal);
}
.choices{display:grid; gap:.6rem; grid-template-columns:1fr}
@media(min-width:520px){.choices{grid-template-columns:1fr 1fr}}
.choice{
  display:flex; align-items:flex-start; gap:.6rem;
  padding:.7rem .8rem; border:1.5px solid #D8D3C8; border-radius:var(--r-sm);
  background:var(--sunk); cursor:pointer; min-height:48px;
  transition:border-color .15s, background-color .15s;
}
.choice:hover{border-color:var(--teal)}
.choice input{
  width:20px; height:20px; min-height:0; flex:none; margin-top:.15rem;
  accent-color:var(--teal); padding:0;
}
.choice span{font-size:.97rem; line-height:1.4}
.choice:has(input:checked){border-color:var(--teal); background:var(--teal-wash)}
.choice:has(input:focus-visible){outline:3px solid var(--teal); outline-offset:2px}

.consent{
  display:flex; align-items:flex-start; gap:.7rem;
  padding:var(--s4); border:1.5px solid var(--line); border-radius:var(--r-sm);
  background:var(--sunk); margin-bottom:var(--s4);
}
.consent input{width:20px; height:20px; min-height:0; flex:none; margin-top:.2rem; accent-color:var(--teal); padding:0}
.consent label{font-weight:400; font-size:.95rem; line-height:1.5}

/* Two registration tracks on one page, kept visually distinct so a parent and
   a prospective trainee never feel they are reading each other's form. */
.track{
  background:var(--white); border:1px solid var(--line);
  border-top:5px solid var(--teal); border-radius:var(--r-md);
  padding:clamp(1.5rem,4vw,2.5rem); box-shadow:var(--e1);
}
.track--pro{border-top-color:var(--sage-deep)}
/* Register: the two forms side by side from 1100px. Each keeps its own colour
   rule and heading, so the two tracks stay visibly separate. */
.tracks{display:grid; gap:var(--s6); grid-template-columns:1fr; align-items:start}
@media(min-width:1100px){.tracks{grid-template-columns:repeat(2,minmax(0,1fr))}}
.track > h2{font-size:clamp(1.5rem,1.2rem + 1vw,1.9rem)}
.track .enquiry{background:transparent; border:0; padding:0; margin-top:var(--s5)}
.track-nav{display:flex; flex-wrap:wrap; gap:var(--s4); margin-top:var(--s6)}

/* 14. MOTION CRAFT ========================================================= */
/* Added depth without breaking the budget: every effect below is user- or
   scroll-initiated, moves <=14px, runs once, and animates only transform,
   opacity or background-size. Nothing loops. Nothing moves on its own. */

/* --- headline word reveal ------------------------------------------------
   Words rise and fade in sequence. This is where the typographic personality
   lives, and it costs nothing in layout because the words are inline-block
   and never reflow. JS sets the per-word delay; the cap is 8 words so the
   line always finishes inside ~350ms. */
.js [data-split] .w{
  display:inline-block;
  opacity:0;
  transform:translateY(14px);
  transition:opacity .42s cubic-bezier(.2,.7,.3,1), transform .42s cubic-bezier(.2,.7,.3,1);
  will-change:transform,opacity;
}
.js [data-split].in .w{opacity:1; transform:none; will-change:auto}

/* --- button fill sweep ---------------------------------------------------
   The hover colour wipes across instead of switching flatly. Done with
   background-size so there is no extra element and no stacking-context risk;
   the end state is identical to before, so contrast is unchanged. */
.btn--primary{
  background-image:linear-gradient(var(--gold),var(--gold));
  background-repeat:no-repeat;
  background-size:0% 100%;
  transition:background-size .3s cubic-bezier(.2,.7,.3,1), transform .2s, box-shadow .2s, color .2s;
}
.btn--primary:hover,.btn--primary:focus-visible{background-size:100% 100%}
.btn--ghost{
  background-image:linear-gradient(var(--teal-wash),var(--teal-wash));
  background-repeat:no-repeat;
  background-size:0% 100%;
  transition:background-size .3s cubic-bezier(.2,.7,.3,1), transform .2s, box-shadow .2s;
}
.btn--ghost:hover,.btn--ghost:focus-visible{background-size:100% 100%}

/* --- card interior response ---------------------------------------------- */
.card__plate{transition:transform .25s cubic-bezier(.2,.7,.3,1), background-color .25s}
.card:hover .card__plate{transform:translateY(-3px)}
.card:hover .card__plate{background:var(--teal); color:#fff}
.card--b:hover .card__plate{background:var(--sage-deep); color:#fff}
.card--gold:hover .card__plate{background:var(--gold-deep); color:#fff}   /* white on gold-deep 4.87:1 */
.card__plate{transition:background-color .25s ease, color .25s ease, transform .3s cubic-bezier(.34,1.56,.64,1)}

/* ---- entrances that belong to a component --------------------------------
   All user- or scroll-initiated, transform and opacity only, within 14px.
   Keyed off .gsap, which the script sets only when it will also set .in, so
   with GSAP blocked or scripts off none of this ever hides anything. */

/* The timeline draws itself: each number pops in turn, then the rule down to
   the next one grows from the top. */
.gsap .timeline > li::before{transition:transform .5s cubic-bezier(.34,1.56,.64,1), opacity .3s ease}
.gsap .timeline > li:not(.in)::before{transform:scale(.4); opacity:0}
.gsap .timeline > li:not(:last-child)::after{transform-origin:top center; transition:transform .55s cubic-bezier(.2,.8,.25,1) .25s}
.gsap .timeline > li:not(.in):not(:last-child)::after{transform:scaleY(0)}
.gsap .timeline > li:nth-child(1)::before{transition-delay:0.00s}
.gsap .timeline > li:nth-child(1)::after{transition-delay:0.22s}
.gsap .timeline > li:nth-child(2)::before{transition-delay:0.14s}
.gsap .timeline > li:nth-child(2)::after{transition-delay:0.36s}
.gsap .timeline > li:nth-child(3)::before{transition-delay:0.28s}
.gsap .timeline > li:nth-child(3)::after{transition-delay:0.50s}
.gsap .timeline > li:nth-child(4)::before{transition-delay:0.42s}
.gsap .timeline > li:nth-child(4)::after{transition-delay:0.64s}
.gsap .timeline > li:nth-child(5)::before{transition-delay:0.56s}
.gsap .timeline > li:nth-child(5)::after{transition-delay:0.78s}
.gsap .timeline > li:nth-child(6)::before{transition-delay:0.70s}
.gsap .timeline > li:nth-child(6)::after{transition-delay:0.92s}
.gsap .timeline > li:nth-child(7)::before{transition-delay:0.84s}
.gsap .timeline > li:nth-child(7)::after{transition-delay:1.06s}
.gsap .timeline > li:nth-child(8)::before{transition-delay:0.98s}
.gsap .timeline > li:nth-child(8)::after{transition-delay:1.20s}

/* Banner panel: settles in a moment after the page heading, and its rows follow.
   Plain CSS on load rather than GSAP, so it never waits for the library -- and
   it ends visible whether or not any script runs. */
@keyframes glanceIn{from{opacity:0; transform:translateY(12px)} to{opacity:1; transform:none}}
@keyframes rowIn{from{opacity:0; transform:translateX(-10px)} to{opacity:1; transform:none}}
.banner .glance{animation:glanceIn .7s cubic-bezier(.2,.8,.25,1) .18s both}
.banner .glance li{animation:rowIn .5s cubic-bezier(.2,.8,.25,1) both}
.banner .glance li:nth-child(1){animation-delay:.38s}
.banner .glance li:nth-child(2){animation-delay:.46s}
.banner .glance li:nth-child(3){animation-delay:.54s}
.banner .glance li:nth-child(4){animation-delay:.62s}
.banner .glance li:nth-child(5){animation-delay:.70s}
@media (prefers-reduced-motion: reduce){
  .banner .glance,.banner .glance li{animation:none}
  .gsap .timeline > li::before,.gsap .timeline > li::after{transform:none; opacity:1; transition:none}
}
.card--c:hover .card__plate{background:var(--coral-deep); color:#fff}

/* --- header entrance ----------------------------------------------------- */
@keyframes hope-head-in{from{opacity:0; transform:translateY(-6px)} to{opacity:1; transform:none}}
/* Removed. It was gated on .js, which the deferred script sets after the first
   paint -- so the header appeared, vanished and slid back in on every page. */

/* --- trust strip --------------------------------------------------------- */
.trust li{transition:transform .2s cubic-bezier(.2,.7,.3,1)}
.trust li:hover{transform:translateY(-2px)}

/* --- in-page links ------------------------------------------------------- */
.prose a,.chan a,.cred__link{
  background-image:linear-gradient(currentColor,currentColor);
  background-repeat:no-repeat;
  background-position:0 100%;
  background-size:0% 1.5px;
  transition:background-size .25s cubic-bezier(.2,.7,.3,1), color .2s;
  text-decoration:none;
}
.prose a:hover,.chan a:hover,.cred__link:hover{background-size:100% 1.5px}

/* Everything above is switched off wholesale by the reduced-motion block in
   section 3, which zeroes all animation and transition durations. */
@media (prefers-reduced-motion: reduce){
  .js [data-split] .w{opacity:1 !important; transform:none !important}
}

/* 15. WORLD REACH MAP =======================================================
   Rebuilt from design/HopeReachMap.dc.html. Geometry and layer flags come
   from tools/genreach.py; only behaviour lives in main.js.

   The rules the design fought for, kept:
     - The country interior is the only marker. No dots, no pins, no labels,
       no arcs. Emphasis is fill, never outline.
     - Strokes carry no data: one uniform hairline everywhere, cartographic.
     - Fills are set by script, not by CSS class, so the three state
       variables stay the single source of truth.
   ========================================================================== */
.reach{background:var(--cream)}

/* Contained, as the design draws it: a bordered, rounded frame sitting
   inside the page container rather than bleeding to the window edges. */
.reach__frame{
  position:relative; width:100%; margin-block:var(--s6);
  background:var(--cream);
  border:1px solid var(--line); border-radius:var(--r-lg);
  overflow:hidden;
}
.reach__svg{display:block; width:100%; height:auto; aspect-ratio:1000 / 406}

/* One hairline for every country, data-free by design. */
/* No fill here on purpose. The resting colour is a presentation attribute
   written by tools/genreach.py, so the map is correctly coloured with
   scripting off; main.js then drives state through style.fill, which beats
   both. A fill declaration in this rule would silently outrank the script. */
.reach__svg path[data-n]{stroke:#D6D1C4; stroke-width:.4}
.js .reach__svg path[data-n]{transition:fill .3s ease-out}
.reach__svg path[data-nav]{cursor:pointer}

/* Focus ring for keyboard navigation. The prototype had none — the handoff
   lists that as a gap to fix. Drawn as a stroke so it follows the country
   outline instead of boxing it. */
.reach__svg path[data-nav]:focus{outline:none}
.reach__svg path[data-nav]:focus-visible{
  outline:none; stroke:var(--teal-deep); stroke-width:2.4; paint-order:stroke;
}
.reach__hi{pointer-events:none}

.reach__legend{
  position:absolute; left:2.2%; bottom:5%; margin:0; padding:0; list-style:none;
  display:flex; flex-direction:column; gap:7px;
}
.reach__legend-head{
  font-size:9.5px; font-weight:700; letter-spacing:.16em;
  text-transform:uppercase; color:var(--muted);
}
.reach__legend li:not(.reach__legend-head){
  display:flex; align-items:center; gap:8px;
  font-size:12.5px; line-height:1.2; color:var(--charcoal);
}
/* Swatches are the exact resting map fills, so the key reads 1:1 against
   the map. Change one here and you must change REACH_LAYERS in main.js. */
.reach__swatch{
  width:17px; height:9px; border-radius:2px; flex:none;
  border:1px solid rgba(0,0,0,.06);
}
.reach__swatch--ip{background:#35646B}
.reach__swatch--tr{background:#A6B6A5}
.reach__swatch--th{background:#CF9789}
.reach__swatch--ib{background:#D9CDAE}
.reach__swatch--base{background:#DCD8CF}
.reach__key-note{color:var(--muted); font-size:11.5px}

.reach__panel{
  position:absolute; left:0; top:0; width:242px; visibility:hidden; opacity:0;
  background:var(--white); border:1px solid var(--line); border-radius:12px;
  box-shadow:var(--e2); overflow:hidden; pointer-events:none;
  transition:opacity .22s ease, transform .26s ease-out;
}
.reach__rule{height:2px; background:var(--gold)}
.reach__panel-in{padding:12px 15px 13px}
.reach__name{margin:0; font-size:16.5px; font-weight:700; line-height:1.2; color:var(--teal)}
.reach__panel-body{display:flex; flex-direction:column; gap:8px; margin-top:9px}
.reach__group-head{
  margin:0 0 4px; font-size:9.5px; font-weight:700; letter-spacing:.15em;
  text-transform:uppercase; color:var(--muted);
}
.reach__group-list{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:3px}
.reach__group-list li{display:flex; gap:7px; align-items:flex-start; font-size:12.5px; line-height:1.35}
.reach__dot{width:4px; height:4px; border-radius:50%; flex:none; margin-top:.5em; background:var(--dot)}

/* Legend filters are a cartographic key, not pills. */
.reach__filters{
  display:flex; flex-wrap:wrap; align-items:center; gap:var(--s5);
  margin-top:var(--s5); padding-top:14px; border-top:1px solid var(--line);
}
.reach__filter{
  border:0; border-bottom:1.5px solid transparent; padding:4px 0;
  background:transparent; font-family:var(--font); font-size:15px;
  color:var(--muted); cursor:pointer; min-height:44px;
}
.reach__filter:hover{color:var(--teal)}
.reach__filter[aria-pressed="true"]{color:var(--teal); border-bottom-color:var(--teal); font-weight:700}
.reach__hint{margin-left:auto; font-size:13px; color:var(--muted)}

.reach__note{margin:14px 0 0; font-size:14px; line-height:1.6; color:var(--charcoal); max-width:96ch}

/* Country lists — the keyboard/screen-reader equivalent of the map, and the
   answer to the handoff's "map is mouse-only" gap. Closed by default: the
   browser skips layout for closed details content, and 97 chips at once is
   unreadable. */
.reach__more{margin-top:var(--s5)}
.reach__more summary{
  cursor:pointer; font-weight:700; color:var(--teal); padding:.45rem 0; font-size:.95rem;
}
.reach__more summary:hover{color:var(--teal-deep)}
.reach__chips{display:flex; flex-wrap:wrap; gap:.4rem; list-style:none; margin:var(--s3) 0 0; padding:0}
.reach__chip{
  cursor:pointer; font-family:var(--font); font-size:.85rem; font-weight:700;
  color:var(--teal); background:var(--white); border:1px solid var(--line);
  border-radius:var(--r-pill); padding:.3rem .7rem; min-height:32px;
}
.reach__chip:hover,.reach__chip:focus-visible{background:var(--teal-wash); border-color:var(--teal)}
.reach__chip[aria-current="true"]{background:var(--teal); color:var(--white); border-color:var(--teal)}

@media (prefers-reduced-motion: reduce){
  .js .reach__svg path[data-n]{transition:none}
  .reach__panel{transition:none}
}

@media (max-width:640px){
  .reach__legend{position:static; margin:var(--s4) 0 0; padding:0 var(--s4) var(--s4)}
  .reach__panel{display:none}
  .reach__hint{margin-left:0; flex-basis:100%}
}

/* 16. HERO GRID ===========================================================
   The silhouette band of twelve children that used to open the hero was
   retired when the hero took a photograph; its rules and its preload went
   with it (September 2026), so no visitor downloads an image nobody sees. */
/* Two columns on desktop: words left, artwork right, both centred against
   each other. On narrow screens the art drops below the copy — it is
   decoration, so it should never push the headline off the first screen. */
.hero__grid{display:grid; gap:clamp(1.75rem,4vw,3.25rem);
  grid-template-columns:1fr; align-items:center}
@media(min-width:940px){
  .hero__grid{grid-template-columns:minmax(0,1fr) minmax(0,.95fr)}
}

/* 17. SECTION ENTRANCE =====================================================
   Every section below the fold arrives with a short fade and a 22px rise as
   it is scrolled to. Transform and opacity only — both composited, so this
   costs no layout, which matters on a page this long.

   [data-sec] is set by the script, so with JS off nothing is ever hidden.
   The hero and the credentials band are excluded: they are already on screen
   when the page loads, and animating them would just delay first paint. */
.js [data-sec]{
  /* 14px, not the 22px this used to travel: the motion budget is a written
     accessibility constraint, not a preference, and the rest of the file
     already claims to honour it. */
  opacity:0; transform:translateY(14px);
  transition:opacity .55s cubic-bezier(.2,.7,.3,1),
             transform .55s cubic-bezier(.2,.7,.3,1);
}
.js [data-sec].in{opacity:1; transform:none}

@media (prefers-reduced-motion: reduce){
  .js [data-sec]{opacity:1 !important; transform:none !important; transition:none}
}

/* 18. WHY IT MATTERS ========================================================
   The two-card index at the top of the page, and the deep banner it sits
   under. Both are specific to this page; nothing else uses them. */
.banner--deep{background:var(--teal); border-bottom:0}
.banner--deep h1{color:var(--white)}
.banner--deep .lede{color:#CBE0E4}
.banner--deep .crumbs{color:var(--stone-muted)}
.banner--deep .crumbs a{color:var(--gold-on-teal)}

.grid--two{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}

/* Why it matters: the two-part index. A small "01" label above each heading read
   as a stray caption. The numeral is now the card's anchor, set large beside
   the text, with the card's colour carried down its left edge. */
.idx{
  position:relative; display:grid; grid-template-columns:auto minmax(0,1fr); column-gap:clamp(1rem,2.5vw,1.75rem);
  align-content:start; background:var(--white); border:1px solid var(--line); border-left:5px solid var(--teal);
  border-radius:var(--r-md); padding:clamp(1.5rem,3vw,2.25rem); box-shadow:var(--e1);
  transition:transform .25s cubic-bezier(.2,.7,.3,1), box-shadow .25s ease;
}
.idx > *{grid-column:2}
.idx:hover{transform:translateY(-4px); box-shadow:var(--e2)}
.idx--gold{border-left-color:var(--gold-deep)}
.idx__n{
  grid-column:1; grid-row:1 / span 4; margin:0; line-height:.85;
  font-size:clamp(2.75rem,2rem + 2.4vw,3.9rem); font-weight:700; letter-spacing:0;
  color:var(--teal);   /* 9.13:1 on white */
}
.idx--gold .idx__n{color:var(--gold-deep)}   /* 4.87:1 */
.idx p:not(.idx__n){color:var(--muted); margin-top:var(--s3)}
.idx .more{margin-top:var(--s4)}

/* The gap in Pakistan: four sourced numbers on deep teal, between the two halves
   of the argument. Champagne on deep teal is 5.41:1 (4.53:1 on the card). */
.gap-band{background:var(--teal-deep); color:#DCEAEC}
.gap-band h2{color:#fff}
.gap-band .lede{color:#CBE0E4}
.gap-band .eyebrow{color:var(--gold-on-teal)}
.gap-stats{display:grid; gap:var(--s4); margin-top:var(--s6); grid-template-columns:1fr}
@media(min-width:640px){.gap-stats{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1100px){.gap-stats{grid-template-columns:repeat(4,minmax(0,1fr))}}
.stat.stat--gap{background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.14); border-top:3px solid var(--gold)}
.stat--gap b{color:var(--gold)}
.stat--gap span{color:#DCEAEC}
.stat--gap cite{color:#CBE0E4}
.gap-band a{color:var(--gold-on-teal)}
.gap-band a:hover{color:#fff}
.gap-band :focus-visible{outline-color:#fff}
.gap-band__foot{color:#DCEAEC; max-width:70ch}

/* Volunteer terms — a definition list read as label/value rows. */
.terms{display:grid; gap:0; margin:0}
.terms > div{
  display:grid; gap:var(--s3); padding:var(--s4) 0;
  border-bottom:1px solid var(--line); grid-template-columns:1fr;
}
@media(min-width:640px){.terms > div{grid-template-columns:minmax(0,.4fr) minmax(0,1fr); align-items:baseline}}
.terms dt{font-weight:700; color:var(--teal); margin:0}
.terms dd{margin:0; color:var(--charcoal)}
.lbl{font-weight:700; margin:0 0 var(--s3)}

/* Pointer band — a teal strip with a gold hairline that sends the reader to
   the argument rather than restating it. Used on School and Therapy. */
.pointer{background:var(--teal); border-block:1px solid var(--gold)}
.pointer h2{color:var(--white)}
.pointer .lede{color:#CBE0E4}
.pointer .eyebrow{color:var(--gold-on-teal)}
.btn--gold{background:var(--gold); color:var(--teal-deep); border-color:var(--gold)}
.btn--gold:hover,.btn--gold:focus-visible{background:var(--white); border-color:var(--white); color:var(--teal-deep)}

/* 19. HOME — DOORS, TILES, PILLS, PORTRAIT =================================
   The three-door row, the vision stat tiles and the volunteer pills, from
   the handoff's Home screen. */
.doors{display:grid; gap:var(--s5); grid-template-columns:1fr; margin-top:var(--s7)}
@media(min-width:820px){.doors{grid-template-columns:repeat(3,minmax(0,1fr))}}
.door{
  background:var(--white); border:1px solid var(--line); border-radius:16px;
  overflow:hidden; display:flex; flex-direction:column;
  transition:transform .25s cubic-bezier(.2,.7,.3,1), box-shadow .25s ease, border-color .25s ease;
}
.door:hover{transform:translateY(-4px); box-shadow:var(--e2); border-color:var(--teal)}
.door--sage:hover{border-color:var(--sage-deep)}
.door--gold:hover{border-color:var(--gold-deep)}
/* 16:10 frame. A marked placeholder until real photographs arrive — the
   handoff's 31 images are Unsplash comps and the project rule is no stock
   photography of children. */
.door__img{
  aspect-ratio:16/10; display:grid; place-items:center; text-align:center;
  padding:var(--s4); background:var(--teal-wash); color:var(--teal);
  border-bottom:2px dashed var(--teal); font-size:.86rem; font-weight:700;
}
.door--sage .door__img{background:var(--sage-wash); color:var(--sage-deep); border-bottom-color:var(--sage-deep)}
.door--gold .door__img{background:#FAF6EE; color:var(--gold-deep); border-bottom-color:var(--gold-deep)}  /* 4.52:1 — #F6F0E2 gave only 4.29 */
.door__body{padding:26px; display:flex; flex-direction:column; gap:var(--s3); flex:1}
.door__who{
  font-size:.78rem; font-weight:700; letter-spacing:.14em;
  text-transform:uppercase; color:var(--teal); margin:0;
}
.door--sage .door__who{color:var(--sage-deep)}
.door--gold .door__who{color:var(--gold-deep)}
.door h3{font-size:1.25rem}
/* .card p sets muted grey and outranks a bare class, so the labels name their parent. */
.card .door__who{color:var(--teal)}
.door__who--sage,.card .door__who--sage{color:var(--sage-deep)}
.door__who--gold,.card .door__who--gold{color:var(--gold-deep)}   /* 4.87:1 on white */

/* Adult therapy: four kinds of support, two by two. */
.grid--pair{grid-template-columns:1fr; margin-top:var(--s6)}
@media(min-width:760px){.grid--pair{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* Programmes: five cards as two over three, so none is left on a row alone. */
.progs{grid-template-columns:1fr; margin-top:var(--s6)}
@media(min-width:700px){.progs{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1024px){
  .progs{grid-template-columns:repeat(6,minmax(0,1fr))}
  .progs > :nth-child(-n+2){grid-column:span 3}
  .progs > :nth-child(n+3){grid-column:span 2}
}
.progs .more{margin-top:auto}

/* Link chips: short, scannable ways into another page. */
.chips{list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:.6rem}
.chips a{display:inline-flex; align-items:center; min-height:44px; padding:.55rem 1rem;
  background:var(--white); border:1px solid var(--line); border-radius:var(--r-pill);
  color:var(--teal); font-weight:700; text-decoration:none; box-shadow:var(--e1);
  transition:transform .2s cubic-bezier(.2,.7,.3,1), border-color .2s ease, box-shadow .2s ease}
.chips a:hover,.chips a:focus-visible{transform:translateY(-2px); border-color:var(--teal); box-shadow:var(--e2)}
.chips--lg a{font-size:1.05rem; padding:.75rem 1.2rem}
.mini--link{text-decoration:none; color:inherit; display:block}
.mini--link h3{color:var(--teal)}
.banner__acts{display:flex; flex-wrap:wrap; gap:.75rem}

/* Home: adult therapy, visible beside the three doors rather than two pages away. */
.doors__more{margin-top:var(--s5); max-width:none; padding:var(--s4) var(--s5); background:var(--white);
  border:1px solid var(--line); border-left:4px solid var(--coral-deep); border-radius:var(--r-md);
  box-shadow:var(--e1); color:var(--charcoal)}
.doors__more strong{color:var(--teal)}
.doors__more .more{padding-top:0; margin-left:.35rem; white-space:nowrap}

/* Volunteer: the photograph sits beside the text at a sensible size instead of
   spanning the page at nearly 800px tall. */
.photo.photo--side{aspect-ratio:4/3; max-height:none; margin:0}
.photo.photo--side img{width:100%; height:100%; object-fit:cover}
@media(min-width:760px){.ticks--cols{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--s3) var(--s6)}}

/* Getting therapy -- three ways in, one row. */
.access{grid-template-columns:1fr; margin-top:var(--s6)}
@media(min-width:880px){.access{grid-template-columns:repeat(3,minmax(0,1fr))}}
.access .card .more{margin-top:auto}
.access__small{font-size:.92rem}
.card--gold .card__plate{background:#FDF8E8; color:var(--gold-deep)}   /* icon 4.59:1 */
.card--gold:hover{border-color:var(--gold-deep)}

/* What to expect -- the path as a numbered line beside the photograph, rather
   than two sections that each told half of it. */
.expect{display:grid; gap:clamp(2rem,5vw,4rem); grid-template-columns:1fr}
@media(min-width:880px){.expect{grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr); align-items:start}}
.expect__intro .photo{margin-top:var(--s5)}
.timeline{list-style:none; margin:0; padding:0; counter-reset:step; position:relative}
.timeline li{counter-increment:step; position:relative; padding:0 0 var(--s5) 3.75rem}
.timeline li:last-child{padding-bottom:0}
.timeline li::before{
  content:counter(step); position:absolute; left:0; top:-.1rem;
  width:2.5rem; height:2.5rem; border-radius:50%; background:var(--teal); color:#fff;
  display:grid; place-items:center; font-weight:700;
}
/* The connecting rule is decoration; the numbers carry the order. */
.timeline li:not(:last-child)::after{
  content:""; position:absolute; left:1.2rem; top:2.6rem; bottom:.2rem;
  width:2px; background:var(--line);
}
.timeline h3{font-size:1.15rem; color:var(--teal)}
.timeline p{margin-top:.3rem; color:var(--muted)}

/* Closing band on teal: the words and the two ways to reach us in one centred
   column. Side by side, the buttons sat alone at the far right of the wrap with
   a wide empty gap between them and the words they answer. */
.pointer{padding-block:clamp(2.5rem,5vw,4rem)}
.cta-band{display:flex; flex-direction:column; align-items:center; gap:var(--s5); text-align:center}
.cta-band > div{max-width:46rem}
.cta-band > div > *{margin-inline:auto}
.cta-band__acts{display:flex; flex-wrap:wrap; justify-content:center; gap:.75rem; margin:0}
.btn--on-teal{background:transparent; color:#fff; border-color:rgba(255,255,255,.75)}   /* 9.13:1 */
.btn--on-teal:hover,.btn--on-teal:focus-visible{background:#fff; color:var(--teal-deep); border-color:#fff}
/* Links inside a closing band -- gold-on-teal is the token for small text on teal (4.85:1). */
/* Any text in a band, not just the lede -- separators between links included (6.66:1). */
.pointer p{color:#CBE0E4}
.pointer a:not(.btn){color:var(--gold-on-teal)}
.pointer a:not(.btn):hover{color:#fff}

/* Split: an introduction on the left, the list, FAQ or map it introduces on the
   right. Several sections were one 68ch column centred in a 1320px wrap -- a
   third of the width used and the page made twice as tall to hold it. The copy
   and its order are unchanged; on a phone this is the same single column. */
.split{display:grid; gap:var(--s5) clamp(2rem,5vw,4.5rem); grid-template-columns:1fr}
@media(min-width:960px){
  .split{grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr); align-items:start}
  .split--media{align-items:center}
}
.split__body > :first-child{margin-top:0}
.split__intro p{max-width:none}
.split__body .note{max-width:none}

/* School: the funded-places card is one centred column, its two actions under
   the argument they follow rather than stranded at the card's right edge. */
.vision{text-align:center}
.vision > *{margin-inline:auto}
.vision > p{max-width:60ch}
.vision__acts{justify-content:center}

/* The site's teal focus ring vanishes on a teal band. White is 9.13:1 against it. */
.pointer :focus-visible,.foot :focus-visible,.banner--deep :focus-visible{outline-color:#fff}
.door p{color:var(--muted); font-size:.98rem; flex:1}
.door .more{margin-top:auto}

/* Vision stat tiles — white, 3px top rule alternating teal and gold. */
/* 2x2, as the handoff draws it — auto-fit gave a 3+1 row at this width. */
.tiles{
  display:grid; gap:var(--s4); list-style:none; margin:0; padding:0;
  grid-template-columns:1fr;
}
@media(min-width:520px){.tiles{grid-template-columns:repeat(2,minmax(0,1fr))}}
.tile{
  background:var(--white); border:1px solid var(--line);
  border-top:3px solid var(--teal); border-radius:var(--r-md); padding:var(--s5);
}
.tile--gold{border-top-color:var(--gold)}
.tile b{display:block; font-size:clamp(1.7rem,4vw,2.3rem); line-height:1.05; color:var(--teal); font-weight:700}
.tile--gold b{color:var(--gold-deep)}
.tile span{display:block; margin-top:var(--s3); font-size:.92rem; color:var(--charcoal)}

/* Volunteer route pills — labels, not links. */
.pills{display:flex; flex-wrap:wrap; gap:.5rem; list-style:none; margin:0; padding:0}
.pills li{
  border:1px solid var(--line); border-radius:var(--r-pill);
  padding:.4rem .9rem; font-size:.9rem; font-weight:700; color:var(--teal);
  background:var(--white);
}

/* Founder portrait — the one genuinely real photograph on the site. */
.portrait{display:block; max-width:320px; width:100%}
.portrait img{
  display:block; width:100%; height:auto; border-radius:18px;
  border:1px solid var(--line);
}

/* 20. PHOTO FRAMES =========================================================
   Images sit in a fixed-ratio frame so the page never reflows as they load;
   every one carries width/height or an aspect-ratio, and CLS stays at 0.

   .frame--comp marks a placeholder. These are the handoff's Unsplash comps,
   downloaded so the site can be seen as designed — they are NOT photographs
   of this centre, and the project rule is no stock photography of children.
   The badge is deliberately visible: remove the class, not the marker, when
   real photography replaces them. See assets/img/comps/CREDITS.md. */
.frame{position:relative; overflow:hidden; border-radius:18px; background:var(--sunk)}
.frame[data-ratio="16/10"]{aspect-ratio:16/10}
.frame img,.door__img img,.photo img,.gal img{
  width:100%; height:100%; object-fit:cover; display:block;
}
.frame--comp{position:relative}
/* The "placeholder" badge that sat on all 31 photographs is gone at the
   owner's instruction. .frame--comp itself stays: it still carries the
   aspect-ratio and overflow rules the layout depends on, and it still marks
   which images are not the centre's own -- which is what the credits owe.
   See site/assets/img/comps/CREDITS.md. */
/* The frames these replace were dashed placeholder boxes; with a photograph
   in them the dashes and the centred label are no longer wanted. */
/* flex:none matters: .door is a column flex container, and without it the
   image frame can be stretched past its aspect ratio when the grid equalises
   card heights — which made one door's photo twice the height of its
   neighbours'. */
.door__img.frame--comp,.photo.frame--comp{
  border:0; border-bottom:0; padding:0; display:block; background:var(--sunk);
  overflow:hidden; flex:none;
}
.door__img.frame--comp{aspect-ratio:16/10}
.photo.frame--comp{aspect-ratio:4/3; border-radius:18px; overflow:hidden}
.gal .frame--comp{aspect-ratio:auto; height:100%; min-height:168px; border:0; padding:0; border-radius:var(--r-md); overflow:hidden}

/* 21. MOTION, SECOND PASS ==================================================
   Richer interaction without leaving the budget: everything here is user- or
   scroll-initiated, moves 14px or less, and animates only transform, opacity,
   background-size or fill. Nothing loops, pins, parallaxes or autoplays.

   GSAP is in package.json but is deliberately not shipped. It is 72KB, and
   the things it is good at — timeline scrubbing, pinning, parallax — are the
   things this audience's motion budget rules out. Every effect below is a
   CSS transition the browser composites on its own thread. */

/* Photographs settle rather than snap: a 1.5% scale is well under 14px at
   any frame size on this page, and it only ever runs on hover. */
.frame--comp img,.door__img img,.gal .frame--comp img{
  transition:transform .5s cubic-bezier(.2,.7,.3,1);
}
.door:hover .door__img img,
.gal .frame--comp:hover img,
.photo.frame--comp:hover img{transform:scale(1.015)}

/* Stat tiles and doors lift on hover, like the cards already do. */
.tile{transition:transform .25s cubic-bezier(.2,.7,.3,1), box-shadow .25s ease}
.tile:hover{transform:translateY(-3px); box-shadow:var(--e2)}
.pills li{transition:transform .2s cubic-bezier(.2,.7,.3,1), border-color .2s ease}
.pills li:hover{transform:translateY(-2px); border-color:var(--teal)}

/* Credential card: the seal turns up a fraction after the card. */
.cred{transition:transform .3s cubic-bezier(.2,.7,.3,1), box-shadow .3s ease}
.cred:hover{transform:translateY(-2px); box-shadow:var(--e2)}

/* The trust strip used to start at opacity 0 and wait for .band.in. Nothing
   ever set it: main.js skips .band when it marks sections, on the grounds
   that the strip is above the fold and animating it only delays first paint.
   So the four items never appeared and the strip rendered as an empty white
   band between two hairlines. It is above the fold -- it is simply there. */

/* The header gains a hairline shadow once the page has moved. */
.head{transition:box-shadow .25s ease}
.head.is-stuck{box-shadow:0 1px 0 var(--line),0 6px 18px rgba(23,79,89,.06)}

/* Ghost buttons fill from the left like the primary ones do. */
.btn--ghost{
  background-image:linear-gradient(var(--teal-wash),var(--teal-wash));
  background-repeat:no-repeat; background-size:0% 100%;
  transition:background-size .3s cubic-bezier(.2,.7,.3,1),
             transform .2s cubic-bezier(.2,.7,.3,1), border-color .2s ease;
}
.btn--ghost:hover,.btn--ghost:focus-visible{background-size:100% 100%; transform:translateY(-2px)}

@media (prefers-reduced-motion: reduce){
  .frame--comp img,.door__img img,.gal .frame--comp img,
  .tile,.pills li,.cred,.head,.btn--ghost{transition:none}
  .door:hover .door__img img,.gal .frame--comp:hover img,
  .photo.frame--comp:hover img{transform:none}
}

/* 22. CARD, BANNER AND TRIO MEDIA ==========================================
   Media slots the design already draws: a photograph on each service and
   pathway card, a banner image on Volunteer, and the three-up row in "Lend a
   hand". No new sections — these fill frames the layout already had. */
/* .card pads with --s6, so the bleed must be --s6 too — with --s5 the
   photograph stopped short of the card's right edge. */
.card__img{
  margin:calc(var(--s6) * -1) calc(var(--s6) * -1) var(--s4);
  aspect-ratio:16/10; overflow:hidden; border-radius:var(--r-md) var(--r-md) 0 0;
  background:var(--sunk); flex:none;
}
.card__img img{width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .5s cubic-bezier(.2,.7,.3,1)}
.card:hover .card__img img{transform:scale(1.03)}

.banner__media{
  /* A cinematic strip rather than a slab. At 21:9 across a 1320px wrap this
     photograph stood 566px tall and pushed the page's first real sentence
     below the fold. The ratio is kept for narrow screens, where it is only
     167px; the cap does the work at desktop. Cropping is object-fit's job,
     so nothing is scaled or distorted. */
  margin:var(--s4) 0; aspect-ratio:21/9; max-height:clamp(220px,32vh,340px);
  overflow:hidden; border-radius:18px; background:var(--sunk);
}
.banner__media img{width:100%; height:100%; object-fit:cover; display:block}

.trio{display:grid; gap:var(--s4); grid-template-columns:1fr}
@media(min-width:760px){.trio{grid-template-columns:repeat(3,minmax(0,1fr))}}
.trio .frame{aspect-ratio:16/9}

@media (prefers-reduced-motion: reduce){
  .card__img img{transition:none}
  .card:hover .card__img img{transform:none}
}

/* The founder portrait is used exactly once, on About, which is the
   leadership page. Home keeps the summary and the credential card, laid out
   as a single column so the space the portrait used to occupy closes up
   rather than being left empty. */
.founder-brief{display:grid; gap:var(--s5)}
.founder-brief .prose{max-width:76ch}
.founder-brief .cred{max-width:640px}

/* 23. FOUNDER STORY ========================================================
   Editorial column. Narrower measure than the rest of the site because this
   is the longest continuous read on it — roughly 62 characters a line, which
   is where sustained prose stays comfortable. */
/* Centred, not left-pinned: at 1320px a left-aligned 68ch column leaves the
   whole right half of the section empty. Long-form prose is the one place a
   centred measure is the editorial convention rather than a compromise. */
.story{max-width:68ch; margin-inline:auto}
.story p{max-width:none}
/* The founder's story is an essay, so the measure stays at 68ch -- widening it
   would cost readability. What changes on a wide screen is the empty margin: each
   pull quote floats into it, level with the passage it comes from. The negative
   right margin takes the quote's whole box out of the column, so the text keeps
   its full measure and does not wrap around it. From 1320px, where the margin is
   wide enough to hold a quote (about 550px free beside a 647px column). */
@media(min-width:1320px){
  .story--essay{margin-left:5rem; margin-right:auto}
  .story--essay > .pull{float:right; clear:right; width:24rem; margin:.4rem calc(-24rem - 3.5rem) 1.5rem 0}
  .story--essay::after{content:""; display:block; clear:both}
}

/* Pull quote. Gold rule on the left, generous space around it; the quote is
   the one place the page slows down. */
.pull{
  margin:clamp(2.25rem,5vw,3.25rem) 0; padding:0 0 0 clamp(1.25rem,3vw,2rem);
  border-left:3px solid var(--gold);
}
.pull p{
  margin:0; font-size:clamp(1.25rem,1.05rem + .9vw,1.7rem); line-height:1.4;
  color:var(--teal); font-style:italic; max-width:34ch;
}
.pull cite{
  display:block; margin-top:var(--s4); font-style:normal; font-size:.86rem;
  font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  color:var(--muted);
}

/* 24. TOUCH TARGETS ========================================================
   WCAG 2.2 SC 2.5.8 asks for a 24x24 CSS-pixel minimum on pointer targets.
   axe does not test this rule by default, so these three were passing the
   automated audit while failing the criterion — found by measuring every
   interactive element at 390px.

   Inline links inside running prose are exempt under the criterion, so body
   copy is deliberately left alone. */

/* Consent and choice checkboxes were 20x20. */
.consent input[type="checkbox"],
.choice input[type="checkbox"]{width:24px; height:24px}

/* Footer bar links sat at 16px tall. Padding lifts the hit area without
   moving anything visually. */
.foot__bar a{display:inline-block; padding-block:4px}

/* The scroll cue was 22px tall. */
.cue{min-height:24px; align-items:center}

/* 25. REACH HEAD, FIGURES AND COVERAGE COLUMNS =============================
   The layout around the map, from the design. The map component itself is
   untouched — this is only what sits above and below it. */
.reach__head{display:grid; gap:clamp(1.5rem,4vw,3rem); grid-template-columns:1fr}
@media(min-width:900px){
  .reach__head{grid-template-columns:minmax(0,1.35fr) minmax(0,1fr); align-items:start}
}
.reach__figures{
  display:grid; gap:var(--s5); list-style:none; margin:0; padding:0;
  grid-template-columns:repeat(3,minmax(0,1fr));
}
@media(max-width:520px){.reach__figures{grid-template-columns:1fr}}
.reach__figures b{
  display:block; font-size:clamp(2rem,1.4rem + 2.4vw,3rem); line-height:1;
  color:var(--teal); font-weight:700;
}
.reach__figures span{
  display:block; margin-top:var(--s3); font-size:.86rem; line-height:1.35;
  color:var(--muted);
}

/* The four country lists said again, in words, what the map and the three
   figures above it already say. They now sit behind one click. <details> means
   they are there with no JS and reachable from the keyboard; opening staggers
   the columns in, transform and opacity only, once. */
.reach__more{margin-top:var(--s5); border-top:1px solid var(--line)}
.reach__more > summary{
  cursor:pointer; list-style:none; display:flex; align-items:center; gap:.6rem;
  padding:var(--s5) 0; min-height:48px;
  font-size:1rem; font-weight:700; color:var(--teal);
}
.reach__more > summary::-webkit-details-marker{display:none}
.reach__more > summary:hover,.reach__more > summary:focus-visible{color:var(--teal-deep)}
.reach__chev{width:18px; height:18px; flex:none; transition:transform .3s cubic-bezier(.2,.75,.3,1)}
.reach__more[open] > summary .reach__chev{transform:rotate(180deg)}
.reach__more[open] .reach__col{animation:reachCol .45s cubic-bezier(.2,.75,.3,1) both}
.reach__more[open] .reach__col:nth-child(2){animation-delay:.06s}
.reach__more[open] .reach__col:nth-child(3){animation-delay:.12s}
.reach__more[open] .reach__col:nth-child(4){animation-delay:.18s}
@keyframes reachCol{from{opacity:0; transform:translateY(10px)} to{opacity:1; transform:none}}
@media(prefers-reduced-motion:reduce){
  .reach__chev{transition:none}
  .reach__more[open] .reach__col{animation:none}
}

.reach__cols{
  display:grid; gap:var(--s5) var(--s6); margin-top:0;
  padding-top:0; border-top:0;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,215px),1fr));
}
.reach__col h3{font-size:1rem; color:var(--teal)}
.reach__sub{margin:.25rem 0 0; font-size:.82rem; color:var(--muted); line-height:1.4}
.reach__names{list-style:none; margin:var(--s4) 0 0; padding:0;
  display:flex; flex-direction:column; gap:.3rem; font-size:.92rem}
.reach__names li{color:var(--charcoal)}
/* Country names stay clickable — they pin the country on the map — but read
   as text rather than as buttons, which is how the design prints them. */
.reach__name{
  background:none; border:0; padding:2px 0; margin:0; font:inherit;
  color:var(--charcoal); cursor:pointer; text-align:left; min-height:24px;
  border-bottom:1px solid transparent;
}
.reach__name:hover,.reach__name:focus-visible{color:var(--teal); border-bottom-color:var(--teal)}
.reach__name[aria-current="true"]{color:var(--teal); font-weight:700; border-bottom-color:var(--teal)}
.reach__plus{color:var(--muted); font-size:.82rem}

/* 26. FOOTER, SECOND PASS ==================================================
   Was four plain lists with browser-default underlines. Now a brand column
   with the mark and the tagline, three link columns, and a quieter legal
   bar. Underlines are drawn on hover rather than sitting there by default. */
.foot__grid{
  display:grid; gap:clamp(2rem,4vw,3.5rem);
  grid-template-columns:1fr;
}
@media(min-width:700px){.foot__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1000px){
  .foot__grid{grid-template-columns:minmax(0,1.4fr) repeat(4,minmax(0,1fr))}
}
.foot__logo{
  display:inline-flex; align-items:center; gap:.7rem; text-decoration:none;
  color:#fff; font-weight:700; font-size:1.12rem; margin-bottom:var(--s4);
}
.foot__logo img{width:60px; height:auto}
.foot__brand p{max-width:44ch}
.foot__tag{
  margin-top:var(--s4); font-style:italic; color:var(--gold-on-teal);
  font-size:1rem;
}
.foot__addr{margin-top:var(--s4); font-size:.9rem}

/* Underline on hover, not at rest. */
.foot a{
  color:#CFE6EA; text-decoration:none;
  background-image:linear-gradient(currentColor,currentColor);
  background-repeat:no-repeat; background-position:0 100%;
  background-size:0 1px;
  transition:background-size .25s cubic-bezier(.2,.7,.3,1), color .2s ease;
}
.foot a:hover,.foot a:focus-visible{color:#fff; background-size:100% 1px}
.foot__logo:hover{background-size:0 1px}

.foot__legal{display:flex; flex-wrap:wrap; gap:var(--s5)}

@media (prefers-reduced-motion: reduce){
  .foot a{transition:none}
}

/* 27. FAQ ==================================================================
   Native <details>, so it works without JavaScript and a browser's find-in-
   page can still reach closed answers. */
.faq{border-top:1px solid var(--line)}
.faq__item{border-bottom:1px solid var(--line)}
.faq__item summary{
  cursor:pointer; list-style:none; padding:var(--s5) 2.5rem var(--s5) 0;
  font-size:1.06rem; font-weight:700; color:var(--teal); position:relative;
  min-height:48px;
}
.faq__item summary::-webkit-details-marker{display:none}
.faq__item summary::after{
  content:""; position:absolute; right:.5rem; top:50%;
  width:11px; height:11px; margin-top:-7px;
  border-right:2px solid currentColor; border-bottom:2px solid currentColor;
  transform:rotate(45deg); transition:transform .25s cubic-bezier(.2,.7,.3,1);
}
.faq__item[open] summary::after{transform:rotate(-135deg); margin-top:-3px}
.faq__item summary:hover,.faq__item summary:focus-visible{color:var(--teal-deep)}
.faq__item p{padding:0 0 var(--s4); color:var(--charcoal); max-width:70ch}
@media (prefers-reduced-motion: reduce){
  .faq__item summary::after{transition:none}
}

/* 28. FIRST STEPS GUIDE ====================================================
   A routing form, not a screener. Nothing is scored and nothing is stored. */
.choices--stack{grid-template-columns:1fr}
/* The questionnaire: nine options in one 68ch column made it the tallest thing
   on the page. Wider, the long options sit two abreast. */
.story--tool{max-width:62rem}
@media(min-width:900px){.story--tool .choices--stack{grid-template-columns:1fr 1fr}}
.steps-form legend{
  font-weight:700; color:var(--teal); font-size:1.05rem; padding:0;
  margin-bottom:var(--s4);
}
.steps-form fieldset{border:0; padding:0; margin:0}

.result{
  background:var(--white); border:1px solid var(--line);
  border-top:3px solid var(--teal); border-radius:var(--r-md);
  padding:clamp(1.5rem,3.5vw,2.5rem);
}
.result:focus{outline:3px solid var(--teal); outline-offset:3px}
.result h2{font-size:clamp(1.4rem,1.2rem + 1vw,1.9rem)}
.result__list{display:grid; gap:var(--s5); margin-top:var(--s5)}
.result__item{
  padding:var(--s5); border:1px solid var(--line); border-radius:var(--r-md);
  background:var(--sunk);
}
.result__item h3{font-size:1.08rem; color:var(--teal)}
.result__item p{margin-top:var(--s3); color:var(--charcoal)}

/* Map embed. A fixed ratio so the third-party frame cannot shift the page as
   it loads, and lazy so it is not fetched until scrolled to. */
.mapwrap{
  /* The Google embed -- not the reach map, which is frozen. At 16/9 across the
     wrap it stood 742px tall, most of the section it sits in, to show a place
     marker. Capped; the embed reflows to whatever box it is given. */
  position:relative; aspect-ratio:16/9; max-height:clamp(260px,44vh,440px);
  overflow:hidden;
  border:1px solid var(--line); border-radius:18px; background:var(--sunk);
}
@media(max-width:640px){.mapwrap{aspect-ratio:4/3}}
.mapwrap iframe{position:absolute; inset:0; width:100%; height:100%; border:0}

/* Two centres, a card each: the map, the coordinates, and the two ways to get
   there. The cards carry equal weight -- neither centre is the lesser one. */
.places{display:grid; gap:clamp(1.5rem,4vw,2.5rem); grid-template-columns:1fr; margin-top:var(--s6)}
@media(min-width:880px){.places{grid-template-columns:repeat(2,minmax(0,1fr))}}
.place h3{font-size:clamp(1.2rem,1.05rem + .6vw,1.5rem); color:var(--teal); margin-bottom:var(--s3)}
.place__coords{margin-top:var(--s3); font-size:.9rem; color:var(--muted); font-variant-numeric:tabular-nums}
.place__acts{display:flex; flex-wrap:wrap; gap:.75rem; margin-top:var(--s3)}
@media(max-width:699px){.place__acts .btn{flex:1 1 100%}}

/* 29. PORTAL ===============================================================
   A hub, not an account area. The three routes are the same three the site
   already has; this page gathers them, says what each one needs, and adds a
   short form for people who would rather talk. */
.portal__h{
  font-size:.78rem; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--muted); margin-top:var(--s4);
}
.ticks--tight{margin-top:var(--s3); gap:.4rem}
.ticks--tight li{font-size:.92rem}
.ticks--tight svg{width:15px; height:15px}
.portal__no{
  margin-top:var(--s4); font-size:.9rem; color:var(--muted);
  padding-top:var(--s3); border-top:1px solid var(--line);
}
.portal__no strong{color:var(--charcoal)}

/* 31. HERO GROWTH MOTIF ====================================================
   Replaces the silhouette band. Four strands — therapy, education, family,
   training — rise from one root and meet in a single canopy, which is the
   argument the whole site makes, drawn rather than stated.

   Built in SVG rather than sourced: it is on-palette, weighs nothing, stays
   sharp at any size, and needs no photograph of a child. */
.growth{margin:0; width:100%; max-width:520px; justify-self:center}
.growth__svg{display:block; width:100%; height:auto; overflow:visible}

.growth__ground{stroke:var(--line); stroke-width:2; fill:none; stroke-linecap:round}
.growth__stem{stroke:var(--sage-deep); stroke-width:3; fill:none; stroke-linecap:round}

.growth__arc{
  fill:none; stroke-width:2.5; stroke-linecap:round;
  opacity:.55; transition:opacity .3s ease, stroke-width .3s ease;
}
.growth__arc[data-arc="therapy"]{stroke:var(--teal)}
.growth__arc[data-arc="education"]{stroke:var(--sage-deep)}
.growth__arc[data-arc="family"]{stroke:var(--coral-deep)}
.growth__arc[data-arc="training"]{stroke:var(--gold-deep)}

.growth__leaf{
  opacity:.5; transition:opacity .3s ease, transform .3s cubic-bezier(.2,.7,.3,1);
  transform-box:fill-box; transform-origin:center;
}
.growth__leaf[data-arc="therapy"]{fill:var(--teal)}
.growth__leaf[data-arc="education"]{fill:var(--sage)}
.growth__leaf[data-arc="family"]{fill:var(--coral)}
.growth__leaf[data-arc="training"]{fill:var(--gold)}
.growth__core{fill:var(--cream); stroke:var(--teal); stroke-width:2.5; opacity:.9}

/* Focus or hover a strand and the rest step back. Opacity only — nothing
   moves more than a hair, and nothing loops. */
.growth.is-on .growth__arc,
.growth.is-on .growth__leaf{opacity:.14}
.growth.is-on .growth__arc.on{opacity:1; stroke-width:3.5}
.growth.is-on .growth__leaf.on{opacity:.85; transform:scale(1.06)}

.growth__cap{margin-top:var(--s5)}
.growth__key{
  display:flex; flex-wrap:wrap; gap:.35rem var(--s4);
  list-style:none; margin:0; padding:0; justify-content:center;
}
.growth__key button{
  display:inline-flex; align-items:center; gap:.45rem; min-height:32px;
  background:none; border:0; padding:.25rem .1rem; cursor:pointer;
  font-family:var(--font); font-size:.9rem; color:var(--muted);
  border-bottom:1.5px solid transparent;
}
.growth__key button:hover,.growth__key button:focus-visible{color:var(--teal); border-bottom-color:var(--teal)}
.growth__sw{width:11px; height:11px; border-radius:50%; flex:none}
.growth__sw--therapy{background:var(--teal)}
.growth__sw--education{background:var(--sage-mid)}
.growth__sw--family{background:var(--coral)}
.growth__sw--training{background:var(--gold)}
.growth__note{
  margin-top:var(--s3); text-align:center; font-size:.86rem; color:var(--muted);
  min-height:2.6em;
}

@media (prefers-reduced-motion: reduce){
  .growth__arc,.growth__leaf{transition:none}
  .growth.is-on .growth__leaf.on{transform:none}
}

/* 32. PORTAL PANEL =========================================================
   The signed-in area. Deliberately plain: this is somewhere a parent reads
   their child's plan, not somewhere to show off. */
.panel{
  background:var(--white); border:1px solid var(--line);
  border-top:3px solid var(--teal); border-radius:var(--r-md);
  padding:clamp(1.5rem,4vw,2.5rem);
}
.panel__head{display:flex; flex-wrap:wrap; gap:var(--s4); align-items:start; justify-content:space-between}
.signin{max-width:34rem}

.pblock{margin-top:var(--s6); padding-top:var(--s5); border-top:1px solid var(--line)}
.pblock:first-child{margin-top:0; padding-top:0; border-top:0}
.pblock h3{font-size:1.15rem; color:var(--teal)}
.pblock__blurb{margin-top:var(--s3); color:var(--muted); font-size:.94rem}
.pblock__empty{margin-top:var(--s4); color:var(--muted); font-style:italic}

.prow{
  margin-top:var(--s4); padding:var(--s4); border:1px solid var(--line);
  border-radius:var(--r-sm); background:var(--sunk);
}
.prow strong{display:block; color:var(--charcoal)}
.prow p{margin-top:.35rem; font-size:.94rem; color:var(--charcoal)}
.prow__meta{color:var(--muted); font-size:.86rem}
.prow__task{
  margin-top:var(--s3); padding-top:var(--s3);
  border-top:1px dashed var(--line); font-size:.92rem;
}
.prow__tag{
  display:inline-block; margin-bottom:.4rem; font-size:.7rem; font-weight:700;
  letter-spacing:.12em; text-transform:uppercase; color:var(--teal);
  background:var(--teal-wash); border-radius:var(--r-pill); padding:.2rem .6rem;
}
.prow__tag--funded{color:var(--sage-deep); background:var(--sage-wash)}
.prow__tag--pending{color:var(--gold-deep); background:#FAF6EE}
.prow__tag--cancelled,.prow__tag--missed{color:var(--coral-deep); background:var(--coral-wash)}

.pbar{margin-top:var(--s4); height:8px; border-radius:99px; background:var(--line); overflow:hidden}
.pbar__fill{height:100%; background:var(--teal); border-radius:99px}

/* 33. THERAPY SELECTOR =====================================================
   Four cards act as tabs; one panel below reveals the detail. This replaces
   an accordion inside each card, which pushed the page around and made the
   four therapies impossible to compare.

   The panel reveals the way the Start here result does — same gesture, so
   the site behaves consistently. */
.svc-cards{
  display:grid; gap:var(--s4); grid-template-columns:1fr;
}
@media(min-width:640px){.svc-cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1000px){.svc-cards{grid-template-columns:repeat(4,minmax(0,1fr))}}

.svc-card{
  display:flex; flex-direction:column; text-align:left; padding:0; cursor:pointer;
  background:var(--white); border:1px solid var(--line); border-radius:14px;
  overflow:hidden; font-family:var(--font); color:inherit;
  transition:transform .28s cubic-bezier(.2,.7,.3,1),
             box-shadow .28s ease, border-color .28s ease;
}
.svc-card:hover{transform:translateY(-4px); box-shadow:var(--e2)}
.svc-card__img{display:block; aspect-ratio:16/10; overflow:hidden; background:var(--sunk)}
.svc-card__img img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .55s cubic-bezier(.2,.7,.3,1);
}
.svc-card:hover .svc-card__img img{transform:scale(1.04)}
.svc-card__body{display:flex; flex-direction:column; gap:.4rem; padding:var(--s5); flex:1}
.svc-card__title{font-size:1.08rem; font-weight:700; color:var(--teal)}
.svc-card__helps{font-size:.88rem; color:var(--muted); line-height:1.45; flex:1}
.svc-card__more{
  font-size:.86rem; font-weight:700; color:var(--teal); margin-top:var(--s3);
  display:inline-flex; align-items:center; gap:.35rem;
}
.svc-card__more::after{content:"\2192"; transition:transform .25s ease}
.svc-card:hover .svc-card__more::after{transform:translateX(3px)}

/* Selected card: a teal edge and a filled indicator, so the link between the
   card and the panel below is unmistakable. */
.svc-card[aria-selected="true"]{
  border-color:var(--teal); box-shadow:var(--e2);
  outline:2px solid var(--teal); outline-offset:-2px;
}
.svc-card[aria-selected="true"] .svc-card__more{color:var(--teal-deep)}
.svc-card[aria-selected="true"] .svc-card__more::after{transform:rotate(90deg)}
.svc-card--sage[aria-selected="true"]{border-color:var(--sage-deep); outline-color:var(--sage-deep)}
.svc-card--gold[aria-selected="true"]{border-color:var(--gold-deep); outline-color:var(--gold-deep)}

.svc-detail{
  margin-top:var(--s5); padding:clamp(1.5rem,4vw,2.5rem);
  background:var(--sunk); border:1px solid var(--line);
  border-top:3px solid var(--teal); border-radius:var(--r-md);
}
.svc-detail:focus-visible{outline:3px solid var(--teal); outline-offset:3px}
.svc-detail h3{font-size:clamp(1.3rem,1.1rem + .9vw,1.75rem); color:var(--teal)}
.svc-detail__grid{display:grid; gap:var(--s5); margin-top:var(--s5); grid-template-columns:1fr}
@media(min-width:800px){.svc-detail__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
.svc-detail__block h4{
  font-size:.76rem; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--sage-deep);
}
.svc-detail__block p{margin-top:.45rem; font-size:.96rem; color:var(--charcoal)}
.svc-detail__cta{margin-top:var(--s6)}

/* The reveal itself. Blocks arrive in sequence rather than all at once, which
   is what makes it read as a considered answer instead of a page jump. */
.js .svc-detail.is-swapping{opacity:0; transform:translateY(8px)}
.js .svc-detail{
  opacity:1; transform:none;
  transition:opacity .3s ease, transform .3s cubic-bezier(.2,.7,.3,1);
}
/* Panels are hidden at load, so a visible one is always one the visitor
   opened. Without scripting they are all visible and this start state must
   not apply. */
.js .svc-detail__block{opacity:0; transform:translateY(10px)}
.js .svc-detail.is-in .svc-detail__block{
  opacity:1; transform:none;
  transition:opacity .45s ease-out, transform .45s cubic-bezier(.2,.7,.3,1);
}
.js .svc-detail.is-in .svc-detail__block:nth-child(2){transition-delay:.07s}
.js .svc-detail.is-in .svc-detail__block:nth-child(3){transition-delay:.14s}
.js .svc-detail.is-in .svc-detail__block:nth-child(4){transition-delay:.21s}

@media (prefers-reduced-motion: reduce){
  .svc-card,.svc-card__img img,.svc-detail,.svc-detail__block{transition:none}
  .svc-card:hover{transform:none}
  .svc-card:hover .svc-card__img img{transform:none}
  .js .svc-detail__block{opacity:1; transform:none}
}

/* Links on the deep teal banner. Without this they inherit --teal, which is
   the banner's own background: 1:1, and axe caught it. */
.banner--deep a{color:var(--gold-on-teal); text-decoration-color:rgba(211,186,136,.5)}
.banner--deep a:hover,.banner--deep a:focus-visible{color:#fff; text-decoration-color:#fff}

/* 34. HERO PHOTOGRAPH ======================================================
   The design's own hero image, in the hero. Framed rather than floated: a
   soft-stone mat, a generous radius, and a gold hairline that ties it to the
   credential accent used elsewhere.

   width and height are on the img and the frame has a fixed ratio, so this
   cannot shift the page as it loads — it is the largest element above the
   fold and therefore the LCP candidate. */
.hero__art{margin:0; width:100%; max-width:560px; justify-self:center}
.hero__frame{
  position:relative; aspect-ratio:4/3; overflow:hidden;
  border-radius:20px; background:var(--sunk);
  box-shadow:var(--e2);
}
.hero__frame::after{
  content:""; position:absolute; inset:0; border-radius:20px; pointer-events:none;
  border:1px solid rgba(23,79,89,.12);
  box-shadow:inset 0 0 0 4px var(--cream), inset 0 0 0 5px rgba(200,169,107,.55);
}
.hero__frame img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:transform 1.1s cubic-bezier(.2,.7,.3,1);
}
.hero__art:hover .hero__frame img{transform:scale(1.03)}
.hero__cap{
  margin-top:var(--s4); font-size:.82rem; color:var(--muted);
  display:flex; align-items:center; gap:.5rem; flex-wrap:wrap;
}
.hero__cap-tag{
  font-size:.66rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
  background:var(--teal-deep); color:#fff; border-radius:4px; padding:.2rem .45rem;
}

/* Arrival: the frame settles rather than snapping in. Runs once, on load. */
@media (prefers-reduced-motion: no-preference){
  .hero__art{animation:heroSettle .9s cubic-bezier(.16,1,.3,1) both .15s}
}
@keyframes heroSettle{
  from{opacity:0; transform:translateY(12px) scale(.985)}
  to{opacity:1; transform:none}
}

/* 35. MAP ARRIVAL ==========================================================
   Countries settle into place the first time the map is scrolled to. This is
   presentation only: no fill, no layer flag, no interaction and no data is
   touched. The script sets --dx/--dy per country and the transition does the
   rest.

   The motion budget says 14px, and it exists because this audience includes
   autistic children. A hundred countries flying across the screen would
   break it, so the drift is small, it runs once, and reduced-motion skips it
   entirely. What reads as "coming together" here is the stagger, not the
   distance. */
@media (prefers-reduced-motion: no-preference){
  .js .reach__svg[data-arrive] path[data-n]{
    opacity:0;
    transform:translate(var(--dx,0), var(--dy,0));
    transition:opacity .55s ease-out, transform .7s cubic-bezier(.2,.7,.3,1);
    transition-delay:var(--d,0ms);
  }
  .js .reach__svg[data-arrive].is-in path[data-n]{
    opacity:1; transform:none;
  }
}

/* 36. HERO REASSURANCE LINE ================================================
   The line under the two buttons had no styling at all — an earlier
   conditional append never ran — so it sat hard against them at full body
   size and read as part of the button row. */
.hero__note{
  margin-top:var(--s5);
  font-size:.95rem; line-height:1.6; color:var(--muted);
  max-width:46ch;
  padding-top:var(--s4);
  border-top:1px solid var(--line);
}

/* ==========================================================================
   37. MOTION & CRAFT LAYER
   A deliberate pass over the whole site: the hero arrives as a sequence,
   photographs uncover rather than fade, rules draw, numbers count, and every
   interactive surface answers back.

   Everything here is transform / opacity / clip-path / background-size, all
   composited, all disabled under prefers-reduced-motion. No rule in this
   block touches the reach map.
   ========================================================================== */

/* ---- 37.1 hero entrance -------------------------------------------------
   Six beats, roughly 90ms apart: eyebrow, headline, lede, actions, note,
   cue. Short enough to be finished before a reader has settled on the
   headline, ordered enough to read as intent rather than as a slow load. */
@media (prefers-reduced-motion: no-preference){
  /* Not gated on .js: the old gate meant these painted, vanished when the script
     arrived, and faded back -- a flicker on every load. Plain CSS runs from the
     first paint, and an animation always ends visible, script or no script. */
  .hero__copy > *:not(h1){animation:heroIn .75s cubic-bezier(.16,1,.3,1) both}
  .hero__copy > .eyebrow    {animation-delay:.05s}

  /* The headline rises but never fades: it is the largest contentful paint
     on this page, and anything that starts it at opacity 0 postpones the
     metric by the length of the animation. A transform costs nothing --
     the text is painted where the browser can see it, and moves after. */
  .hero__copy > h1{animation:heroRise .75s cubic-bezier(.16,1,.3,1) both}
  .banner h1          {animation:heroRise .75s cubic-bezier(.16,1,.3,1) both}
  /* Inner-page banners: the breadcrumb and actions fade up; the lede only rises,
     because a three-line lede can be the largest paint on the page. */
  .banner__text > .crumbs {animation:heroIn .6s cubic-bezier(.16,1,.3,1) both}
  .banner__text > .lede   {animation:heroRise .75s cubic-bezier(.16,1,.3,1) both .08s}
  .banner__text > .banner__acts,.banner__text > .mt3{animation:heroIn .7s cubic-bezier(.16,1,.3,1) both .2s}
  .why-hero__stat{animation:heroIn .8s cubic-bezier(.16,1,.3,1) both .25s}
  .hero__copy > .hero__lede {animation-delay:.24s}
  .hero__copy > .hero__acts {animation-delay:.33s}
  .hero__copy > .hero__note {animation-delay:.42s}
  .hero__copy > .cue        {animation-delay:.50s}
  .hero__frame{animation:uncover 1.1s cubic-bezier(.16,1,.3,1) both .2s}
}
@keyframes heroIn{
  from{opacity:0; transform:translateY(14px)}
  to{opacity:1; transform:none}
}
@keyframes heroRise{
  from{transform:translateY(14px)}
  to{transform:none}
}
@keyframes uncover{
  from{clip-path:inset(0 0 100% 0)}
  to{clip-path:inset(0 0 0 0)}
}

/* ---- 37.2 photographs uncover on scroll ---------------------------------
   A wipe reads as deliberate where a fade reads as a slow connection. The
   image starts a touch scaled so it settles into the frame. */
.js [data-uncover]{clip-path:inset(0 0 100% 0)}
.js [data-uncover] img{transform:scale(1.05)}
@media (prefers-reduced-motion: no-preference){
  .js [data-uncover]{transition:clip-path .95s cubic-bezier(.2,.75,.3,1)}
  .js [data-uncover] img{transition:transform 1.2s cubic-bezier(.2,.75,.3,1)}
}
.js [data-uncover].is-in{clip-path:inset(0 0 0 0)}
.js [data-uncover].is-in img{transform:none}

/* ---- 37.3 (removed) ----------------------------------------------------
   This drew a second rule above every section h2. But .eyebrow::after already
   draws one under the eyebrow directly above it, so any section with both got
   two dashes eleven pixels apart, and any section without an eyebrow got a
   stray dash floating over the heading. One rule per section heading is the
   design; this was a duplicate of it. */

/* ---- 37.4 numbers ------------------------------------------------------
   Tabular figures so a counting number does not jitter its own width. */
.stat b,.tile b{font-variant-numeric:tabular-nums}
/* .reach__figures is deliberately not in that list. The reach section is
   frozen by instruction: nothing in this stylesheet changes how it renders. */

/* ---- 37.5 cards answer back ---------------------------------------------
   A colour bar wipes across the top on hover: one element, one transform,
   and a static grid starts feeling responsive without anything moving far
   enough to disturb the reading.

   Gated on a real pointer. A touch device cannot hover, so on a phone these
   rules only ever cost style recalculation for a bar nobody can trigger --
   61ms of it, measured. Worse, a tapped :hover state sticks until the next
   tap elsewhere. Both problems disappear by not shipping it to touch. */
@media (hover: hover) and (pointer: fine){
  /* The 3px hover bar that used to sit here had 14px corners on a 3px strip, so
     its ends curled and never met the card's edge. The lift and the border
     colour already say "this is interactive"; the bar is gone. */

  .mini{transition:transform .28s cubic-bezier(.2,.75,.3,1), box-shadow .28s ease, border-color .28s ease}
  .mini:hover{transform:translateY(-3px); box-shadow:var(--e2); border-color:var(--teal)}
  .idx{transition:transform .28s cubic-bezier(.2,.75,.3,1), box-shadow .28s ease}
  .idx:hover{transform:translateY(-3px); box-shadow:var(--e2)}
}

/* ---- 37.6 buttons -------------------------------------------------------
   A real press. One pixel is enough to feel and too little to notice. */
.btn{transition:background-size .3s cubic-bezier(.2,.75,.3,1),
                transform .18s cubic-bezier(.2,.75,.3,1),
                box-shadow .25s ease, color .2s ease, border-color .2s ease}
.btn:active{transform:translateY(1px) scale(.995)}
.btn--primary{box-shadow:0 1px 2px rgba(23,79,89,.10)}
@media (hover: hover) and (pointer: fine){
  .btn--primary:hover{box-shadow:0 6px 18px rgba(23,79,89,.18)}
}

/* ---- 37.7 form fields ---------------------------------------------------
   The focused field takes a teal ring, so a parent working through a long
   form always knows where they are. */
.field input,.field select,.field textarea{
  transition:border-color .2s ease, box-shadow .2s ease, background-color .2s ease;
}
.field input:focus,.field select:focus,.field textarea:focus{
  border-color:var(--teal); background:var(--white);
  box-shadow:0 0 0 3px rgba(23,79,89,.14);
}
@media (hover: hover) and (pointer: fine){
  .choice{transition:border-color .2s ease, background-color .2s ease, transform .2s cubic-bezier(.2,.75,.3,1)}
  .choice:hover{border-color:var(--teal); transform:translateY(-1px)}
}

/* ---- 37.8 placeholders, redesigned --------------------------------------
   These were bright dashed boxes, and 36 of them made a finished site look
   unfinished. They are still unmistakably placeholders, because that rule
   stands, but they now read as an editorial note in the margin rather than
   as something broken. */
.tbd{
  display:inline; border:0; border-radius:0; padding:0;
  color:var(--muted); font-style:italic; font-weight:400; font-size:1em;
  line-height:inherit;
  /* A marker line low in the line box. Painted with background-size in em
     rather than a colour-stop percentage: an inline box is only as tall as
     the font, so a stop at 62% lands across the middle of the letters and
     reads as a strikethrough. */
  background-image:linear-gradient(rgba(200,169,107,.45),rgba(200,169,107,.45));
  background-repeat:no-repeat;
  background-size:100% .28em;
  background-position:0 1.02em;
  box-decoration-break:clone; -webkit-box-decoration-break:clone;
}
.tbd::before{
  /* A non-breaking space: a trailing ordinary space in a content string is
     collapsed away at the inline boundary, and the label runs into the text. */
  content:"to add\2014\00A0"; font-style:normal; font-weight:700;
  font-size:.78em; letter-spacing:.06em; text-transform:uppercase;
  color:var(--gold-deep); background:none;
}
.vision .tbd,.banner--deep .tbd,.pointer .tbd{
  background-image:linear-gradient(rgba(211,186,136,.4),rgba(211,186,136,.4));
  color:#E6EEF0;
}
.vision .tbd::before,.banner--deep .tbd::before,.pointer .tbd::before{color:var(--gold-on-teal)}

/* ---- 37.8b handing the reveal over to GSAP ------------------------------
   .gs is set by the script on every element GSAP drives. GSAP writes opacity
   and transform inline, frame by frame; a CSS transition on the same
   properties would be a second engine fighting it for the same pixels. The
   class only ever exists when the library actually loaded, so the CSS path
   below is untouched when it did not. */
.gs{transition:none !important}

/* ---- 37.9 links ---------------------------------------------------------
   The underline retracts on hover instead of appearing. It reads as the link
   responding rather than as a state being switched on. Pointer devices only:
   a phone paints the gradient and never animates it. Underlines themselves
   are not conditional -- these rules only replace one underline with another
   that can move, so gating them takes nothing away from a touch reader. */
@media (hover: hover) and (pointer: fine){
  .prose a,.story a,.faq__item p a{
    background-image:linear-gradient(currentColor,currentColor);
    background-repeat:no-repeat; background-position:0 100%;
    background-size:100% 1px; text-decoration:none;
    transition:background-size .3s cubic-bezier(.2,.75,.3,1), color .2s ease;
  }
  .prose a:hover,.story a:hover,.faq__item p a:hover{
    background-size:0 1px; color:var(--gold-link-hover);
  }
}

/* ---- 37.10 moving between pages ----------------------------------------
   A cross-document view transition: the outgoing page fades to the incoming
   one instead of the browser blanking to white between them. It is CSS only,
   which matters here -- the Content-Security-Policy is script-src 'self',
   so there is no inline script to hook navigation with, and none is needed.

   Opacity only, no movement, and it is user-initiated by definition, so it
   sits inside the motion budget. Browsers without the feature ignore the
   at-rule and navigate exactly as they do now. */
@view-transition{ navigation:auto }
::view-transition-old(root),
::view-transition-new(root){ animation-duration:.26s; animation-timing-function:cubic-bezier(.2,.75,.3,1) }

@media (prefers-reduced-motion: reduce){
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*){ animation:none !important }
  .hero__copy > *,.hero__art,.banner h1,.banner__text > *,.why-hero__stat{animation:none}
  .hero__frame{animation:none}
  .js [data-uncover]{clip-path:none; transition:none}
  .js [data-uncover] img{transform:none; transition:none}
    .mini,.idx,.btn,.choice,
  .prose a,.story a{transition:none}
}

/* ---- 37.11 story chapters ----------------------------------------------
   The founder story is the longest continuous read on the site. Numbered
   chapters give it a spine: a reader can see how far through they are, and
   can come back to a part rather than re-scanning from the top. The numeral
   is decorative and hidden from screen readers, which get the heading. */
.chap{
  position:relative; margin-top:clamp(2.5rem,5vw,3.5rem);
  padding-top:var(--s5); color:var(--teal);
  border-top:1px solid var(--line);
}
.chap__n{
  display:block; font-size:.78rem; font-weight:700; letter-spacing:.18em;
  color:var(--gold-deep); margin-bottom:.45rem;
}
@media(min-width:900px){
  .chap__n{
    position:absolute; left:-4.5rem; top:var(--s5); margin:0;
    font-size:1.6rem; letter-spacing:0; line-height:1;
    color:var(--line); font-weight:700;
  }
  .story .chap{padding-left:0}
}

/* ---- 37.12 comparison table --------------------------------------------
   Training should read academic where Therapy reads clinical. A real table
   is the right element: it is scannable, it is what a professional comparing
   providers expects, and a screen reader can navigate it by row and column.
   It scrolls inside its own container so it never pushes the page sideways. */
.tablewrap{overflow-x:auto; border:1px solid var(--line); border-radius:var(--r-md); background:var(--white)}
.ctable{border-collapse:collapse; width:100%; min-width:640px; font-size:.95rem}
.ctable th,.ctable td{
  padding:var(--s4) var(--s5); text-align:left; vertical-align:top;
  border-bottom:1px solid var(--line);
}
.ctable thead th{
  background:var(--teal); color:#fff; font-size:1.02rem; vertical-align:bottom;
  border-bottom:0;
}
.ctable thead th span{
  display:block; font-weight:400; font-size:.8rem; margin-top:.2rem; color:#CBE0E4;
}
.ctable thead th:first-child{background:var(--teal-deep)}
.ctable tbody th{
  width:26%; color:var(--teal); font-weight:700; background:var(--sunk);
}
.ctable tbody tr:last-child th,.ctable tbody tr:last-child td{border-bottom:0}
.ctable tbody tr{transition:background-color .2s ease}
.ctable tbody tr:hover td{background:var(--teal-wash)}
.ctable .yes{color:var(--sage-deep)}

/* 40. SUBMISSIONS INBOX (staff.html) ========================================
   A dense table on a page nobody visits casually. Different rules apply
   here than on the rest of the site: this is a working tool for one or two
   people, not a page to be persuaded by.

   Contrast is computed against --white (#FFFFFF), which is what .panel
   actually sets — this sits inside the panel, not on the page ground:
     charcoal on white   14.56:1     teal-deep on white   12.16:1
     muted on white       6.23:1     white on teal         9.13:1
     charcoal on teal-wash 12.64:1   muted on sage-wash    5.52:1
     teal-deep on cream   11.46:1  (the sticky header's tint)
   All clear 4.5:1. The handled row uses --sage-wash as a fill only, never as
   a text colour.

   An earlier version of this comment cited --paper and --ink at ratios that
   were never computed, against two tokens this stylesheet does not define.
   Every var() below now names a token that exists; a var() that does not
   resolve falls back to the inherited value or to transparent, silently. */
.adm__bar{display:flex; flex-wrap:wrap; gap:var(--s4); align-items:center;
  justify-content:space-between; margin-bottom:var(--s4)}
.adm__tabs{display:flex; gap:.4rem; flex-wrap:wrap}
.adm__tab{
  font:inherit; font-size:.95rem; font-weight:700; cursor:pointer;
  padding:.5rem .9rem; border-radius:var(--r-sm);
  border:1px solid var(--line); background:transparent; color:var(--teal-deep);
  transition:background-color .2s ease, border-color .2s ease;
}
.adm__tab:hover{background:var(--teal-wash)}
.adm__tab.is-on{background:var(--teal); border-color:var(--teal); color:#fff}

.adm__tools{display:flex; flex-wrap:wrap; gap:var(--s4); align-items:center}
.adm__search input{
  font:inherit; padding:.5rem .75rem; min-width:15rem;
  border:1px solid var(--line); border-radius:var(--r-sm); background:#fff; color:var(--charcoal);
}
.adm__check{display:flex; align-items:center; gap:.45rem; font-size:.95rem; cursor:pointer}
.adm__dl{white-space:nowrap}
.adm__count{font-size:.9rem; color:var(--muted); margin:0 0 var(--s3)}

/* The table is wider than any phone and that is fine: it scrolls inside its
   own box so the page itself never scrolls sideways. */
.adm__scroll{overflow-x:auto; border:1px solid var(--line); border-radius:var(--r-sm); background:#fff}
.adm__table{border-collapse:collapse; width:100%; font-size:.9rem}
.adm__table th,.adm__table td{
  text-align:left; padding:.6rem .7rem; border-bottom:1px solid var(--line);
  vertical-align:top; white-space:nowrap;
}
.adm__table th{
  position:sticky; top:0; z-index:1;
  background:var(--cream); color:var(--teal-deep); font-weight:700;
  border-bottom:2px solid var(--line);
}
.adm__table tbody tr:last-child td{border-bottom:0}
.adm__table tbody tr:hover{background:var(--teal-wash)}
/* Handled rows recede rather than disappear -- still readable, visibly done. */
.adm__table tr.is-handled{background:var(--sage-wash)}
.adm__table tr.is-handled td{color:var(--muted)}
/* Free text is the one thing allowed to wrap; the title attribute carries
   the rest, because a message column wide enough for a paragraph pushes
   every useful column off the screen. */
.adm__long{white-space:normal; max-width:26ch; overflow:hidden;
  text-overflow:ellipsis; display:table-cell}

@media (max-width:700px){
  .adm__bar{flex-direction:column; align-items:stretch}
  .adm__tools{flex-direction:column; align-items:stretch}
  .adm__search input{min-width:0; width:100%}
}

@media (prefers-reduced-motion: reduce){
  .adm__tab{transition:none}
}

/* A button that reads as a link. Used for "I have forgotten my password",
   which is an action rather than a destination, so it must be a <button> for
   a screen reader and a keyboard — but looking like a button would give it
   the same weight as Sign in, which it should not have.
   --teal-deep on --paper is 8.9:1. */
.linkish{
  font:inherit; background:none; border:0; padding:0; cursor:pointer;
  color:var(--teal-deep); text-decoration:underline; text-underline-offset:3px;
}
.linkish:hover,.linkish:focus-visible{color:var(--charcoal)}


/* ==========================================================================
   PHONES
   Measured at 390px before this block: banners 600-890px tall, so the first
   screen was nothing but the banner; a 98px sticky header; three to four
   full-width cards with 200px photographs stacked one under another; link
   buttons under the 44px tap size. Nothing below changes a desktop layout.
   ========================================================================== */
@media(max-width:699px){
  :root{--head-h:74px}
  .logo img{height:52px}
  .head__in{min-height:74px}

  /* Card groups with photographs become one swipeable row. The next card peeks
     in from the edge, so it is obvious there is more; nothing moves on its own. */
  .doors,.svc-cards,.access{
    display:grid; grid-template-columns:none; grid-auto-flow:column; grid-auto-columns:84%;
    gap:var(--s4); overflow-x:auto; overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory; scroll-padding-inline:1.25rem;
    margin-inline:-1.25rem; padding:.25rem 1.25rem var(--s4);
    scrollbar-width:none;
  }
  .doors::-webkit-scrollbar,.svc-cards::-webkit-scrollbar,.access::-webkit-scrollbar{display:none}
  .doors > *,.svc-cards > *,.access > *{scroll-snap-align:start}

  /* The banner panel as a compact two-by-two, not a second screen of banner. */
  .banner{padding-block:1.5rem 1.75rem}
  .banner h1{font-size:clamp(1.85rem,1.4rem + 3vw,2.3rem)}
  .banner__grid{gap:var(--s4)}
  .glance{padding:.9rem 1rem}
  .glance ul{display:grid; grid-template-columns:1fr 1fr; gap:.55rem 1rem; margin-top:.5rem}
  .glance li{border-top:0; padding:0 0 0 .95rem}
  .glance li::before{top:.45rem}
  .glance strong{font-size:.92rem}
  .glance span{font-size:.86rem}

  /* Every link that acts like a button gets a thumb-sized target. */
  .more,.chips a{min-height:44px}
  .more{padding-top:.35rem}

  .section{padding-block:2.25rem}
  .cta-band__acts .btn,.banner__acts .btn{flex:1 1 auto}
}
.glance__title{font-size:.8125rem}

/* ==========================================================================
   WHY IT MATTERS
   Four short chapters instead of two long essays. Every figure is a big
   number with one plain sentence and its source; the arithmetic is a chart.
   ========================================================================== */
.why-hero h1{max-width:18ch}
.why-hero__stat{
  background:rgba(255,255,255,.1); border:1px solid rgba(255,255,255,.18); border-top:3px solid var(--gold);
  border-radius:var(--r-md); padding:clamp(1.25rem,3vw,2rem); color:#DCEAEC;
}
.why-hero__stat b{display:block; font-size:clamp(3rem,2.2rem + 3.5vw,4.6rem); line-height:1; color:var(--gold-on-teal); font-variant-numeric:tabular-nums}
.why-hero__stat span{display:block; margin-top:.6rem; font-size:1.02rem; line-height:1.5}
.why-hero__stat cite{display:block; margin-top:.6rem; font-style:normal; font-size:.86rem; color:#CBE0E4}
.why-hero .why-hero__stat a{color:#fff}   /* gold would be 3.67:1 on this card */

/* Chapter strip: where the page is going, in one line. */
.chapters{background:var(--white); border-bottom:1px solid var(--line)}
.chapters__list{list-style:none; margin:0; padding:.6rem 0; display:flex; gap:.4rem; overflow-x:auto; scrollbar-width:none}
.chapters__list::-webkit-scrollbar{display:none}
.chapters__list a{display:inline-flex; align-items:center; gap:.55rem; min-height:44px; padding:.45rem .9rem .45rem .5rem;
  border-radius:var(--r-pill); color:var(--teal); font-weight:700; text-decoration:none; white-space:nowrap;
  transition:background-color .2s ease}
.chapters__list a:hover,.chapters__list a:focus-visible{background:var(--teal-wash)}
.chapters__list span{display:grid; place-items:center; width:1.75rem; height:1.75rem; border-radius:50%; background:var(--teal); color:#fff; font-size:.9rem}
@media(min-width:960px){.chapters__list{justify-content:space-between}}

.stats--three{grid-template-columns:1fr}
@media(min-width:760px){.stats--three{grid-template-columns:repeat(3,minmax(0,1fr))}}
.why-quote{margin:var(--s6) 0 0; padding:var(--s5) var(--s6); background:var(--teal-wash); border-radius:var(--r-md); border-left:4px solid var(--teal)}
.why-quote p{margin:0; max-width:none; font-size:clamp(1.15rem,1rem + .7vw,1.45rem); line-height:1.45; color:var(--teal); font-style:italic}
.why-quote cite{display:block; margin-top:.6rem; font-style:normal; font-size:.9rem; color:var(--muted)}
.why-sub{margin-top:var(--s7); color:var(--teal); font-size:clamp(1.25rem,1.1rem + .6vw,1.55rem)}
.delay-grid{margin-top:var(--s4); grid-template-columns:1fr}
@media(min-width:640px){.delay-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* Same specificity as .grid:has(> :nth-child(4):last-child), which makes four cards 2x2; later, so it wins. */
@media(min-width:1100px){.grid.delay-grid:has(> .card){grid-template-columns:repeat(4,minmax(0,1fr))}}
.delay-grid .card{padding:var(--s5)}
.delay-grid h3{font-size:1.1rem}
.hope{margin-top:var(--s6); padding:var(--s5) var(--s6); background:var(--sage-wash); border-radius:var(--r-md); border-left:4px solid var(--sage-deep)}
.hope .eyebrow{color:var(--sage-deep)}
.hope__text{margin-top:.4rem; max-width:none; font-size:1.08rem; color:var(--charcoal)}

.gap-stats--six{grid-template-columns:1fr}
@media(min-width:640px){.gap-stats--six{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1024px){.gap-stats--six{grid-template-columns:repeat(3,minmax(0,1fr))}}

/* The arithmetic as a chart: one measure, one hue, one axis. The two bars share
   a scale running to PKR 80,000, and the dashed line inside each track is the
   minimum wage (40,700 / 80,000 = 50.875%). Bars are teal on the sunk track,
   8.10:1; the wage line is steel, 5.52:1. Values are written beside the bars,
   so nothing depends on reading the geometry. */
.costchart{margin:var(--s6) 0 0; padding:clamp(1.25rem,3vw,2rem); background:var(--white); border:1px solid var(--line); border-radius:var(--r-md); box-shadow:var(--e1)}
.costchart__title{font-weight:700; color:var(--teal); font-size:1.1rem; margin-bottom:var(--s4)}
.costchart__row{display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:var(--s4); row-gap:.45rem; margin-top:var(--s4)}
.costchart__label,.costchart__value{margin:0; max-width:none; display:flex; flex-direction:column; gap:.1rem}
.costchart__value{text-align:right}
.costchart__label strong,.costchart__value strong{color:var(--charcoal); font-size:1rem}
.costchart__label span,.costchart__value span{color:var(--muted); font-size:.9rem}
.costchart__track{grid-column:1 / -1; position:relative; height:20px; background:var(--sunk); border-radius:4px}
.costchart__track::after{content:""; position:absolute; left:50.875%; top:-6px; bottom:-6px; border-left:2px dashed var(--muted)}
.costchart__bar{height:100%; background:var(--teal); border-radius:0 4px 4px 0; transform-origin:left center}
.costchart__bar--low{width:37.5%}
.costchart__bar--high{width:90%}
.costchart__key{display:flex; align-items:center; gap:.6rem; margin:var(--s5) 0 0; max-width:none; font-size:.9rem; color:var(--muted)}
.costchart__keyline{display:inline-block; width:0; height:1.1rem; border-left:2px dashed var(--muted)}
/* Bars grow from the baseline when the chart arrives. Transform only. */
.gsap .costchart .costchart__bar{transition:transform 1.4s cubic-bezier(.16,1,.3,1)}
.gsap .costchart:not(.in) .costchart__bar{transform:scaleX(0)}
.gsap .costchart .costchart__row + .costchart__row .costchart__bar{transition-delay:.25s}
.why-note{max-width:70ch; color:var(--charcoal)}
.why-small{max-width:none; font-size:.92rem; color:var(--muted)}

.help{background:linear-gradient(180deg, var(--cream) 0%, var(--coral-wash) 100%)}
.help-grid{margin-top:var(--s6); grid-template-columns:1fr}
@media(min-width:700px){.help-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1180px){.grid.help-grid:has(> .card){grid-template-columns:repeat(4,minmax(0,1fr))}}
.help-card .btn{margin-top:auto; align-self:flex-start}
.help-card h3{font-size:1.15rem}

.cites--two{columns:1; column-gap:var(--s7)}
@media(min-width:1024px){.cites--two{columns:2}}
.cites--two li{break-inside:avoid; font-size:.9rem}
@media(prefers-reduced-motion:reduce){.gsap .costchart .costchart__bar{transition:none; transform:none}}

/* Trust strip: the four credentials arrive one after another just after the
   hero settles. Plain CSS from first paint, 10px, ends visible without script. */
@media (prefers-reduced-motion: no-preference){
  .band .trust > li{animation:heroIn .7s cubic-bezier(.16,1,.3,1) both}
  .band .trust > li:nth-child(1){animation-delay:.55s}
  .band .trust > li:nth-child(2){animation-delay:.63s}
  .band .trust > li:nth-child(3){animation-delay:.71s}
  .band .trust > li:nth-child(4){animation-delay:.79s}
}

/* Why it matters: the chapter you are reading is marked in the strip. */
.chapters__list a[aria-current="true"]{background:var(--teal-wash)}
.chapters__list a[aria-current="true"] span{background:var(--gold-deep)}   /* white on gold-deep 4.87:1 */

/* Why it matters on a phone. Stacked, the rebuilt page ran to 11,264px. The
   figure cards and the ways to help become swipeable rows (each card has a
   link, so the row is reachable by keyboard); the four delay cards, which have
   no links, become a compact list instead of a row nobody could tab into. */
@media(max-width:699px){
  .stats--three,.gap-stats--six,.grid.help-grid:has(> .card){
    display:grid; grid-template-columns:none; grid-auto-flow:column; grid-auto-columns:80%;
    gap:var(--s3); overflow-x:auto; overscroll-behavior-x:contain; scroll-snap-type:x mandatory;
    scroll-padding-inline:1.25rem; margin-inline:-1.25rem; padding:.25rem 1.25rem var(--s4); scrollbar-width:none;
  }
  .stats--three::-webkit-scrollbar,.gap-stats--six::-webkit-scrollbar,.help-grid::-webkit-scrollbar{display:none}
  .stats--three > *,.gap-stats--six > *,.help-grid > *{scroll-snap-align:start}
  .stats--three .stat,.gap-stats--six .stat{padding:var(--s4)}
  .stat b{font-size:2.1rem}

  .grid.delay-grid:has(> .card){grid-template-columns:1fr; gap:var(--s3)}
  .delay-grid .card{display:grid; grid-template-columns:auto minmax(0,1fr); column-gap:var(--s4); row-gap:.2rem; padding:var(--s4)}
  .delay-grid .card__plate{grid-row:1 / span 2; width:44px; height:44px}
  .delay-grid .card h3{margin:0}
  .delay-grid .card p{margin:0}

  .why-quote{padding:var(--s4)}
  .hope{padding:var(--s4)}
  .costchart{padding:var(--s4)}
  .cites--two li{font-size:.84rem}
  .why-hero__stat b{font-size:2.8rem}
}

/* Buttons inside a dark banner. .banner--deep a (gold, white on hover) outranks
   .btn--gold, which painted gold text on a gold button and white on white on
   hover. Teal-deep on gold is 5.41:1; on the white hover it is 12.16:1. */
.banner--deep .btn--gold{color:var(--teal-deep)}
.banner--deep .btn--gold:hover,.banner--deep .btn--gold:focus-visible{color:var(--teal-deep); background:var(--white); border-color:var(--white)}
.banner--deep .btn--on-teal{color:#fff}
.banner--deep .btn--on-teal:hover,.banner--deep .btn--on-teal:focus-visible{color:var(--teal-deep); background:#fff}

/* No stranded last words. Headings balance their lines; body copy avoids a
   single word alone on the last line. Browsers without text-wrap ignore it. */
h1,h2,h3,h4,.lede,.eyebrow,.glance strong,.nav__panel strong,.chips a{text-wrap:balance}
p,li,dd,figcaption,cite,.fs-sm{text-wrap:pretty}
.center p,.fs-sm{text-wrap:balance}

/* Slim bar: a short aside with its one action centred under it. Beside the
   text, the button sat alone at the far right of a full-width bar. */
.section--tight{padding-block:clamp(1.5rem,3vw,2.25rem)}
.slimbar{display:flex; flex-direction:column; align-items:center; gap:var(--s4); text-align:center;
  background:var(--teal-wash); border-radius:var(--r-md); padding:clamp(1.5rem,3.5vw,2.5rem) clamp(1.25rem,3vw,2.25rem)}
.slimbar--quiet{background:var(--sunk)}
.slimbar__title{font-size:clamp(1.3rem,1.1rem + .8vw,1.7rem); margin-top:.15rem}
.slimbar__text > *{margin-inline:auto}
.slimbar__text p:not(.eyebrow){margin-top:.4rem; color:var(--charcoal); max-width:62ch}
.slimbar .btn{white-space:nowrap}

/* On a phone, paragraphs read better from a straight left edge than centred,
   and a button spanning the card still sits square in it. */
@media(max-width:699px){
  .vision,.slimbar{text-align:left; align-items:stretch}
  .vision > *,.slimbar__text > *{margin-inline:0}
  .vision__acts .btn{flex:1 1 100%}
  .slimbar .btn{white-space:normal}
}

/* Chapter 4 opens with the founder's own words about the families who arrive.
   Deep teal, a large quote, and the lines arriving one at a time -- each line
   is its own reveal, so the reader meets them in order. White on deep teal is
   12.16:1; #DCEAEC is 9.86:1; champagne for the turn is 5.41:1. */
.story-band{background:var(--teal-deep); color:#DCEAEC; padding-block:clamp(3rem,7vw,5.5rem)}
.story-band .eyebrow{color:var(--gold-on-teal)}
.story-band__grid{display:grid; gap:clamp(1.5rem,4vw,4rem); grid-template-columns:1fr; margin-top:var(--s4); align-items:start}
@media(min-width:960px){.story-band__grid{grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr)}}
.story-band__quote{position:relative; padding-top:1.4rem}
.story-band__mark{position:absolute; top:-1.6rem; left:-.35rem; font-size:7rem; line-height:1; color:var(--gold); opacity:.55; font-family:var(--font)}
.story-band blockquote{margin:0}
.story-band blockquote p{margin:0; max-width:none; color:#fff; font-style:italic;
  font-size:clamp(1.7rem,1.2rem + 2.2vw,2.75rem); line-height:1.28}
.story-band__lines p{margin:0 0 var(--s4); max-width:52ch; font-size:clamp(1.05rem,1rem + .35vw,1.22rem); line-height:1.6; color:#DCEAEC}
.story-band__lines .story-band__turn{padding-top:var(--s4); border-top:1px solid rgba(255,255,255,.18); color:var(--gold-on-teal); font-style:italic}
.story-band__lines .story-band__cite{font-size:.9rem; color:#CBE0E4}
.story-band a{color:#fff}
.story-band :focus-visible{outline-color:#fff}
.gsap .story-band .story-band__mark{transition:transform .9s cubic-bezier(.34,1.56,.64,1), opacity .6s ease}
.gsap .story-band:not(.in) .story-band__mark{transform:scale(.5); opacity:0}

.help__title{font-size:clamp(2rem,1.4rem + 2.6vw,3.2rem); line-height:1.15; max-width:20ch}
.help__lede{max-width:62ch}
.help__hope{margin:var(--s7) auto 0; max-width:46rem; text-align:center}
.help__hope blockquote{margin:0}
.help__hope p{margin:0 auto; max-width:none; font-style:italic; color:var(--teal); font-size:clamp(1.35rem,1.1rem + 1.1vw,1.9rem); line-height:1.35}
.help__hope figcaption{margin-top:var(--s3); font-size:.9rem; color:var(--muted); letter-spacing:.02em}
@media(prefers-reduced-motion:reduce){.gsap .story-band .story-band__mark{transition:none; transform:none; opacity:.55}}

/* Rows of short links wrap between links, never inside one. */
.fs-sm a{white-space:nowrap}
/* The founder attribution runs the full width, so the title stays in one piece. */
.story-band__lines .story-band__cite{max-width:none}

/* The three reach figures sit side by side on a phone instead of a column of
   three short numbers. Text above the map only; the map is untouched. */
@media(max-width:699px){
  .reach__figures{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--s3); margin-top:var(--s4)}
  .reach__figures li{margin:0; padding:0}
  .reach__figures b{font-size:1.9rem; line-height:1.1}
  .reach__figures span{font-size:.8rem; line-height:1.35}
}
/* Touch behaviour, from the Web Interface Guidelines pass (18 September 2026).
   `manipulation` drops the ~300ms delay a phone holds every tap for in case a
   second tap follows, which made every button feel half a beat behind. The tap
   flash is the site's own teal rather than the browser's default grey-blue.
   Safe-area insets are deliberately absent: the viewport meta does not set
   viewport-fit=cover, so the page already starts below a notch. */
a,button,summary,label,input,select,textarea{
  touch-action:manipulation;
  -webkit-tap-highlight-color:rgba(31,95,107,.14);
}

/* The phone drawer, closed from the first paint (see the nav section above).
   .navjs is set by main.js, which is deferred, so until it ran a phone painted
   the whole menu open -- a header 672px tall -- and then snapped it shut, and
   everything below jumped: a layout shift of 0.66 on every page, where anything
   over 0.1 is rated poor. `scripting: enabled` is known before any script runs,
   so the drawer is closed from the start whenever scripts can open it. With
   scripts blocked the query does not match and the menu stays a list in the
   flow, as before. Browsers that do not know the feature treat the query as
   false and keep the old behaviour. If main.js itself failed to arrive, the
   footer still links every page. */
@media (max-width:1179px) and (scripting: enabled){
  html:not(.navjs) .head{position:sticky}
  :root .nav-toggle{display:inline-flex}
  :root .nav{
    display:none; position:absolute; left:0; right:0; top:100%; padding:var(--s3);
    background:var(--cream); border-bottom:1px solid var(--line); box-shadow:var(--e2);
    max-height:calc(100dvh - var(--head-h)); overflow-y:auto;
  }
  :root .nav.is-open{display:block}
}
