/* ==========================================================================
   Menopause Education White Paper — movement landing page
   Typeface: Figtree (self-hosted). Palette: Calla Lily Clinical Care.
   ========================================================================== */

:root {
  /* ------------------------------------------------------------------ PALETTE
     CALLA LILY ONLY (round 4). The page previously ran a Calla Lily / ABIG
     hybrid; the client has reverted to a single Calla Lily identity.

     ABIG's colours — crimson #EB0028 / #C4001F, ABIG navy #1A2242 / #18244E,
     and warm off-white #E7E7E5 — may appear ONLY inside the ABIG logo artwork
     itself. They must never be used for accents, buttons, rules, eyebrows,
     hovers, focus rings, markers, or surfaces. There is deliberately no
     crimson token in this file: reintroducing one is the regression to avoid.

     The five brand colours, and nothing else:
       navy      #1F2B51    blue      #19408F    mid-blue  #4980C1
       soft      #D2D4DC    gold      #F3C544                              */
  --header-h: 61px;         /* real sticky-header height; the reader toolbar tucks under it */
  --navy: #00205b;          /* Calla Lily navy, sampled from callali.ly — 15.5:1 on white */
  --navy-field: #00205b;    /* movement / dark-field background */
  --navy-deep: #001842;     /* darker step of the same navy, for the footer */
  --blue: #19408f;          /* 9.4:1 on white — the accent for text and hovers */
  --blue-mid: #407ec9;      /* Calla Lily's light blue, from the site's nav pill */
  --blue-mid-dark: #2f66a8; /* AA-safe darkened variant for small text */
  --blue-soft: #ccd6e6;
  --rule: #ccd6e6;          /* blue-tinted rule — the grey #D2D4DC is retired */

  /* ROUND 24 — NO GREY ANYWHERE.
     Client: "they dont use gray anywhere currently on their things". Every
     neutral surface, rule and hairline on the page was a cool grey derived from
     #D2D4DC. Each has been replaced by the lightest workable tint of the brand
     blue #407ec9, matched to the tonal weight of the grey it replaces so that
     no surface changes prominence — #f2f3f6 and #f2f6fb both sit at ~1.09:1
     against white. The page reads the same; it is simply on-brand now. */
  --hairline: #e2eaf5;
  --paper: #ffffff;
  --paper-tint: #f2f6fb;    /* lightest tint of #407ec9 — replaces the grey #F2F3F6 */

  /* ROUND 24 — the blush surfaces, at the client's direction. */
  --blush: #ffefef;         /* Take Action field, template box, paper-meta strip */
  --blush-deep: #ffe3e2;    /* replaces the sage green on the ask box and discs */
  --blush-rule: #f2cbc9;    /* hairline for both, same role the green rule had */

  /* ROUND 24 — TEXT ON THE NAVY FIELD, THREE TIERS, NO YELLOW.
     Client: "It doesnt look like they use the yellow on dark blue background
     anywhere on their website, so we may not want to do that on ours... Or if
     you use a shade to darken the text a touch but reserve pure white for the
     most important things to stand out."

     Both of her options, together. Gold is gone from every dark field. Pure
     white is now rationed — headlines, counters, primary buttons — and
     everything else steps down through a softened white and then the brand's
     own light blue, which is the colour of the "English" pill in their nav.
     Gold survives only on light surfaces, where their site does use it. */
  --on-navy: #ffffff;          /* tier 1 — reserved for what must be read first */
  --on-navy-soft: #ccdaee;     /* tier 2 — body copy on navy, 11.0:1 */
  --on-navy-accent: #8fb4de;   /* tier 3 — eyebrows, labels, links, 7.2:1 */
  --gold: #f3c544;          /* Calla Lily accent — LIGHT SURFACES ONLY (see round 24) */
  /* Round 6: Calla Lily's lightest green, sampled from the hero panel on
     callali.ly. Used as the Share-section surface in place of the saturated
     blue. Navy #1F2B51 sits on it at 10.98:1 and the navy footer beneath it
     reads at 13.22:1, so the section boundary stays crisp. */
  --cl-green-50: #dde9d8;
  --cl-green-100: #eef4ec;  /* one step lighter — inset caption field */
  --cl-green-200: #b9cdb1;  /* hairline/divider on the green surface */

  /* ROUND 20 — the Zibners quote band moved off green and onto a pale blue.
     Both are tints of --mid-blue (#4980C1), the colour of "a Central Issue, Not
     a Peripheral One" in the hero, mixed 90% and 68% toward white. The surface
     lands at 1.12:1 against the page — the same weight the green band had, so
     the band reads exactly as prominently as before, just in the blue family.
     Navy on it is 12.26:1 and the blue caption 8.60:1. */
  --blue-50:  #edf2f9;   /* kept for small insets on white */
  --blue-200: #c5d6eb;

  /* ROUND 21 — the pale versions failed at the one job a full-bleed band has:
     separating from its neighbour. Measured against the page's grey tint
     (#f2f3f6), the quote blue was only dE 2.5 apart, which over a large flat
     area reads as the same colour. These are the band-strength tints — dE 16.5
     for the blue and 15.5 for the green — deep enough to be a deliberate change
     of surface while still light enough to carry navy type at 9:1 or better. */
  --blue-100: #c1d4ea;   /* Zibners quote band */
  --blue-300: #9dbbdf;   /* its hairline */
  --cl-green-75:  #d3e2cd;  /* share band */
  --cl-green-250: #a9c29f;  /* its hairline */
  /* ROUND 17 — client: "update the dark navy box behind 'the ask is this' to be
     green so it subtly matches the 'bring two answers to the call' circle
     icons". She asked for the box to stay DARK and become green, not to go pale,
     which is the right instinct: that panel is the loudest thing in the section
     and a #DDE9D8 panel would have made the ask recede.

     So this is the same Calla Lily sage — hue 102°, sampled from #dde9d8 — taken
     down to 20% lightness. It is a shade of the existing brand green, not a new
     colour. Measured: white 11.09:1, gold 6.80:1, both well past AA. */
  --cl-green-900: #2D4125;   /* retired r19 — kept only so nothing references a dead var */

  /* ROUND 19c — the card numbers went coral, then a softer coral, and are now
     YELLOW with a navy numeral at the client's request. This deliberately reuses
     the existing brand gold rather than introducing a fifth accent: navy on it
     is 8.46:1, and it is the same yellow already carrying the petal mark and the
     goal bar, so the page gains no new colour. The coral sampled from
     callali.ly (#FE6460, a gradient midpoint) is retired. */
  --ink: #00205b;
  --ink-mute: #43546f;      /* blue-toned, replaces the grey-violet #4A5372 */

  --shell: 1180px;
  --radius-sm: 10px;
  --radius: 18px;
  --radius-lg: 28px;

  /* Prose steps reduced ~10% from round 1; --step-0 never drops below 15px. */
  --step-1: clamp(0.76rem, 0.74rem + 0.09vw, 0.81rem);
  --step-0: clamp(0.94rem, 0.92rem + 0.13vw, 0.99rem);
  --step-1u: clamp(1.04rem, 0.98rem + 0.3vw, 1.21rem);
  --step-2: clamp(1.35rem, 1.19rem + 0.72vw, 1.85rem);
  --step-3: clamp(1.9rem, 1.55rem + 1.6vw, 3rem);
  --step-4: clamp(1.95rem, 1.35rem + 2.05vw, 3.05rem);

  /* TYPEFACE — single source of truth ---------------------------------------
     Figtree (OFL, self-hosted in ./assets/fonts/, declared in fonts.css) is our
     stand-in for Calla Lily's licensed brand face Circular, which we can
     neither self-host nor load from a CDN. To change the face, edit the family
     list in scripts/fetch-fonts.py, re-run it, and change THIS LINE only.
     The system fallback deliberately starts with system-ui so the swap-in is
     a geometric-to-neutral shift rather than a jarring one.                   */
  --font-sans: 'Figtree', system-ui, -apple-system, 'Segoe UI', Roboto,
               'Helvetica Neue', Arial, sans-serif;

  /* Figtree runs slightly narrower and a touch smaller on the body than
     Poppins at the same px size, so headings get marginally less negative
     tracking and display sizes are nudged to hold the previous optical size.
     Body steps above are UNCHANGED — the round-2 reduction stays. */
  --track-display: -0.018em;
  --track-title: -0.015em;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

*, *::before, *::after { box-sizing: border-box; }

/* Round 8 §7 — sticky-nav overlap. `scroll-padding-top` alone is ignored by
   some in-page scroll containers and by programmatic scrollIntoView, so every
   anchor target also carries its own `scroll-margin-top`. Both are derived
   from --header-h so they stay correct when the header shrinks on mobile. */
html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h, 61px) + 28px);
}
:target,
[id]:is(section, div, article, h2, h3) {
  scroll-margin-top: calc(var(--header-h, 61px) + 28px);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }

h1, h2, h3 { margin: 0; line-height: 1.08; letter-spacing: -0.02em; font-weight: 700; }
p { margin: 0; }

a { color: var(--blue); text-underline-offset: 3px; }
a:hover { color: var(--navy); }

:focus-visible {
  outline: 3px solid var(--blue-mid);
  outline-offset: 3px;
  border-radius: 4px;
}
.movement :focus-visible, .site-footer :focus-visible {
  outline-color: #ffffff;
}
/* Round 6: the Share section is now light green, where gold would sit at
   1.3:1. Navy-blue gives a 7.7:1 focus ring on that surface. */
.share-section :focus-visible { outline-color: var(--blue); }

.shell { width: min(100% - 2.5rem, var(--shell)); margin-inline: auto; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: 1rem; top: -100px; z-index: 100;
  background: var(--navy); color: #fff; padding: 0.7rem 1.2rem;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm); font-weight: 600;
  transition: top 0.18s var(--ease);
}
.skip-link:focus { top: 0; color: #fff; }

/* Eyebrow labels.
   Round 4: the short leading dash rule was removed at the client's request.
   Do not reinstate a `content` dash, an `::before` rule, or a literal — / – / -
   in the markup — the label stands on its own, carried by the letter-spacing
   and colour. `display: block` (not flex) because there is no longer a
   sibling element to align against. */
.eyebrow {
  font-size: var(--step-1); font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--blue); margin-bottom: 1rem;
  display: block;
}
.eyebrow-light { color: var(--on-navy-accent); }

.section-title { font-size: var(--step-3); font-weight: 700; max-width: 20ch; }
.section-lede {
  margin-top: 1.15rem; max-width: 56ch; color: var(--ink-mute);
  font-size: var(--step-1u); line-height: 1.55;
}

/* ------------------------------------------------------------- buttons -- */
.btn {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-family: inherit; font-weight: 600; font-size: 0.97rem;
  border-radius: 999px; border: 1.5px solid transparent;
  padding: 0.78rem 1.5rem; cursor: pointer; text-decoration: none;
  transition: transform 0.18s var(--ease), background-color 0.18s var(--ease),
              color 0.18s var(--ease), box-shadow 0.18s var(--ease);
  line-height: 1.2;
}
.btn-sm { padding: 0.55rem 1.1rem; font-size: 0.9rem; }
.btn-lg { padding: 0.95rem 1.9rem; font-size: 1.02rem; }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn-primary { background: var(--blue); color: #fff; box-shadow: 0 8px 20px -12px rgba(25, 64, 143, 0.9); }
.btn-primary:hover { background: var(--navy); color: #fff; }

.btn-ghost { background: transparent; color: var(--blue); border-color: var(--blue-soft); }
.btn-ghost:hover { background: var(--paper-tint); border-color: var(--blue); color: var(--blue); }

/* ROUND 24 — was a gold capsule on navy. Their site never puts yellow on the
   dark field, and this is the single most important control on it, so it takes
   the top tier instead: solid white, navy label, 15.5:1. */
.btn-gold { background: #ffffff; color: var(--navy); }
.btn-gold:hover { background: var(--on-navy-soft); color: var(--navy); }

.btn-outline { background: transparent; color: var(--navy); border-color: var(--navy); }
.btn-outline:hover { background: var(--navy); color: #fff; border-color: var(--navy); }

.btn-outline-light { background: transparent; color: #fff; border-color: rgba(255, 255, 255, 0.5); }
.btn-outline-light:hover { background: rgba(255, 255, 255, 0.12); color: #fff; }

.icon-btn {
  display: inline-grid; place-items: center; width: 34px; height: 34px;
  border-radius: 50%; border: 1.5px solid var(--blue-soft);
  background: #fff; color: var(--navy); cursor: pointer;
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease);
}
.icon-btn:hover { background: var(--paper-tint); border-color: var(--blue); }

/* -------------------------------------------------------------- header -- */
.site-header {
  position: sticky; top: 0; z-index: 40;
  /* --header-h is what the sticky reader toolbar tucks under; kept in sync
     with the header's real height at each breakpoint. */
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--blue-soft);
}
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; padding: 0.7rem 0;
}
/* Co-brand lockup: Calla Lily | Prepared by ABIG.
   The two marks are sized to equal OPTICAL weight, not equal pixel height —
   the ABIG wordmark is a single heavy line of caps, so it renders much shorter
   than the two-line Calla Lily lockup. */
/* Two marks and a hairline, at every width. The header carries no
   "prepared by" label — that relationship is stated in the page intro, the
   media block and the footer, and the header reads cleaner without it. */
.cobrand {
  display: flex; align-items: center; gap: 0.85rem; min-width: 0;
}
.cobrand-link { display: inline-flex; align-items: center; flex: none; border-radius: 4px; }
.cobrand-link img { display: block; width: auto; }
.cobrand-abig img { height: 19px; }         /* 1315x357 -> ~70px wide */

/* ---------------------------------------------------------- CALLA LILY MARK
   The petal is WHITE in every context — that is the real brand colour; the
   navy-filled petal used previously was our own recolour and was wrong.
   Because white disappears on white, a light hairline defines its edge. The
   stroke exists ONLY for that, so it stays faint: Calla Lily soft grey at a
   true 1px device hairline (vector-effect: non-scaling-stroke), which cannot
   thin away at header size (~37px) nor thicken into a rim when shown large.

   The gold capsule (#F3C544) and mid-blue wedge (#4980C1) are untouched. */
.brand-mark {
  display: block; height: var(--mark-h, 37px); width: var(--mark-h, 37px);
  flex: none; overflow: visible;
}
.brand-mark-petal {
  fill: #fff;
  stroke: var(--mark-stroke, #ccd6e6);
  stroke-width: var(--mark-stroke-w, 1.25);
}

/* The lockup reproduces the original single PNG's proportions exactly:
   at a 312px-tall source canvas the mark is 306px, the gap 78px and the
   wordmark 965px, so gap and wordmark are expressed against --lockup-h. */
.cobrand-calla {
  /* Round 33: sized against the ABIG logo beside it. ABIG is a single line of
     caps, this is a two-line wordmark, so matching cap heights would make this
     block twice ABIG's height and dominate the pair. The block height is what
     the eye reads, so it is set to ~1.68x ABIG's — the two then sit as peers
     and Calla Lily still leads by being first. Every breakpoint holds that
     same ratio. */
  --lockup-h: 32px;
  --mark-h: calc(var(--lockup-h) * 0.9808);   /* 306 / 312 */
  gap: calc(var(--lockup-h) * 0.25);          /*  78 / 312 */
}
.cobrand-calla .cobrand-wordmark { height: var(--lockup-h); }
.cobrand-divider {
  width: 1px; height: 29px; background: var(--rule); flex: none;
}
.header-nav { display: flex; align-items: center; gap: 1.6rem; flex: none; position: relative; }
.nav-links { display: flex; align-items: center; gap: 1.6rem; }
.nav-toggle {
  display: none; align-items: center; gap: 0.45rem;
  font: inherit; font-size: 0.84rem; font-weight: 500; color: var(--ink);
  background: none; border: 1px solid var(--rule); border-radius: 8px;
  padding: 0.42rem 0.7rem; cursor: pointer;
}
.nav-toggle:hover { border-color: var(--blue-mid); color: var(--blue); }
.nav-toggle svg { flex: none; }
.nav-link {
  font-size: 0.86rem; font-weight: 500; color: var(--ink-mute); text-decoration: none;
}
.nav-link:hover { color: var(--blue); }

/* ---------------------------------------------------------------- hero -- */
/* overflow-x clipped so the cover's soft radial glow (which is inset past the
   figure edges) can never create a sideways scroll on narrow screens. */
.hero { padding: clamp(3rem, 6vw, 6.5rem) 0 clamp(3.5rem, 6vw, 6rem); overflow-x: clip; }
.hero-grid {
  display: grid; grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(2rem, 5vw, 5rem); align-items: center;
}
.hero-title {
  font-size: var(--step-4); font-weight: 700; letter-spacing: -0.03em;
  line-height: 1.03; color: var(--blue); text-wrap: balance;
}
.hero-title em { font-style: normal; color: var(--blue-mid); display: block; margin-top: 0.15em; }
.hero-sub {
  margin-top: 1.6rem; font-size: var(--step-1u); color: var(--ink-mute);
  max-width: 46ch; line-height: 1.55;
}
/* The CTA group is shrink-to-fit, so its width IS the combined width of the
   button pair. The note is centred inside that group, which puts its optical
   centre on the pair's centre rather than on the text column. */
.hero-cta { display: flex; flex-direction: column; align-items: center; width: fit-content; max-width: 100%; margin-top: 2.2rem; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 0.85rem; }
.hero-note { margin-top: 1.1rem; font-size: var(--step-1); color: var(--ink-mute); text-align: center; }

.hero-cover { margin: 0; position: relative; justify-self: end; max-width: 470px; width: 100%; }
.hero-cover::before {
  content: ''; position: absolute; inset: -8% -12% -14% -8%;
  background: radial-gradient(60% 55% at 70% 30%, rgba(73, 128, 193, 0.22), transparent 70%),
              radial-gradient(50% 50% at 25% 80%, rgba(0, 32, 91, 0.14), transparent 70%);
  border-radius: 50%; z-index: -1;
}
.hero-cover img {
  max-height: 620px; object-fit: contain; margin-inline: auto;
  border-radius: var(--radius); border: 1px solid var(--blue-soft);
  box-shadow: 0 40px 80px -50px rgba(0, 32, 91, 0.7);
  width: 100%;
}

/* ------------------------------------------------------------ movement -- */
.movement {
  background: var(--navy-field); color: #fff; position: relative; overflow: hidden;
  padding: clamp(3.5rem, 7vw, 6.5rem) 0;
  isolation: isolate;
}
/* ABIG-style dark field: a very low-opacity photographic layer under a navy
   scrim, kept quiet so every counter still clears AA against the navy field. */
.movement-bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
}
.movement-bg img {
  width: 100%; height: 100%; object-fit: cover; opacity: 0.13;
  filter: blur(2px) saturate(0.8);
}
.movement-bg::after {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(60% 55% at 78% 12%, rgba(73, 128, 193, 0.3), transparent 65%),
    radial-gradient(46% 46% at 8% 92%, rgba(73, 128, 193, 0.2), transparent 65%),
    linear-gradient(180deg, rgba(24, 36, 78, 0.86), rgba(24, 36, 78, 0.94));
}
.movement .shell { position: relative; z-index: 1; }
.movement-title { color: #fff; }

.counters {
  list-style: none; margin: 2.6rem 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.1rem;
}
.counter {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius); padding: 1.7rem 1.5rem 1.6rem;
  display: flex; flex-direction: column; gap: 0.85rem;
  container-type: inline-size;
  transition: opacity 0.35s var(--ease);
}
.counter-icon { color: var(--on-navy-accent); opacity: 0.9; flex: none; }
.counter-icon svg { display: block; }
.counter-line { display: flex; flex-direction: column; gap: 0.15rem; }
.counter-num {
  font-size: clamp(3.1rem, 2.1rem + 3.4vw, 4.9rem);
  font-size: clamp(2.5rem, calc(25.5cqi - 13px), 5.5rem);
  font-weight: 900;
  letter-spacing: -0.035em; line-height: 1; color: var(--on-navy);
  font-variant-numeric: tabular-nums; min-height: 1em;
}
.counter-label {
  font-size: var(--step-0); font-weight: 500; color: rgba(255, 255, 255, 0.86);
  line-height: 1.4;
}
.skeleton {
  display: inline-block; width: 4.5ch; height: 0.78em; border-radius: 6px;
  background: linear-gradient(90deg, rgba(255,255,255,0.13), rgba(255,255,255,0.28), rgba(255,255,255,0.13));
  background-size: 200% 100%; animation: shimmer 1.4s linear infinite;
  vertical-align: -0.02em;
}
@keyframes shimmer { to { background-position: -200% 0; } }

/* ROUND 8 P0. There was a `[data-stats-state='error'] .counters { display:none }`
   rule here. It deleted the entire tracker whenever /api/stats failed — which is
   always, on a static host. It is gone for good: NOTHING may hide the counters
   or the goal bar. The degraded state is this one quiet line instead. */
.stats-offline {
  margin-top: 0.9rem; max-width: 62ch;
  font-size: var(--step-1); line-height: 1.55;
  color: rgba(255, 255, 255, 0.72);
}
.stats-offline[hidden] { display: none; }

.movement-body {
  margin-top: 2.6rem; display: grid; grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(1.8rem, 4vw, 3.5rem); align-items: start;
}
@media (max-width: 900px) { .movement-body { grid-template-columns: 1fr; } }

.movement-copy {
  margin-top: 0; max-width: 62ch; font-size: var(--step-1u);
  line-height: 1.62; color: rgba(255, 255, 255, 0.92);
}

.goal {
  margin-top: 0; max-width: 620px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius); padding: 1.5rem 1.6rem 1.35rem;
}
.goal-head {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: 0.5rem 1rem; margin-bottom: 1.1rem;
}
.goal-title { font-size: var(--step-1u); font-weight: 700; color: #fff; }
.goal-remaining { font-size: var(--step-1); color: var(--on-navy-accent); font-weight: 600; letter-spacing: 0.02em; }

/* Scale row: the LEADING figure is the live reader count, the trailing figure
   is the goal. Both, the fill width, aria-valuenow and "N to go" are written
   from one value in renderStats() so they can never disagree. */
.goal-scale {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1rem; margin-bottom: 0.55rem;
}
.goal-live { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.goal-live-num {
  font-size: clamp(2.2rem, 1.6rem + 2vw, 3.2rem); font-weight: 900;
  line-height: 1; letter-spacing: -0.03em; color: var(--on-navy);
  font-variant-numeric: tabular-nums;
}
.goal-live-label,
.goal-target {
  font-size: var(--step-1); letter-spacing: 0.11em; text-transform: uppercase;
  font-weight: 600; color: rgba(255, 255, 255, 0.78);
}
.goal-target { align-self: flex-end; white-space: nowrap; }
.goal-target b { color: #fff; font-weight: 700; }

.progress-track {
  height: 14px; border-radius: 999px; background: rgba(255, 255, 255, 0.16);
  overflow: hidden; position: relative;
}
.progress-fill {
  height: 100%; width: 0; min-width: 3px; border-radius: 999px;
  background: linear-gradient(90deg, #407ec9, #9dc2e8);
  transition: width 1.1s var(--ease);
}
.goal-pct {
  margin-top: 0.6rem; font-size: var(--step-1);
  color: rgba(255, 255, 255, 0.82); font-variant-numeric: tabular-nums;
}
.movement-cta { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 2.4rem; }

/* ----------------------------------------------------------------- why -- */
.why { padding: clamp(3.5rem, 7vw, 6.5rem) 0; background: var(--paper); }
/* Five findings, not six, since round 28. The 1px gaps let the container's rule
   colour show through as gridlines, which means any unfilled cell reads as a
   grey box rather than as empty space. So the row is tiled explicitly instead of
   left to wrap: a 6-track grid gives three cards of 2 tracks, then two cards of
   3, and both rows come out flush with no dead cell. */
.stats {
  list-style: none; margin: 3rem 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 1px;
  background: var(--rule); border: 1px solid var(--rule);
  border-radius: var(--radius); overflow: hidden;
}
.stat { grid-column: span 2; }
.stat:nth-child(4), .stat:nth-child(5) { grid-column: span 3; }
/* Per-card "source" labels were removed (the section lede does the attributing),
   so the padding is re-balanced top/bottom instead of leaving a dead gap. */
.stat { background: #fff; padding: 2.1rem 1.75rem; display: flex; flex-direction: column; gap: 0.85rem; }
.stat-figure {
  font-size: clamp(2.4rem, 1.8rem + 2.2vw, 3.35rem); font-weight: 900;
  letter-spacing: -0.04em; line-height: 1; color: var(--blue);
}
.stat-unit { font-size: 0.55em; font-weight: 700; letter-spacing: -0.02em; color: var(--blue-mid-dark); }
.stat-body { color: var(--ink-mute); font-size: 0.9rem; line-height: 1.6; flex: 1; }
.stat-body strong { color: var(--navy); font-weight: 600; }
.pull-quote {
  margin: 3.5rem 0 0; padding: 2.2rem 0 0; border-top: 1px solid var(--hairline);
  max-width: 62ch;
}
.pull-quote p {
  font-size: var(--step-2); font-weight: 500; line-height: 1.42;
  color: var(--navy); letter-spacing: -0.015em;
}
.pull-quote cite {
  display: block; margin-top: 1.2rem; font-style: normal;
}
.quote-attrib {
  display: block; font-size: 0.95rem; font-weight: 700; color: var(--navy);
  letter-spacing: -0.005em;
}
.quote-source {
  display: block; margin-top: 0.2rem; font-size: 0.8rem; font-weight: 500;
  color: var(--ink-mute);
}

/* (The second, individually signed author quote was removed in round 4 — the
   same words already appear in the audio transcript, and the conclusion
   pull-quote above carries the section's editorial voice.) */

/* -------------------------------------------------------------- reader -- */
.reader-section { padding: clamp(3.5rem, 7vw, 6.5rem) 0; background: var(--paper-tint); }
.reader-shell {
  margin-top: 2.5rem; background: #fff; border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  /* `clip` not `hidden`: hidden would make the shell a scroll container and
     break the sticky reader toolbar on mobile. */
  overflow: hidden; overflow: clip;
  box-shadow: 0 40px 80px -60px rgba(0, 32, 91, 0.6);
}
.reader-toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.85rem 1.1rem; border-bottom: 1px solid var(--rule);
  background: #fff; position: sticky; top: var(--header-h, 61px); z-index: 2; flex-wrap: wrap;
}
.reader-pages { font-size: 0.86rem; font-weight: 500; color: var(--ink-mute); }
.reader-pages span { color: var(--navy); font-weight: 600; font-variant-numeric: tabular-nums; }
.reader-tools { display: flex; align-items: center; gap: 0.6rem; }
.zoom-value {
  font-size: 0.86rem; font-weight: 600; color: var(--navy);
  min-width: 3.4ch; text-align: center; font-variant-numeric: tabular-nums;
}
.reader-viewport {
  height: min(78vh, 860px); overflow-y: auto; overflow-x: auto;
  background: var(--paper-tint); position: relative; scroll-behavior: auto;
  overscroll-behavior: contain;
}
.reader-status {
  position: absolute; inset: 0; display: grid; place-content: center;
  justify-items: center; gap: 0.9rem; color: var(--ink-mute); font-size: 0.95rem;
}
.spinner {
  width: 26px; height: 26px; border-radius: 50%;
  border: 3px solid var(--blue-soft); border-top-color: var(--blue);
  animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.pdf-pages { padding: 1.4rem 0 2rem; display: flex; flex-direction: column; align-items: center; gap: 1.4rem; }
.pdf-page {
  position: relative; background: #fff; box-shadow: 0 10px 30px -22px rgba(0, 32, 91, 0.8);
  border: 1px solid var(--blue-soft); overflow: hidden;
}
.pdf-page canvas { display: block; }
.pdf-page .page-badge {
  position: absolute; left: 10px; top: 10px; z-index: 3; font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-mute);
  background: rgba(255, 255, 255, 0.85); padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--blue-soft); pointer-events: none;
}
.annotationLayer { position: absolute; inset: 0; }
.annotationLayer section { position: absolute; }
.annotationLayer .linkAnnotation > a {
  position: absolute; inset: 0; display: block;
  background: rgba(64, 126, 201, 0.13); border-radius: 2px;
  transition: background 120ms ease;
}
.annotationLayer .linkAnnotation > a:hover { background: rgba(64, 126, 201, 0.26); }
.reader-fallback { margin-top: 1.2rem; color: var(--ink-mute); font-size: var(--step-1); }

/* ================================================== MOBILE PAGER READER ==
   ≤768px the reader becomes a single-page swipeable pager. Critically there is
   NO nested vertical scroll container: .reader-viewport is height:auto in this
   mode, so vertical page scroll always belongs to the document. The stage uses
   touch-action: pan-y pinch-zoom, which hands vertical panning and pinch-zoom
   straight to the browser and only leaves horizontal gestures to our swipe
   handler. Nothing calls preventDefault on a vertical gesture.               */
.reader-mobile-only { display: none; }
.pager-stage, .pager-hint { display: none; }

@media (max-width: 768px) {
  :root { --header-h: 60px; }
  .reader-desktop-only { display: none !important; }
  .reader-mobile-only { display: flex; }

  .reader-shell { margin-top: 1.8rem; border-radius: var(--radius); }

  .reader-toolbar {
    flex-wrap: nowrap; gap: 0.5rem; padding: 0.5rem 0.6rem;
    /* tucks directly under the sticky site header */
    position: sticky; top: var(--header-h, 51px); justify-content: space-between;
  }
  .reader-pages { font-size: 0.82rem; white-space: nowrap; }
  .reader-tools { gap: 0.35rem; }
  /* One download affordance is already pinned in the site header, and the
     escape row below the reader repeats it — three would be noise. */
  .reader-download { display: none; }
  /* The toolbar already says "Page N of 20"; the on-canvas badge would only
     collide with it under the sticky bar. */
  .pager-stage .page-badge { display: none; }

  .pager-btn {
    display: inline-grid; place-items: center;
    width: 44px; height: 44px; min-width: 44px; min-height: 44px;
    border-radius: 50%; border: 1.5px solid var(--rule);
    background: #fff; color: var(--navy); cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .pager-btn[disabled] { opacity: 0.35; cursor: default; }
  .reader-download {
    min-height: 44px; padding: 0.5rem 0.9rem; font-size: 0.84rem; white-space: nowrap;
  }

  /* No overflow, no fixed height: the document owns vertical scrolling. */
  .reader-viewport {
    height: auto; max-height: none; overflow: visible;
    overscroll-behavior: auto; background: var(--paper-tint);
    /* height:auto collapses the viewport to nothing before the first page
       renders, and .reader-status is absolutely positioned inside it — so the
       "Preparing the reader…" line used to spill over the swipe hint below.
       Reserve the status block's height; loaded pages are far taller. */
    min-height: 116px;
  }
  .pdf-pages { display: none; }

  .pager-stage {
    display: block; position: relative; width: 100%;
    padding: 0.7rem 0 0.9rem; background: var(--paper-tint);
    touch-action: pan-y pinch-zoom;   /* vertical scroll + pinch stay native */
    -webkit-tap-highlight-color: transparent;
    overflow-x: hidden;
  }
  .pager-stage .pdf-page {
    margin-inline: auto; max-width: 100%; transition: transform 0.18s var(--ease);
  }
  .pager-stage .pdf-page canvas { max-width: 100%; height: auto; }
  /* Double-tap zoom: horizontal-only overflow, never a vertical scroll trap. */
  .pager-stage[data-zoomed='true'] { overflow-x: auto; touch-action: pan-x pan-y pinch-zoom; }
  .pager-stage[data-zoomed='true'] .pdf-page { margin-inline: 0; max-width: none; }
  .pager-stage[data-zoomed='true'] .pdf-page canvas { max-width: none; }

  .pager-hint {
    display: block; text-align: center; padding: 0.15rem 1rem 0.7rem;
    font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--ink-mute); background: var(--paper-tint);
  }

  .reader-escape {
    display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: 1.1rem;
    align-items: center;
  }
  .reader-escape .btn { flex: 1 1 100%; justify-content: center; min-height: 46px; }
  /* Citation links stay tappable at mobile scale: a slightly stronger
     highlight so they read as links at thumbnail size, plus an invisible
     padded hit area so a ~7px-tall link box at fit-to-width is still
     comfortably tappable with a thumb. Deliberately a highlight and not an
     underline — the paper's own artwork already underlines its links, and a
     red rule on top of that read as an error mark. */
  .pager-stage .annotationLayer .linkAnnotation > a {
    background: rgba(64, 126, 201, 0.2);
  }
  .pager-stage .annotationLayer .linkAnnotation > a::after {
    content: ''; position: absolute; inset: -5px -4px;
  }
  .pager-stage .annotationLayer .linkAnnotation > a:active { background: rgba(64, 126, 201, 0.34); }
}
@media (min-width: 769px) { .reader-escape { display: none; } }

/* ------------------------------------------------------------- authors -- */
.authors-section { padding: clamp(3.5rem, 7vw, 6.5rem) 0; background: var(--paper-tint); }
.authors { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.2rem; margin-top: 2.6rem; }
.author {
  background: #fff; border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 1.9rem 1.8rem;
  display: grid; grid-template-columns: auto 1fr; gap: 0.35rem 1.35rem;
  align-content: start;
}
/* 200x200 source images — displayed at 88px so they are never upscaled. */
.author-avatar {
  grid-row: 1 / span 4; width: 88px; height: 88px; border-radius: 50%;
  object-fit: cover; border: 2px solid var(--rule);
  background: var(--paper-tint); image-rendering: auto;
}
.author-name { font-size: var(--step-1u); color: var(--navy); font-weight: 700; align-self: end; }
.author-name span { font-weight: 500; color: var(--ink-mute); font-size: 0.75em; letter-spacing: 0; }
.author-role { margin-top: 0.35rem; font-weight: 600; color: var(--blue); font-size: 0.88rem; }
.author-bio { margin-top: 0.7rem; color: var(--ink-mute); font-size: 0.88rem; line-height: 1.6; }
.author > .author-bio, .author > .author-links { grid-column: 2; }

.author-links {
  display: flex; flex-wrap: wrap; gap: 0.45rem; margin-top: 1rem; list-style: none;
  padding: 0;
}
.author-links a {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.78rem; font-weight: 600; text-decoration: none;
  color: var(--navy); background: var(--paper-tint);
  border: 1px solid var(--rule); border-radius: 999px; padding: 0.34rem 0.75rem;
  transition: background 0.18s var(--ease), color 0.18s var(--ease), border-color 0.18s var(--ease);
}
.author-links a:hover { background: var(--blue); border-color: var(--blue); color: #fff; }
.author-links svg { flex: none; }

.contrib-title {
  margin-top: 3.2rem; font-size: var(--step-1); letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--blue); font-weight: 600;
}
.contributors {
  list-style: none; margin: 1.4rem 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 2.5rem;
}
/* ROUND 6: name on line one, affiliation on line two — ALWAYS, for every
   person, however short the affiliation. The previous rule was a wrapping flex
   row, so "Laura Okafor  CEO, Perry & Perry Academy" sat inline while longer
   affiliations wrapped, which read as accidental rather than designed.
   The li stays a grid ITEM so both columns share a row height and the divider
   rules stay level across the two columns; `align-content: start` keeps the
   text at the top of a taller row instead of floating in the middle. */
.contributors li {
  display: grid; align-content: start; gap: 0.2rem;
  padding: 0.85rem 0; border-bottom: 1px solid var(--rule);
}
.contrib-name { font-weight: 600; color: var(--navy); font-size: 0.94rem; line-height: 1.35; }
.contrib-aff { color: var(--ink-mute); font-size: 0.83rem; line-height: 1.45; }

/* --------------------------------------------------------------- share -- */
/* ROUND 6 RECOLOUR. This section used to be a saturated blue field with
   reversed (white-on-blue) treatment throughout. It is now Calla Lily's
   lightest green, so every pair inside it was rechecked against the new
   surface and every reversed treatment was flipped back to navy-on-light.
   Measured contrast on #DDE9D8:
     navy #1F2B51 body/headings ....... 10.98:1  (AA body, AAA)
     ink-mute #4A5372 lede ............  6.03:1  (AA body)
     blue #19408F campaign line/label .  7.70:1  (AA body)
     white on navy button fill ........ 13.79:1
     navy button edge vs surface ...... 10.98:1  (AA non-text, 3:1)
     surface vs navy-deep footer ...... 13.22:1  (boundary stays obvious)
   Gold is DELIBERATELY not used for text or focus here — it sits at 1.3:1 on
   this green. It survives only as the decorative rule under the eyebrow. */
.share-section {
  background: var(--cl-green-75); color: var(--navy);
  padding: clamp(3.5rem, 7vw, 6rem) 0;
  /* Hairline against the white section above; the navy footer below needs no
     help at 13.2:1. */
  border-top: 1px solid var(--cl-green-200);
}
.share-section .eyebrow { color: var(--blue); }
.share-title { color: var(--navy); }
.share-section .campaign-line { color: var(--blue); }

/* ROUND 10 §1-REVISED — COPY FIRST, THEN PICK A DESTINATION.
   The round-5 two-column split (buttons left, caption right) is gone, along
   with the round-8 sticky-buttons trick that existed only to fill the dead area
   beside two caption cards. There is now one caption box across the top and the
   destinations underneath it, so the visual order matches the DOM order and
   both match the instruction: copy, then choose where to post. */
.share-caption-primary {
  margin-top: 2.2rem; max-width: 68ch;
}
/* Eleven destinations is too many for a wrapping flex row, so the buttons are a
   real grid. Full page width now, so it opens out to four columns. */
.share-buttons {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.7rem;
  align-content: start; margin-top: 1.1rem;
}
/* Round 8 §3 — WHITE buttons on the green, per the client. White on #DDE9D8 is
   only 1.26:1 (measured), so the button edge cannot be the white fill itself:
   the boundary is carried by a navy-tinted hairline, #6E7899, which measures
   3.48:1 against the green AND 4.37:1 against the white fill — both sides of
   the edge clear the 3:1 non-text contrast minimum in WCAG 1.4.11. A soft
   shadow adds depth on top of that but is never load-bearing. Label and icon
   are navy at 13.79:1 on the white fill. The copy-link button is EXPLICITLY
   untouched: it stays transparent and outlined as the secondary action. */
.share-btn {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-family: inherit; font-size: 0.9rem; font-weight: 600; text-align: left;
  color: var(--navy); background: var(--paper); border: 1.5px solid #6b83a8;
  border-radius: 999px; padding: 0.7rem 1.1rem; cursor: pointer; min-height: 44px;
  box-shadow: 0 1px 2px rgba(0, 32, 91, 0.10), 0 4px 10px rgba(0, 32, 91, 0.07);
  transition: transform 0.18s var(--ease), background 0.18s var(--ease),
              color 0.18s var(--ease), border-color 0.18s var(--ease),
              box-shadow 0.18s var(--ease);
}
/* Round 13 — these are now real <a> elements so that iOS and Android can hand
   the link to the installed app. They must remain visually identical to the
   buttons they replaced. */
.share-btn { text-decoration: none; -webkit-tap-highlight-color: transparent; }
.share-btn:visited { color: var(--navy); }
.share-btn:visited:hover { color: #fff; }
.share-btn svg { flex: none; }
.share-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-btn:hover {
  transform: translateY(-2px); background: var(--navy); color: #fff;
  border-color: var(--navy);
  box-shadow: 0 2px 4px rgba(0, 32, 91, 0.14), 0 10px 20px rgba(0, 32, 91, 0.13);
}
.share-btn:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(0, 32, 91, 0.14); }
/* Copy link is the secondary action: outlined rather than filled. Unchanged. */
.share-btn-copy {
  background: transparent; color: var(--navy); border: 1.5px solid var(--navy);
  box-shadow: none;
}
.share-btn-copy:hover { background: var(--navy); color: #fff; border-color: var(--navy); box-shadow: none; }

/* Round 8 §4 — TWO captions stacked in the right-hand column, which is what
   gives that column enough weight to sit beside the eleven-button grid. */


/* Share caption card. */
.share-caption {
  margin-top: 0; max-width: none;
  background: var(--paper);
  border: 1px solid var(--cl-green-200);
  border-radius: var(--radius); padding: 1.25rem 1.4rem 1.15rem;
}
/* Round 13 — mobile spacing at the top of the caption card.

   Client: "the spacing is slightly off where the top of the caption box lives."
   Measured on the live site at 390px: 20px of card padding above the 36px copy
   button, but only 11px of clearance BELOW it before the dashed caption box.
   The 0.7rem margin was tuned for a plain text label; the taller button ate
   into it, so the row read as loose on top and cramped underneath.

   At 360px it was worse — label and button no longer fitted on one line (they
   needed 282px of 281px available), so the button wrapped onto its own row and
   the gap jumped to 64px. Reducing the column gap buys the 1px back; the row
   gap keeps the wrap tidy on genuinely narrow screens like a 320px SE. */
.share-caption-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.6rem 0.75rem; flex-wrap: wrap; margin-bottom: 1rem;
}
.share-caption-label { min-width: 0; }
.share-caption-label {
  font-size: var(--step-1); font-weight: 600; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--blue);
}
.share-caption-text {
  font-size: 0.94rem; line-height: 1.6; color: var(--navy); white-space: pre-wrap;
  /* The tagged canonical URL is one unbreakable token and overflowed the card
     at 375px before round 10. Break it anywhere rather than clip it. */
  overflow-wrap: anywhere; word-break: break-word;
  background: var(--cl-green-100); border-radius: var(--radius-sm);
  padding: 0.85rem 1rem; border: 1px dashed var(--cl-green-200);
}
.share-caption-copy {
  display: inline-flex; align-items: center; gap: 0.4rem; min-height: 36px;
  font-family: inherit; font-size: 0.8rem; font-weight: 600; cursor: pointer;
  color: var(--navy); background: transparent; border: 1.5px solid var(--navy);
  border-radius: 999px; padding: 0.35rem 0.9rem;
}
.share-caption-copy:hover { background: var(--navy); color: #fff; border-color: var(--navy); }

/* The destination grid narrows with the viewport; the caption box above it is
   full-width at every size, because it is the first step in the flow. */
@media (max-width: 900px) {
  .share-buttons { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .share-buttons { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* ====================================================== INSTAGRAM SHARE KIT
   Round 6. Sits between the light-green Share section and the Take-action band,
   on plain paper so the three read as distinct bands going into the navy footer.
   All type here is navy or ink-mute on white: 13.8:1 and 7.6:1. */
.sharekit-section { background: var(--paper); padding: clamp(3.5rem, 7vw, 6rem) 0; }
/* ROUND 11 — .sharekit-lede, .sharekit-actions, .sharekit-actions-note and
   .sharekit-savenote were removed with the bulk zip download. The stage now
   follows the section title directly, so it carries the spacing the lede used
   to provide. */
.sharekit-stage { margin-top: 2.2rem; }
.sharekit-tabs { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.sharekit-tab {
  font-family: inherit; font-size: 0.9rem; font-weight: 600; cursor: pointer;
  min-height: 44px; padding: 0.6rem 1.15rem; border-radius: 999px;
  color: var(--navy); background: transparent; border: 1.5px solid var(--rule);
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease), color 0.18s var(--ease);
}
.sharekit-tab:hover { border-color: var(--navy); }
.sharekit-tab[aria-selected="true"] { background: var(--navy); border-color: var(--navy); color: #fff; }

.sharekit-panel {
  margin-top: 1.6rem; display: grid; grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(1.6rem, 3.5vw, 3rem); align-items: start;
}
.sharekit-panel:focus-visible { outline-offset: 6px; }
/* `display: grid` above beats the UA `[hidden] { display: none }`, so the
   inactive tab panels have to be re-hidden explicitly. */
.sharekit-panel[hidden] { display: none; }
.sharekit-preview { display: grid; grid-template-columns: auto 1fr; gap: 1.4rem; align-items: start; }

/* Phone mockup — a plain CSS device shell, no image asset. The Story frame is
   1080x1920, so the screen is locked to 9:19.5 and the art fills it exactly. */
.phone { margin: 0; }
.phone-shell {
  /* The Story art is 1080x1920, so the SCREEN is locked to exactly 9:16 and the
     frame is never cropped. The extra top padding is bezel, not screen, so the
     notch sits above the artwork rather than over the Calla Lily lockup. */
  position: relative; width: clamp(158px, 18vw, 224px); aspect-ratio: 9 / 16;
  background: var(--navy-deep); border-radius: 26px; padding: 20px 7px 9px;
  box-sizing: content-box;
  box-shadow: 0 24px 50px -26px rgba(21, 29, 56, 0.75), 0 0 0 1px var(--hairline);
}
.phone-notch {
  position: absolute; top: 7px; left: 50%; transform: translateX(-50%);
  width: 30%; height: 6px; border-radius: 999px; background: rgba(255, 255, 255, 0.28);
}
.phone-screen {
  display: block; width: 100%; height: 100%; object-fit: cover;
  border-radius: 20px; background: var(--navy);
}
.phone-cap, .sharekit-square figcaption {
  margin-top: 0.6rem; font-size: 0.8rem; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-mute);
}
.sharekit-square { margin: 0; }
.sharekit-square img {
  display: block; width: 100%; height: auto; border-radius: var(--radius);
  border: 1px solid var(--hairline);
}

.sharekit-side { display: grid; gap: 1.1rem; }
/* Round 15 — the two "Download feed post" / "Download Story" buttons are gone.

   Client: "Instead of a button that says 'download feed post' and 'download
   story' could we introduce a download button on the top right corner of each
   image? That is more universally recognized as downloading image and it would
   save the bulk of making those buttons and it pushing the caption box around."

   Both points hold. The corner download affordance is the convention people
   already know from photo apps, and removing the button row takes a 44px block
   out of the side column, so the caption card no longer gets shoved down.

   White fill with a navy-tinted hairline, matching the share buttons: the images
   are dark navy artwork, so the control needs its own opaque surface to stay
   legible rather than relying on the image behind it. 44px square meets the
   WCAG 2.5.8 minimum target size. */
.sharekit-square, .phone-shell { position: relative; }
.kit-dl {
  position: absolute; top: 0.65rem; right: 0.65rem; z-index: 3;
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 999px;
  color: var(--navy); background: var(--paper);
  border: 1.5px solid #6b83a8; text-decoration: none;
  box-shadow: 0 1px 2px rgba(0, 32, 91, 0.16), 0 6px 14px rgba(0, 32, 91, 0.18);
  transition: transform 0.18s var(--ease), background 0.18s var(--ease),
              color 0.18s var(--ease), border-color 0.18s var(--ease);
}
.kit-dl:hover {
  background: var(--navy); color: #fff; border-color: var(--navy);
  transform: translateY(-1px);
}
.kit-dl:active { transform: translateY(0); }
/* The phone screen is inset behind a bezel, so nudge the control inward to stay
   clear of the rounded corner and the notch. */
.phone-shell .kit-dl { top: 0.9rem; right: 0.9rem; }
/* The caption box reuses the Share-section component, restyled for paper. */
.sharekit-caption { background: var(--paper-tint); border-color: var(--hairline); }
.sharekit-caption .share-caption-label { color: var(--blue); }
.sharekit-caption .share-caption-text {
  background: var(--paper); color: var(--navy);
  border: 1px dashed var(--rule); white-space: pre-wrap;
}
.sharekit-caption .share-caption-copy { color: var(--navy); border-color: var(--navy); }
.sharekit-caption .share-caption-copy:hover { background: var(--navy); color: #fff; }

/* How to post */
/* Round 8 §5 — "How to post it" was three dense numbered lists side by side,
   14 steps of small type. It is now three native <details> disclosures, closed
   by default, one per placement, at roughly half the words. Native
   details/summary gives correct semantics and keyboard behaviour for free. */
.howto { margin-top: clamp(2.6rem, 5vw, 4rem); border-top: 1px solid var(--hairline); padding-top: 2.2rem; }
.howto-title { font-size: var(--step-2); color: var(--navy); }
.howto-item {
  margin-top: 0.7rem; background: var(--paper-tint);
  border: 1px solid var(--hairline); border-radius: var(--radius);
}
.howto-item + .howto-item { margin-top: 0.6rem; }
.howto-item[open] { background: var(--paper); border-color: var(--rule); }
.howto-summary {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.95rem 1.25rem; cursor: pointer; min-height: 48px;
  font-weight: 700; font-size: 1.02rem; color: var(--navy);
  list-style: none; border-radius: var(--radius);
}
.howto-summary::-webkit-details-marker { display: none; }
.howto-summary:hover { background: rgba(0, 32, 91, 0.04); }
.howto-summary-label { display: inline-flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; }
.howto-chev { flex: none; color: var(--blue); transition: transform 0.2s var(--ease); }
.howto-item[open] .howto-chev { transform: rotate(180deg); }
.howto-flag {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--navy-deep); background: var(--gold); border-radius: 999px; padding: 0.2rem 0.6rem;
}
.howto-steps {
  margin: 0; padding: 0 1.35rem 1.35rem 2.5rem; display: grid; gap: 0.5rem;
}
.howto-steps li { color: var(--ink-mute); font-size: 0.93rem; line-height: 1.6; }
.howto-steps strong { color: var(--navy); }
@media (prefers-reduced-motion: reduce) { .howto-chev { transition: none; } }

/* ============================================================== ANCHOR QUOTE
   Round 9 §3. A single full-width quiet band carrying the campaign's
   designated emotional anchor. It also does structural work: it separates the
   white share kit from the take-action bands so the two do not run together. */
/* Round 23 — client: the band "is heavy on the left with text" and the right
   side was doing nothing. A gradient rather than an ornament, running LIGHT ON
   THE LEFT to DEEPER ON THE RIGHT, which does two jobs at once:

     · it puts tonal weight on the empty right side, so the band stops reading
       as a left-aligned block on a flat field, and
     · it lightens exactly where the type sits, so the quote gains contrast
       instead of paying for the decoration.

   Measured navy on this ramp: 9.94:1 at the left end, 7.61:1 at the right.
   Both clear AAA, so the sentence is legible at every point along it.

   The band also has to stay visually separate from the #f2f3f6 section beneath
   it — the failure the client caught in round 21, where a tint sat only 2.5 dE
   from its neighbour and effectively vanished. Perceptual distance here ranges
   12.6 to 24.7 dE, so it reads as its own surface all the way across.

   The radial bloom sits at the TOP LEFT, behind the type, not on the right.
   First attempt put it top-right and it fought the ramp — the white washed out
   the exact area the ramp was darkening, cancelling the weight the gradient was
   there to create. Behind the text it reinforces both goals instead: the quote
   gets a lighter ground, and the right side keeps its depth. */
.anchor-quote {
  background:
    radial-gradient(90% 130% at 6% 12%, rgba(255, 255, 255, 0.62) 0%, rgba(255, 255, 255, 0) 62%),
    linear-gradient(104deg, #cfdcef 0%, #c3d6eb 38%, #a9c3e2 78%, #9dbbdf 100%);
  border-top: 1px solid var(--blue-300);
  padding: clamp(3rem, 6vw, 5rem) 0;
}
/* On narrow screens the text fills the width, so a horizontal ramp would run
   underneath it and cost contrast at the right-hand end of every line. The
   ramp turns vertical, where nothing is competing with it. */
@media (max-width: 700px) {
  .anchor-quote {
    background:
      radial-gradient(120% 90% at 100% 0%, rgba(255, 255, 255, 0.45) 0%, rgba(255, 255, 255, 0) 60%),
      linear-gradient(168deg, #cfdcef 0%, #c1d4ea 50%, #b3cae5 100%);
  }
}
/* Round 15 — client: this quote "is way too scrunched up on desktop".

   The cause was a unit-scope mistake. `max-width: 34ch` sat on the FIGURE, whose
   font-size is body copy (~10px per ch), so it resolved to 340px. The quote
   inside renders at --step-3, which is 48px at 1440px — roughly 24px per
   character. A 48px quote in a 340px column is about 14 characters per line, so
   this 100-character sentence was breaking over EIGHT lines in a narrow ribbon.

   The measure now sits on the paragraph itself, so `ch` is finally computed
   against the type it is actually constraining. 24ch of 48px type is ~575px and
   lands the sentence in three or four lines. Line-height opens slightly too:
   1.24 was set when the block was eight lines deep and needed the compression. */
.anchor-quote figure { margin: 0; max-width: none; }
.anchor-quote blockquote { margin: 0; }
.anchor-quote blockquote p {
  font-size: var(--step-3); line-height: 1.3; color: var(--navy);
  font-weight: 700; letter-spacing: -0.015em; text-wrap: balance;
  max-width: 24ch;
}
.anchor-quote blockquote p::before { content: '\201C'; }
.anchor-quote blockquote p::after { content: '\201D'; }
.anchor-quote figcaption {
  margin-top: 1.1rem; font-size: var(--step-1u); font-weight: 600; color: var(--blue);
}
.anchor-quote figcaption span { font-weight: 400; color: var(--ink-mute); }

/* ============================================================= TAKE ACTION
   Round 8 §6. Rebuilt. Was three tall cards crammed side by side; the client
   said it was "A lot to look at and not really compelling" and explicitly
   authorised spreading it over more vertical space.

   It is now three stacked FULL-WIDTH bands in descending order of consequence,
   each on its own surface so they read as three separate asks rather than a
   grid of options:
     1  .act-primary   white paper-tint, largest type          — the ask
     2  .act-forward   plain paper                             — the forward
     3  .act-media     tinted, compact, two columns            — media

   The word count across the three is roughly half what it was. */
/* ROUND 17 — one tinted surface for the whole section, with the three actions as
   contained cards on top of it. Before, each band painted its own full-bleed
   background and the intro sat on white, so the heading looked like it belonged
   to nothing and the three actions looked like three unrelated sections that
   happened to be adjacent. */
/* ROUND 24 — the Take Action field is blush (#ffefef) at the client's
   direction, replacing the page tint. The two panels inside it that were also
   on the tint — the email template and the paper-meta strip — move with it, so
   the band stays one surface family rather than pink with grey-blue insets. */
.actions { border-top: 1px solid var(--hairline); background: var(--blush); }
.actions-intro { padding: clamp(3.2rem, 6vw, 5rem) 0 clamp(1.4rem, 2.6vw, 2rem); }
.actions-lede { margin-top: 0.8rem; max-width: 46ch; }
/* The cards. `.shell` inside each card still sets the shared left edge for the
   content, so the Round 15 alignment work survives — the card itself is what
   moved, not the text inside it. */
.actions-cards {
  padding-bottom: clamp(3rem, 6vw, 5rem);
  display: grid; gap: clamp(1rem, 2vw, 1.4rem);
}

.act {
  background: var(--paper); border: 1px solid var(--hairline);
  border-radius: var(--radius-lg); overflow: clip;
}
/* Round 15 — client: "The spacing for 'take action' isn't aligning with 'for
   deans, program directors..' sections below it. It is fine on mobile, but
   desktop looks un alligned."

   Correct, and measurable. The bands' max-width was being centred inside the
   shell, so at 1440px their left edges were at 380px, 360px and 130px — three
   different edges — while the section heading above them sat at 130px. On mobile
   the max-widths never bind, so all four collapsed onto the same edge and it
   looked right. Anchoring the measure to the start of the shell puts every band
   and the heading on one left edge at every width. */
/* The inner wrapper is no longer a `.shell` — it sits inside one. Horizontal
   padding is the card's own inset, so all three cards indent their content by
   the same amount and the cards themselves align to the section heading. */
.act-inner { padding: clamp(1.9rem, 3.6vw, 2.8rem) clamp(1.4rem, 3vw, 2.6rem); }
/* The measure has to constrain the TEXT, not the container. `.act-inner` also
   carries `.shell`, whose `margin-inline: auto` centres the box, so capping the
   box itself centred a narrowed band instead of narrowing the line length —
   which is exactly how the left edges drifted to 380px and 360px while the
   heading stayed at 130px. Keeping the shell box intact and limiting the
   children preserves the reading measure AND the shared left edge. */
.act-inner > * { max-width: 62ch; }
/* ROUND 17 — the card index. Client: "Maybe the sections need to be numbered
   below it to make sense?" Deliberately NOT green: green is now the language of
   steps WITHIN a card (the two answers, the three forward actions), so the index
   uses Calla Lily's coral to stay a different kind of thing. aria-hidden,
   because the count is already carried by the heading and the reading order. */
.act-index {
  font-size: 0.82rem; font-weight: 700; letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  width: 1.75rem; height: 1.75rem; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--gold); color: var(--navy);
  margin-bottom: 0.9rem;
}
.act-audience {
  font-size: var(--step-1); font-weight: 600; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--blue);
}
.act-title { font-size: var(--step-2); color: var(--navy); line-height: 1.2; margin-top: 0.7rem; }
.act-title-lg { font-size: var(--step-3); letter-spacing: -0.015em; }
.act-title-sm { font-size: var(--step-1u); }
.act-body { color: var(--ink-mute); font-size: 0.98rem; line-height: 1.7; margin-top: 1rem; }
.act-body-lead { font-size: var(--step-1u); }
.act-cta { margin-top: 1.6rem; }
.act-cta .btn { min-height: 44px; }

/* Band 1 — the institutional ask.

   ROUND 16 — client: "The design for these sections is not the best, revisit the
   UX and UI for those sections." Two columns on desktop. The left column is the
   decision (who it is for, the headline, the ask, the call). The right column is
   the objection handling, in three named cards. `max-width: none` on the grid
   children is deliberate: the Round 15 measure cap belongs on the text inside
   the columns, not on the columns themselves, or the second column would be
   squeezed to a 68ch box and the grid would collapse visually. */

.act-inner-primary {
  display: grid; grid-template-columns: 0.95fr 1.05fr;
  gap: clamp(2rem, 4vw, 3.6rem); align-items: start;
}
.act-inner-primary > * { max-width: none; }
.act-lead > *, .act-detail > * { max-width: 54ch; }
/* Sticks the ask alongside the cards on tall desktop viewports so the sentence
   is still on screen while the reader works down the right-hand column. Capped
   so it never traps a short column, and off entirely on small screens. */
@media (min-width: 1024px) {
  .act-lead { position: sticky; top: calc(var(--header-h, 64px) + 1.5rem); }
}
.act-lead-note {
  margin-top: 1.4rem; color: var(--ink-mute); font-size: 0.92rem; line-height: 1.65;
}

/* The anchor of the band.
   ROUND 19 — the deep sage was wrong and the client said so. This is the light
   Calla Lily green with navy type (10.98:1).
   The one problem with a pale panel is that it only measures 1.26:1 against the
   white card, so on its own it would barely read as a panel at all — hence the
   green hairline, which gives it an edge without adding weight. */
.act-askbox {
  /* ROUND 24 — the sage panel is now blush, at the client's direction. */
  margin-top: 1.5rem; background: var(--blush-deep);
  border: 1px solid var(--blush-rule); border-radius: var(--radius);
  padding: clamp(1.2rem, 2.4vw, 1.7rem) clamp(1.2rem, 2.4vw, 1.8rem);
}
/* ROUND 19 — the lead-in can no longer be gold: gold on this green is 1.30:1,
   effectively invisible. Blue keeps it distinct from the navy sentence it
   introduces, at 7.70:1.
   It stays INLINE with the sentence. Lifting it out as its own label leaves the
   locked wording starting on a lowercase "would", which reads as a typo. */
.act-ask-lead { color: var(--blue); font-weight: 700; }

/* The right-hand column: three cards, one question each. No top strokes and no
   decorative rules, per the standing directive on boxed content. */
.act-detail { display: grid; gap: 1rem; }
.act-card {
  background: var(--paper); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: clamp(1.1rem, 2.2vw, 1.5rem);
}
.act-card-title {
  margin: 0; font-size: 1.05rem; font-weight: 700; color: var(--navy); line-height: 1.35;
}
.act-card-body {
  margin: 0.6rem 0 0; color: var(--ink-mute); font-size: 0.95rem; line-height: 1.65;
}
/* Numbered so the two answers read as a deliverable, not as prose. The counter
   is drawn rather than using a list marker so the number can carry the brand
   blue at a fixed width and the text can align to a single left edge. */
.act-answers { margin: 0.85rem 0 0; padding: 0; list-style: none; display: grid; gap: 0.6rem;
  counter-reset: act-answer; }
.act-answers li {
  counter-increment: act-answer; position: relative; padding-left: 2rem;
  color: var(--navy); font-size: 0.95rem; line-height: 1.55;
}
.act-answers li::before {
  content: counter(act-answer); position: absolute; left: 0; top: 0;
  width: 1.4rem; height: 1.4rem; border-radius: 50%;
  display: grid; place-items: center;
  /* ROUND 17 — client: "Match the green on 'bring two answers to the call'
     circle numbers, it should match the green we use in the Lara Zibners quote
     background." That band is #eef4ec, which measures 1.12:1 against a white
     card — the disc would have vanished. This is the next step of the same
     Calla Lily green, with the palette's own green hairline to give the disc an
     edge. The numeral is navy at 10.98:1, so the information never depends on
     the fill being visible. */
  background: var(--blush-deep); border: 1px solid var(--blush-rule);
  color: var(--navy);
  font-size: 0.72rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.act-card-files .act-toolkit-list { margin-top: 0.85rem; gap: 0.7rem; }
.act-card-files .act-toolkit-list li {
  display: grid; gap: 0.15rem; padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--hairline);
}
.act-card-files .act-toolkit-list li:last-child { padding-bottom: 0; border-bottom: 0; }
/* The playbook's locked ask wording. Given real presence: this is the sentence
   the whole campaign turns on. */
/* ROUND 10 §9 — the client asked for the stroke beside this box to go, on the
   same standing directive that removed the author-box top strokes: decorative
   rules on boxed content "look too much like an AI did it". The box keeps its
   own quiet 1px containing edge; the 4px blue rule on the left is gone. */
.act-ask {
  margin: 0; font-size: clamp(1.12rem, 0.98rem + 0.5vw, 1.42rem);
  /* ROUND 19: navy on the light green panel — 10.98:1. */
  line-height: 1.45; color: var(--navy); font-weight: 500;
}
/* ROUND 16 removed .act-pull ("We are not asking you to build a new program"),
   .act-deliverables-title and .act-deliverables. The sentences themselves are all
   still on the page — the first is now .act-card-title on the first card of the
   right-hand column, and the two deliverables are .act-answers — so this is dead
   CSS removal, not a copy cut. */

/* Band 2 — the forward.

   ROUND 16: the intro and the template sit side by side on desktop instead of
   stacking, and the three actions are a numbered strip rather than the tail of a
   paragraph. The template column is the wider of the two because it holds a real
   email and short lines make it look like filler. */

.act-inner-forward {
  display: grid; grid-template-columns: 0.88fr 1.12fr;
  gap: clamp(2rem, 4vw, 3.6rem); align-items: start;
}
.act-inner-forward > * { max-width: none; }
.act-fwd-lead > * { max-width: 46ch; }
/* At 0.88fr the eyebrow broke as "KNOW A DEAN, CHAIR OR CURRICULUM / LEAD?",
   orphaning one word. Balanced wrapping puts the break after the first comma. */
.act-fwd-lead .act-audience { text-wrap: balance; }
.act-inner-forward .act-template { margin-top: 0; }
.act-steps {
  margin: 1.5rem 0 0; padding: 0; list-style: none; display: grid; gap: 0.55rem;
  counter-reset: act-step;
}
.act-steps li {
  counter-increment: act-step; position: relative; padding-left: 2.1rem;
  color: var(--navy); font-weight: 600; font-size: 0.98rem; line-height: 1.5;
}
.act-steps li::before {
  content: counter(act-step); position: absolute; left: 0; top: -0.05rem;
  width: 1.5rem; height: 1.5rem; border-radius: 50%;
  display: grid; place-items: center;
  /* ROUND 17 — client: "Same for 'know a dean' step by step circles, make those
     circles green as well." Identical treatment to the answer discs above, so
     the two bands read as one system. */
  background: var(--blush-deep); border: 1px solid var(--blush-rule);
  color: var(--navy);
  font-size: 0.74rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.act-template { margin-top: 1.6rem; background: var(--blush); border-color: var(--blush-rule); }
.act-template .share-caption-label,
.action-template .share-caption-label { color: var(--blue); }
.action-template { margin-top: 1.6rem; background: var(--blush); border-color: var(--blush-rule); }
.action-template-text {
  background: var(--paper); color: var(--navy); border: 1px dashed var(--rule);
  white-space: pre-wrap; font-size: 0.9rem;
}
.action-template .share-caption-copy { color: var(--navy); border-color: var(--navy); }
.action-template .share-caption-copy:hover { background: var(--navy); color: #fff; }
.tmpl-subject { font-weight: 700; }
/* Placeholder chips: obvious at a glance what has to be swapped out. */
.tmpl-slot {
  background: #fdf1c9; border: 1px dashed #c9a21a; border-radius: 4px;
  padding: 0 0.28rem; font-weight: 600; color: var(--navy);
}
/* The URL slot is NOT a placeholder — app.js fills it with the real canonical
   URL so the rendered template matches the copied one exactly. Styled as a
   filled value, not as something to swap out. */
.tmpl-slot-url {
  background: transparent; border: 0; padding: 0; color: var(--blue);
  font-weight: 600; text-decoration: underline; text-underline-offset: 2px;
  word-break: break-word;
}
/* The playbook's verbatim credit line, closing the template. */
.tmpl-credit { display: inline-block; font-size: 0.82rem; color: var(--ink-mute); line-height: 1.5; }



/* ROUND 11 — the dean's toolkit. Two real downloads, set as a plain list rather
   than buttons: a dean scanning for material wants to see what the files ARE,
   not two competing CTAs above the one that matters. No decorative stroke on the
   container, per the standing directive. */
.act-toolkit { margin-top: 1.6rem; }
.act-toolkit-title {
  font-weight: 700; color: var(--navy); font-size: var(--step-1u); margin: 0;
}
.act-toolkit-list {
  margin: 0.7rem 0 0; padding: 0; list-style: none; display: grid; gap: 0.55rem;
}
.act-toolkit-list li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 0.7rem;
}
.act-toolkit-list a {
  color: var(--blue); font-weight: 600; font-size: 0.98rem;
  text-underline-offset: 3px;
}
.act-toolkit-list a:hover { color: var(--navy); }
.act-toolkit-meta {
  color: var(--ink-mute); font-size: 0.8rem; letter-spacing: 0.02em;
  white-space: nowrap;
}

/* ROUND 10 §10 — one quiet sentence, no heading and no card. The two names are
   plain text until /config.js → FOLLOW.lara / FOLLOW.adam carry real URLs. */
/* ROUND 17: .follow / .follow-line removed with the markup — the client asked
   for that closing line to go entirely. */

/* Band 3 — media. The quietest treatment on the page by design. */
/* All three cards share one surface. Band 3 was a tinted band before, but the
   SECTION is now that same tint, so a tinted card would have dissolved into it.
   It stays the quietest through size and type, not colour. */
.act-inner-media {
  max-width: none; display: grid; grid-template-columns: 1.35fr 1fr; gap: 2.4rem;
  align-items: start;
}
.act-speakers { margin: 1.1rem 0 0; padding: 0; list-style: none; display: grid; gap: 0.75rem; }
.act-speakers li {
  color: var(--ink-mute); font-size: 0.92rem; line-height: 1.6;
  padding-left: 0.95rem; border-left: 2px solid var(--blush-rule);
}
.act-speakers strong { color: var(--navy); }
/* Replaces the five-row metadata table, which was the single most cluttering
   element in the old band. One factual line. */
.act-meta {
  font-size: 0.86rem; line-height: 1.6; color: var(--ink-mute);
  background: var(--paper); border: 1px solid var(--hairline);
  border-radius: var(--radius-sm); padding: 0.95rem 1.1rem;
}
.act-meta em { color: var(--navy); font-style: italic; }
.act-media .act-cta { margin-top: 1.1rem; }
.act-media-lead { margin-top: 0.7rem; }
.act-media .act-meta { background: var(--blush); border: 0; }

@media (max-width: 980px) {
  /* One column below the breakpoint. The reading order in the markup is already
     the right order for a phone: audience, headline, ask, call, then the three
     cards — so no source reordering is needed. */
  .act-inner-primary,
  .act-inner-forward { grid-template-columns: 1fr; gap: 1.8rem; }
  .act-lead > *, .act-detail > *, .act-fwd-lead > * { max-width: 62ch; }
}
@media (max-width: 900px) {
  .sharekit-panel { grid-template-columns: 1fr; }
  .act-inner-media { grid-template-columns: 1fr; gap: 1.6rem; }
}
@media (max-width: 700px) {
  .sharekit-preview { grid-template-columns: 1fr; justify-items: center; }
  .sharekit-square { width: min(100%, 360px); }
  .sharekit-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .act-cta .btn { width: 100%; justify-content: center; }
}

/* -------------------------------------------------------------- footer -- */
.site-footer { background: var(--navy-deep); color: rgba(255, 255, 255, 0.82); padding: 3rem 0 2.5rem; }
.footer-inner { display: grid; gap: 1.6rem; }
.footer-brand { display: flex; align-items: center; gap: 1.1rem; color: #fff; flex-wrap: wrap; }
.footer-brand .cobrand-divider { background: rgba(255, 255, 255, 0.3); height: 28px; }
.footer-brand .cobrand-link img { display: block; width: auto; }
.footer-brand .cobrand-calla { --lockup-h: 34px; }
.footer-brand .cobrand-abig img { height: 20px; }
/* On the navy footer the hairline is redundant and would read as a halo
   around the white petal, so it is dropped: pure white, no stroke. */
.footer-brand .brand-mark-petal { stroke: none; }
.footer-links { display: flex; flex-wrap: wrap; gap: 1.6rem; }
.footer-links a { color: #fff; font-weight: 500; text-decoration: none; border-bottom: 1px solid rgba(255,255,255,0.35); padding-bottom: 2px; }
.footer-links a:hover { color: var(--on-navy-accent); border-color: var(--on-navy-accent); }
/* The campaign playbook's verbatim credit line. Quieter than the links above
   it but comfortably legible: rgba(255,255,255,0.72) on #151D38 is 9.5:1. */
.footer-credit {
  font-size: 0.86rem; line-height: 1.65; max-width: 78ch;
  color: rgba(255, 255, 255, 0.72);
}
.footer-copy { font-size: var(--step-1); color: rgba(255, 255, 255, 0.6); }

/* --------------------------------------------------------------- toast -- */
.toast {
  position: fixed; left: 50%; bottom: 2rem; transform: translate(-50%, 1rem);
  background: var(--navy); color: #fff; padding: 0.85rem 1.4rem;
  border-radius: 999px; font-weight: 600; font-size: 0.94rem; z-index: 60;
  box-shadow: 0 20px 40px -20px rgba(0, 0, 0, 0.6);
  opacity: 0; transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
}
.toast[data-show='true'] { opacity: 1; transform: translate(-50%, 0); }

/* ---------------------------------------------------------- responsive -- */
@media (max-width: 1080px) {
  /* Two up. The fifth card would sit alone and leave a hole beside it, so it
     takes the full width of its row. */
  .stats { grid-template-columns: repeat(2, 1fr); }
  .stat, .stat:nth-child(4), .stat:nth-child(5) { grid-column: auto; }
  .stat:last-child { grid-column: 1 / -1; }
}
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; }
  /* Single column: right-aligning the cover left a large empty gutter at the
     768px breakpoint. Centre it under the headline instead. */
  .hero-cover { max-width: 420px; justify-self: center; }
  .authors { grid-template-columns: 1fr; }
  .contributors { grid-template-columns: 1fr; }
  /* ROUND 36 — was `.header-nav .nav-link { display: none }`, which removed
     the only in-page navigation on phones. The links now collapse into a
     dropdown behind the Sections button. */
  .nav-toggle { display: inline-flex; }
  /* At 390px the header cannot hold both logos, a labelled button and the
     download CTA: the cobrand block gets squeezed and the ABIG mark overflows
     on top of the nav. The icon carries the button on small screens and the
     word stays in the accessibility tree. */
  .nav-toggle span {
    position: absolute; width: 1px; height: 1px; margin: -1px;
    padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
    border: 0;
  }
  .nav-toggle { padding: 0.46rem 0.5rem; }
  .header-nav { gap: 0.8rem; }
  .cobrand { flex: none; }
  .nav-links {
    position: absolute; top: calc(100% + 0.55rem); right: 0; z-index: 60;
    display: none; flex-direction: column; align-items: stretch; gap: 0;
    min-width: 12.5rem; padding: 0.35rem;
    background: var(--paper); border: 1px solid var(--rule);
    border-radius: 12px; box-shadow: 0 14px 34px rgba(0, 32, 91, 0.14);
  }
  .nav-links.is-open { display: flex; }
  .nav-links .nav-link {
    padding: 0.6rem 0.7rem; border-radius: 8px; font-size: 0.9rem;
  }
  .nav-links .nav-link:hover { background: var(--paper-tint); }
}
@media (max-width: 780px) {
  .cobrand-calla { --lockup-h: 28px; }
  .cobrand-abig img { height: 17px; }
  .cobrand-divider { height: 25px; }
}
@media (max-width: 640px) {
  .shell { width: min(100% - 2rem, var(--shell)); }
  .stats { grid-template-columns: 1fr; }
  .stat, .stat:nth-child(4), .stat:nth-child(5), .stat:last-child { grid-column: auto; }
  /* Buttons stack full-width here; the group must stretch with them so the
     note stays centred on the STACK. */
  .hero-cta, .hero-actions { width: 100%; }
  .hero-actions .btn, .movement-cta .btn { flex: 1 1 100%; justify-content: center; }
  .author { grid-template-columns: 1fr; gap: 0; }
  .author-avatar { grid-row: auto; margin-bottom: 1rem; }
  .author > .author-bio, .author > .author-links { grid-column: 1; }
  .goal-scale { gap: 0.6rem; }
}
@media (max-width: 520px) {
  :root { --header-h: 53px; }
  /* The lockup must never wrap at phone width. */
  .header-inner { gap: 0.6rem; padding: 0.55rem 0; flex-wrap: nowrap; }
  .cobrand { gap: 0.55rem; flex-wrap: nowrap; }
  .cobrand-calla { --lockup-h: 23px; }
  .cobrand-abig img { height: 14px; }
  .cobrand-divider { height: 21px; }
  .header-nav .btn-sm { padding: 0.5rem 0.85rem; font-size: 0.8rem; }
  .footer-brand { gap: 0.85rem; }
  /* Drive the whole lockup, not the wordmark img: setting a height on the img
     alone left the petal mark at its desktop size and broke the lockup's
     proportions (mark 39px against a 34px wordmark). */
  .footer-brand .cobrand-calla { --lockup-h: 29px; }
  .footer-brand .cobrand-abig img { height: 17px; }
  /* Round 6: one column of share buttons on the narrowest phones. */
  .share-buttons { grid-template-columns: 1fr; }
}
@media (max-width: 380px) {
  :root { --header-h: 51px; }
  /* Same fix as the footer, plus this rule never applied: `.cobrand-calla img`
     loses on specificity to `.cobrand-calla .cobrand-wordmark`, so the lockup
     stayed at 27px here while ABIG dropped to 12.5px — the widest gap on the
     page. Setting the custom property makes it take effect. */
  .cobrand-calla { --lockup-h: 21px; }
  .cobrand-abig img { height: 12.5px; }
  .cobrand-divider { height: 19px; }
  /* ROUND 36 — the Sections button added ~48px to this row, which pushed the
     download CTA past the shell edge on a 320px screen. Both logos are fixed
     brand assets and "Download" is fixed copy, so the space comes out of gaps
     and button padding rather than out of anything the reader reads. */
  .header-nav .btn-sm { padding: 0.42rem 0.44rem; font-size: 0.72rem; }
  .header-inner { gap: 0.35rem; }
  .header-nav { gap: 0.32rem; }
  .nav-toggle { padding: 0.38rem 0.34rem; }
  .cobrand { gap: 0.4rem; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ================================================== AUDIO BRIEFING PLAYER ==
   Custom-styled player over a real <audio> element. Everything visible is a
   real focusable control; the scrub bar is a keyboard-operable slider. The
   section sits directly after the reader so the flow is read -> listen. */
.listen-section { padding: clamp(3.5rem, 7vw, 6.5rem) 0; background: var(--paper); }

.player {
  margin-top: 2.6rem; background: #fff; border: 1px solid var(--hairline);
  border-radius: var(--radius-lg); padding: 1.6rem 1.7rem 1.3rem;
  /* Round 4: the heavy drop shadow is gone; the hairline does the work. */
  box-shadow: 0 18px 34px -34px rgba(0, 32, 91, 0.35);
  /* Full content width, matching the reader shell directly above it. */
  max-width: none;
}
.player-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1.2rem;
}
.player-kind {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-size: 0.74rem; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 600; color: var(--blue);
}
.player-listens { font-size: 0.83rem; color: var(--ink-mute); }
.player-listens strong { color: var(--navy); font-weight: 700; font-variant-numeric: tabular-nums; }

.player-controls { display: flex; align-items: center; gap: 0.9rem; }

.player-play {
  flex: none; width: 56px; height: 56px; border-radius: 50%;
  border: none; background: var(--navy); color: #fff;
  display: grid; place-items: center; cursor: pointer;
  transition: background 0.18s var(--ease), transform 0.18s var(--ease);
}
.player-play:hover { background: var(--blue); }
.player-play:active { transform: scale(0.96); }
.player-play .icon-play { margin-left: 3px; }   /* optical centring of the triangle */
.player-play .icon-pause { display: none; }
.player[data-playing='true'] .player-play .icon-play { display: none; }
.player[data-playing='true'] .player-play .icon-pause { display: block; }

.player-btn {
  flex: none; position: relative; min-width: 44px; min-height: 44px;
  display: grid; place-items: center; border-radius: 50%;
  border: 1.5px solid var(--rule); background: #fff; color: var(--navy);
  cursor: pointer; transition: border-color 0.18s var(--ease), color 0.18s var(--ease);
}
.player-btn:hover { border-color: var(--navy); color: var(--blue); }
.player-speed {
  border-radius: 999px; padding: 0 0.85rem; font-size: 0.86rem; font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.player-scrub { flex: 1; min-width: 0; }
.player-bar {
  position: relative; height: 8px; border-radius: 999px;
  background: var(--rule); cursor: pointer; touch-action: none;
}
.player-buffered {
  position: absolute; inset: 0 auto 0 0; width: 0;
  border-radius: 999px; background: rgba(47, 102, 168, 0.22);
}
.player-played {
  position: absolute; inset: 0 auto 0 0; width: 0;
  border-radius: 999px; background: var(--blue);
}
.player-knob {
  position: absolute; top: 50%; left: 0; width: 16px; height: 16px;
  margin: -8px 0 0 -8px; border-radius: 50%; background: #fff;
  border: 3px solid var(--blue); box-shadow: 0 2px 6px rgba(0, 32, 91, 0.35);
  pointer-events: none;
}
.player-bar:focus-visible { outline: 3px solid var(--blue); outline-offset: 5px; }
.player-time {
  display: flex; gap: 0.4rem; margin-top: 0.55rem;
  font-size: 0.78rem; color: var(--ink-mute); font-variant-numeric: tabular-nums;
}

.chapters { list-style: none; margin: 1.5rem 0 0; padding: 0; border-top: 1px solid var(--rule); }
.chapters li + li { border-top: 1px solid var(--rule); }
.chapter {
  width: 100%; display: flex; align-items: center; gap: 0.9rem;
  padding: 0.85rem 0.2rem; min-height: 48px;
  background: none; border: 0; cursor: pointer; text-align: left;
  font: inherit; color: var(--navy);
  transition: color 0.16s var(--ease);
}
.chapter:hover { color: var(--blue); }
.chapter-num {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; font-size: 0.72rem; font-weight: 700;
  background: var(--paper-tint); color: var(--ink-mute);
}
.chapter-name { flex: 1; font-size: 0.94rem; font-weight: 500; }
.chapter-time {
  font-size: 0.8rem; color: var(--ink-mute); font-variant-numeric: tabular-nums;
}
.chapter[aria-current='true'] { color: var(--blue); }
.chapter[aria-current='true'] .chapter-num { background: var(--blue); color: #fff; }
.chapter[aria-current='true'] .chapter-name { font-weight: 600; }

.player-foot { margin-top: 1.2rem; }
.player-foot a {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.83rem; color: var(--blue-ink, var(--navy)); font-weight: 500;
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: rgba(0, 32, 91, 0.3);
}
.player-foot a:hover { color: var(--blue); }

@media (max-width: 768px) {
  .player { padding: 1.2rem 1rem 1rem; margin-top: 2rem; }
  .player-controls { flex-wrap: wrap; row-gap: 1rem; }
  .player-scrub { order: 3; flex: 1 1 100%; }
  .player-play { width: 52px; height: 52px; }
  .player-speed { margin-left: auto; }
  .player-time { margin-top: 0.45rem; }
  .chapter { padding: 0.95rem 0.1rem; min-height: 52px; }
}

/* ==========================================================================
   ROUND 3 — privacy note, share-channel breakdown, audio transcript
   Additive only: no existing rule is changed, so the round-2 layout and
   visual design are untouched.
   ========================================================================== */

/* ------------------------------------------------------- privacy note --
   Quiet by design. It sits under the counters on the navy field, one step
   smaller than body copy and in a muted tint — informative, not a banner.
   We have no cookie consent modal because we set no cookies. */
.privacy-note {
  margin: 1.5rem 0 0;
  max-width: 78ch;
  font-size: var(--step-1);
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.62);
}
.privacy-note strong { color: rgba(255, 255, 255, 0.82); font-weight: 600; }
.privacy-note a {
  color: rgba(255, 255, 255, 0.82);
  text-decoration: underline;
  text-decoration-color: rgba(255, 255, 255, 0.4);
  white-space: nowrap;
}
.privacy-note a:hover { color: var(--on-navy-accent); text-decoration-color: var(--on-navy-accent); }

/* --------------------------------------------- campaign line (share) -- */
/* Round 14 — the real cause of "the spacing is slightly off where the top of
   the caption box lives".

   Round 13 measured and adjusted the padding INSIDE the caption card, which was
   the wrong gap. Re-measuring against the client's screenshot showed the gap
   ABOVE the card was 0px at every breakpoint, desktop included, against 24px
   below it — the hashtag line's box touched the card's top edge, and the small
   amount of visible space was only line-height leading, not spacing.

   This paragraph had a top margin and no bottom margin, so it butted straight
   into whatever followed. Matching the 24px below the card makes the card sit
   evenly between the heading group and the destinations. */
.campaign-line {
  margin-top: 0.9rem;
  margin-bottom: 1.5rem;
  font-size: var(--step-1u);
  font-weight: 600;
  color: var(--gold);
  letter-spacing: -0.01em;
}

/* ---------------------------------------------------------- transcript --
   Native <details> so it works with zero JavaScript and is fully indexable. */
.transcript {
  margin-top: 1.8rem;
  max-width: none;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--paper-tint);
}
.transcript-toggle {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; cursor: pointer; list-style: none;
  padding: 0.95rem 1.3rem; min-height: 44px;
  font-weight: 600; font-size: 0.92rem; color: var(--navy);
  border-radius: var(--radius);
}
.transcript-toggle::-webkit-details-marker { display: none; }
.transcript-toggle:hover { color: var(--blue); }
.transcript-chevron { flex: none; transition: transform 0.2s var(--ease); }
.transcript[open] .transcript-toggle { border-bottom: 1px solid var(--rule); border-radius: var(--radius) var(--radius) 0 0; }
.transcript[open] .transcript-chevron { transform: rotate(180deg); }
.transcript-body {
  padding: 1.2rem 1.4rem 1.5rem;
  display: grid; gap: 0.9rem;
  max-height: 30rem; overflow-y: auto;
  font-size: 0.92rem; line-height: 1.75; color: var(--ink);
}
/* The panel is now full content width, so hold the prose to a readable
   measure rather than letting lines run the full 1180px shell. */
.transcript-body > p, .transcript-body > blockquote { max-width: 74ch; }
.transcript-part {
  margin-top: 0.6rem;
  font-size: 0.8rem; letter-spacing: 0.13em; text-transform: uppercase;
  font-weight: 700; color: var(--blue);
}
.transcript-quote {
  margin: 0.2rem 0; padding: 0.2rem 0 0.2rem 1.1rem;
  border-left: 1px solid var(--hairline);
  color: var(--navy); font-weight: 500;
}
.transcript-quote p { margin: 0; }
@media (prefers-reduced-motion: reduce) {
  .transcript-chevron { transition: none; }
}

/* ------------------------------------------------------- legal / privacy --
   Single-column reading page. Same type ramp and palette as the landing page
   so it reads as part of the campaign, not a bolted-on legal doc. */
.legal-section { padding: clamp(2.6rem, 6vw, 4.5rem) 0 clamp(3.5rem, 7vw, 6rem); background: var(--paper); }
.legal-shell { max-width: 74ch; }
.legal-title { margin-top: 0.6rem; font-size: var(--step-3); color: var(--navy); }
.legal-lede {
  margin-top: 1.2rem; font-size: var(--step-1u); line-height: 1.65;
  color: var(--ink-mute); max-width: 62ch;
}
.legal-meta {
  margin-top: 1.1rem; font-size: var(--step-1); letter-spacing: 0.09em;
  text-transform: uppercase; font-weight: 600; color: var(--blue);
}
.legal-body { margin-top: 2.6rem; border-top: 1px solid var(--rule); padding-top: 2.2rem; }
.legal-body h2 {
  margin-top: 2.6rem; font-size: var(--step-2); color: var(--navy); letter-spacing: -0.02em;
}
.legal-body h2:first-child { margin-top: 0; }
.legal-body h3 {
  margin-top: 1.9rem; font-size: var(--step-1u); font-weight: 600; color: var(--blue);
}
.legal-body p { margin-top: 1rem; line-height: 1.75; }
.legal-body ul { margin: 1rem 0 0; padding-left: 1.2rem; display: grid; gap: 0.6rem; line-height: 1.7; }
.legal-body li::marker { color: var(--blue-mid); }
.legal-body strong { font-weight: 600; color: var(--navy); }
.legal-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.88em; background: var(--paper-tint);
  border: 1px solid var(--rule); border-radius: 5px; padding: 0.1em 0.38em;
}
.legal-back { margin-top: 3rem; font-weight: 600; }

/* =====================================================================
   ROUND 22 — DISTRIBUTION LAYER
   Copyable statistics, milestones, the campaign line, citation tools,
   the educator email, press, and institutional support.

   No new colour enters the page here. Every rule below draws from tokens
   already in :root, because a distribution layer should read as part of
   the paper's world, not as a marketing skin bolted to the bottom of it.
   ===================================================================== */

/* ---- Campaign line, under the movement counters ------------------- */
/* Round 23 — now a headline at the top of the left column rather than a loose
   line above the grid. `align-items: start` on .movement-body means the column
   and the goal card share a top edge, so the two sides finally balance. */
.movement-copy-col { min-width: 0; }
.movement-tag {
  margin: 0 0 0.85rem; max-width: 20ch;
  font-size: var(--step-2); font-weight: 700; line-height: 1.15;
  letter-spacing: -0.02em; color: #fff; text-wrap: balance;
}
/* The hashtag drops to its own line so the headline reads as a statement
   followed by its name, not one long run-on. */
.movement-tag b {
  display: block; margin-top: 0.35rem;
  /* ROUND 24 — was gold. The hashtag has to stay distinct from the white
     headline above it without reaching for yellow on navy, so it takes the
     brand light blue at 7.2:1. */
  color: var(--on-navy-accent); font-weight: 700; letter-spacing: -0.01em;
}

/* ---- Milestones on the goal bar ------------------------------------
   Four markers along the same axis as the fill. The row is a grid rather
   than a flex row so the labels sit at fixed fractions of the track and
   do not shuffle as the numbers change width. */
.milestones {
  list-style: none; margin: 1.1rem 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.4rem;
}
.milestone {
  display: flex; align-items: center; gap: 0.4rem;
  font-size: 0.78rem; font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.55);
  transition: color 0.4s var(--ease);
}
.milestone-dot {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: rgba(255, 255, 255, 0.22);
  transition: background 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.milestone.is-hit { color: var(--on-navy-accent); font-weight: 600; }
.milestone.is-hit .milestone-dot { background: var(--on-navy-accent); }
/* The next target is the only one worth drawing the eye to. A ring rather
   than a fill, so it reads as "not yet" instead of "done". */
.milestone.is-next { color: rgba(255, 255, 255, 0.92); font-weight: 600; }
.milestone.is-next .milestone-dot {
  background: transparent; box-shadow: inset 0 0 0 2px var(--on-navy-accent);
}
.milestone-next {
  margin-top: 0.7rem; font-size: var(--step-1);
  color: rgba(255, 255, 255, 0.82); font-variant-numeric: tabular-nums;
  min-height: 1.2em; /* reserved so the card never reflows on first paint */
}
@media (max-width: 460px) {
  .milestones { grid-template-columns: repeat(2, 1fr); gap: 0.5rem 0.8rem; }
}

/* ---- Copyable statistics ------------------------------------------
   The actions sit at the foot of each card, separated by a hairline so
   they read as a tool attached to the finding rather than more of the
   finding. Muted until hover — the number is the point, not the button. */
.stat-actions {
  margin: 0.35rem 0 0; padding-top: 0.85rem;
  border-top: 1px solid var(--rule);
  display: flex; flex-wrap: wrap; gap: 0.3rem 1rem; align-items: center;
}
.stat-act {
  display: inline-flex; align-items: center; gap: 0.4rem;
  background: none; border: 0; padding: 0.25rem 0; margin: 0;
  font: inherit; font-size: 0.8rem; font-weight: 600; line-height: 1.3;
  color: var(--ink-mute); text-decoration: none; cursor: pointer;
  border-radius: 4px;
  transition: color 0.2s var(--ease);
}
.stat-act svg { flex: none; opacity: 0.85; }
.stat-act:hover { color: var(--blue); text-decoration: underline; text-underline-offset: 3px; }
.stat-act:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }

/* ---- Cite this paper ----------------------------------------------- */
.cite {
  margin-top: 2.2rem; padding: 1.5rem 1.6rem;
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.cite-head {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 0.75rem 1.2rem;
}
.cite-title {
  margin: 0; font-size: var(--step-1u); font-weight: 700;
  letter-spacing: -0.01em; color: var(--navy);
}
.cite-tabs {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--paper-tint); border: 1px solid var(--rule);
  border-radius: 999px;
}
.cite-tab {
  border: 0; background: none; cursor: pointer; font: inherit;
  padding: 0.34rem 0.85rem; border-radius: 999px;
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.06em;
  color: var(--ink-mute);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.cite-tab:hover { color: var(--navy); }
.cite-tab.is-on { background: var(--navy); color: #fff; }
.cite-tab:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.cite-text {
  margin: 1.1rem 0 1.2rem; padding: 0.95rem 1.05rem;
  background: var(--paper-tint); border-radius: var(--radius-sm);
  font-size: 0.88rem; line-height: 1.65; color: var(--ink-mute);
  /* A citation is copied and pasted whole, so it must be selectable as one
     run of text and must not be re-wrapped into something uncopyable. */
  overflow-wrap: anywhere;
}

/* ---- Send it to a medical educator ---------------------------------
   Sits inside the green share band, so the card is white to lift off it
   and reuses the band's own border token. */
.educator {
  margin-top: clamp(2.4rem, 5vw, 3.5rem);
  padding: clamp(1.6rem, 3.5vw, 2.4rem);
  background: var(--paper); border: 1px solid var(--cl-green-200);
  border-radius: var(--radius);
}
.educator-title {
  margin: 0; font-size: var(--step-2); font-weight: 700;
  letter-spacing: -0.02em; color: var(--navy); line-height: 1.2;
}
.educator-lede {
  margin: 0.6rem 0 0; max-width: 58ch;
  font-size: var(--step-1u); line-height: 1.6; color: var(--ink-mute);
}
.educator-mail {
  margin: 1.4rem 0; padding: 1.1rem 1.2rem;
  background: var(--paper-tint); border-radius: var(--radius-sm);
  border-left: 3px solid var(--cl-green-250);
}
.educator-subject {
  margin: 0 0 0.85rem; padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--rule);
  font-size: 0.9rem; color: var(--navy); font-weight: 600;
}
/* --hairline (#6E7899) measures 3.94:1 on the tint behind this label, which
   fails AA. --ink-mute is 7.2:1 on the same surface and reads as the same
   quiet grey at this size. */
.educator-field {
  display: inline-block; margin-right: 0.5rem;
  font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-mute);
}
/* white-space: pre-wrap keeps the paragraph breaks the template was written
   with, so what is on screen is exactly what lands on the clipboard. */
.educator-body {
  margin: 0; white-space: pre-wrap;
  font-size: 0.9rem; line-height: 1.68; color: var(--ink-mute);
}

/* ---- Press and media ------------------------------------------------ */
.press {
  padding: clamp(3.5rem, 7vw, 6rem) 0;
  background: var(--paper); border-top: 1px solid var(--rule);
}
.press-shell {
  display: grid; grid-template-columns: 0.9fr 1.1fr;
  gap: clamp(2rem, 5vw, 4rem); align-items: start;
}
@media (max-width: 900px) { .press-shell { grid-template-columns: 1fr; } }
.press-title { margin-top: 0.5rem; }
.press-lede {
  margin: 1rem 0 0; max-width: 46ch;
  font-size: var(--step-1u); line-height: 1.62; color: var(--ink-mute);
}
.press-contact { margin: 1.6rem 0 0; }
.press-list {
  list-style: none; margin: 0; padding: 0;
  border-top: 1px solid var(--rule);
}
.press-list li {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: 0.3rem 1.5rem;
  padding: 0.95rem 0; border-bottom: 1px solid var(--rule);
}
.press-list a {
  font-weight: 600; font-size: 0.98rem; color: var(--navy);
  text-decoration: none;
  border-bottom: 1px solid var(--blue-soft);
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.press-list a:hover { color: var(--blue); border-color: var(--blue); }
/* Same reason as .educator-field: --hairline is 4.37:1 on white, just under
   the 4.5:1 floor. These are format labels a reader needs to read. */
.press-list span { font-size: 0.84rem; color: var(--ink-mute); }
.press-ask {
  font-size: 0.88rem; color: var(--ink-mute); border-bottom: 0 !important;
}

/* ---- Institutional support ------------------------------------------
   Navy, immediately above the navy footer, so the page closes on one
   uninterrupted dark field rather than a stripe. The ask is the last
   thing a reader sees before the small print. */
.support {
  background: var(--navy);
  color: #fff;
  padding: clamp(3.5rem, 7vw, 6rem) 0;
}
/* Round 23 — asymmetric two-column. The 1.35fr/1fr split keeps the argument
   dominant while giving the ask a real container, and the copy column keeps its
   own measure so the reading line never stretches past comfort even though the
   band is now full width. */
.support-shell {
  max-width: var(--shell);
  display: grid; grid-template-columns: 1.35fr 1fr;
  gap: clamp(2rem, 5vw, 4.5rem); align-items: start;
}
.support-copy { max-width: 54ch; }
.support-title { color: #fff; margin-top: 0.5rem; }
/* The recognition line sits UNDER the button, closing the loop the ask opens:
   here is the commitment, here is how you make it, here is what follows. It is
   deliberately quieter than the ask above it — recognition is the consequence
   of the commitment, not the reason for it, and typographic weight here would
   invert that. */
.support-recognition {
  margin: 1.2rem 0 0; padding-top: 1.1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  font-size: 0.88rem; line-height: 1.6; color: rgba(255, 255, 255, 0.72);
}
.support-ask {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius); padding: clamp(1.5rem, 2.6vw, 2rem);
}
.support-ask-head {
  margin: 0; font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 700; color: var(--on-navy-accent);
}
.support-ask-body {
  margin: 0.9rem 0 0; font-size: 1.02rem; line-height: 1.6;
  color: rgba(255, 255, 255, 0.94); font-weight: 500;
}
/* Both full-width children of the grid. */
.endorsers, .support-strip { grid-column: 1 / -1; }
@media (max-width: 860px) {
  .support-shell { grid-template-columns: 1fr; }
}
.support-lede {
  margin: 1.1rem 0 0;
  font-size: var(--step-1u); line-height: 1.62;
  color: rgba(255, 255, 255, 0.86);
}
.support-cta { margin: 1.5rem 0 0; }
.support :focus-visible { outline-color: #ffffff; }

.endorsers { margin-top: 2.6rem; padding-top: 2rem; border-top: 1px solid rgba(255, 255, 255, 0.16); }
.endorsers-head {
  font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 700; color: rgba(255, 255, 255, 0.62);
}
.endorser-list {
  list-style: none; margin: 1.4rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: 1.6rem 2.4rem;
}
/* Logos arrive in every colour and weight there is. Capping the height and
   letting the width follow keeps a wide wordmark and a square crest looking
   like they belong on the same shelf. */
.endorser img {
  max-height: 46px; width: auto; max-width: 170px;
  object-fit: contain;
}
.endorser-name {
  font-size: 0.95rem; font-weight: 600; color: rgba(255, 255, 255, 0.92);
}

.support-strip {
  margin: 2.8rem 0 0; padding-top: 1.6rem;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; align-items: center;
  font-size: 0.9rem;
}
.support-strip a {
  color: var(--on-navy-accent); text-decoration: none; font-weight: 600;
  border-bottom: 1px solid rgba(243, 197, 68, 0.4);
}
.support-strip a:hover { border-color: var(--on-navy-accent); }
.support-strip span { color: rgba(255, 255, 255, 0.4); }

/* Round 23 — provenance under each finding. Deliberately quiet: --ink-mute at
   small size, so it reads as an apparatus rather than competing with the number
   above it. It still clears AA at 7.58:1 on white and 6.83:1 on the tint, which
   --hairline does not, which is why that token is not used here. */
.stat-source {
  margin: 0.55rem 0 0; font-size: 0.78rem; line-height: 1.45;
  color: var(--ink-mute); letter-spacing: 0.005em;
}
.stat-source a { color: var(--blue); text-decoration-thickness: 1px; text-underline-offset: 2px; }
.stat-source a:hover { color: var(--navy); }

/* Press materials, folded into Take Action band 3 in round 23. */
.act-press { margin-top: 1.5rem; padding-top: 1.25rem; border-top: 1px solid var(--rule); }
.act-press-head {
  margin: 0 0 0.7rem; font-size: 0.8rem; font-weight: 700; color: var(--navy);
  text-transform: uppercase; letter-spacing: 0.07em;
}
.act-press-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.45rem; }
.act-press-list li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem;
  font-size: 0.92rem;
}
.act-press-list a { color: var(--blue); font-weight: 600; }
.act-press-list a:hover { color: var(--navy); }
.act-press-list span { font-size: 0.78rem; color: var(--ink-mute); }
.act-press-note { margin: 0.9rem 0 0; font-size: 0.8rem; color: var(--ink-mute); }

/* Round 23 — the optional-help block in Take Action band 1.

   Set apart from the ask above it with a rule and a small heading, because the
   two are different kinds of statement: the ask is what we want, this is what
   we can do for you if you want it. Running them together as one column of
   paragraphs was what made the call read as a required next step. No panel or
   tint — a box would give the offer the same visual weight as the ask, and it
   should sit clearly below it. */
.act-help {
  margin-top: 1.6rem; padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
}
.act-help-head {
  margin: 0; font-size: 1.02rem; font-weight: 700; color: var(--navy);
  letter-spacing: -0.005em;
}
.act-help-body {
  margin: 0.5rem 0 0; max-width: 56ch;
  font-size: 0.98rem; line-height: 1.65; color: var(--ink-mute);
}
.act-help .act-cta { margin-top: 1.25rem; }

/* Round 25 — the EMAS reference inside a Take Action card. Underlined rather
   than colour-only so it reads as a link against the card's body copy without
   pulling focus from the ask above it. */
.act-card p a {
  color: var(--blue);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.act-card p a:hover { color: var(--navy); }
