/* =====================================================================
   LANDING — shared base sheet (RURAL-WP-01, R410 ruling 2 option (a)).
   THE PRELUDE AND MOCKUP STYLE BLOCK 3, FACTORED OUT OF landing-cgt.css
   VERBATIM — nothing here was edited in the move. This file is enqueued
   BEFORE each landing template's own sheet (pages/landing-cgt.css,
   pages/landing-rural.css), which preserves the consolidated file's
   source order exactly: prelude -> block 3 -> the template's blocks.
   CGT's render is byte-identical across the split (Gate 2 render diff).

   The original CGT-WP-01 header, which documents this content, follows
   unchanged — "this file"/"here" in it predates the split and means the
   consolidated sheet this one was cut from.
   ===================================================================== */
/* =====================================================================
   LANDING — CGT page sheet (CGT-WP-01). THE MOCKUP'S STYLE BLOCKS 3-7,
   CONSOLIDATED IN THEIR ORIGINAL ORDER — the order IS the cascade (blocks
   5-7 override earlier rules at equal specificity by source order) and it
   must survive every future edit: append, never reorder.
   Source of truth: cgt-landing-mockup-v5-28.html (sha256 e1d84c0f…).
   Blocks 1-2 are deliberately NOT here: 1 is the mockup's stand-in token
   copy (its own header bars copying it), 2 is chrome CSS the theme ships.

   THE ONLY EDITS vs the mockup, per the dispatch:
     1. --lattice: data URI -> the real asset (the mockup's own install note).
     2. The :root colour/role definitions removed — tokens.css owns them.
     3. This prelude: the two NON-COLOUR layout tokens the mockup's stand-in
        block carried (--head-h = the header bar height header.css sets;
        --tex-tile = 18px, the mockup's "one unverified number", now VERIFIED
        against quote-block.css:251's live mask-size), and the scoped
        --on-slate override below.

   ⚠ SCOPED --on-slate OVERRIDE, A MEASURED DECISION FLAGGED AT GATE 2.
   tokens.css pairs --ground-slate with --on-slate:var(--cream); the mockup
   ships --on-slate:var(--white). Cream on slate is 4.3009 — legal for the
   LARGE quote type, FAILING 4.5 for the 10.5px figcaption. White is 4.88,
   passing both; the mockup chose it for exactly that reason. Reusing the
   theme pair at its theme value would ship an AA failure the approved
   design avoids, so this page re-points the SAME NAME (no second name,
   R348; no new value — --white is Layer 1) within its own band only. If
   the palette ever rules slate bands site-wide, re-measure the figcaption.
   ===================================================================== */
:root{
  --head-h:80px;
  --tex-tile:18px;
  --lattice:url(../../img/longitude-texture.svg);
}
.band-slate{--on-slate:var(--white)}


/* ================== MOCKUP STYLE BLOCK 3 ================== */
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--ground-page);color:var(--on-page);
  font-family:var(--sans);font-size:16.5px;line-height:1.65}

section{padding:110px 34px}
.in{max-width:1180px;margin:0 auto}
.in--hero{max-width:1320px}
.in--tight{max-width:1040px}
.band-cream{background:var(--ground-alt);color:var(--on-alt)}
.band-plum{background:var(--ground-dark);color:var(--on-dark);
  position:relative;isolation:isolate}
.band-accent{background:var(--ground-accent);color:var(--on-accent);
  position:relative;isolation:isolate}

/* ---- dark-band lattice, matching the pattern the live dark sections carry.
   APPROXIMATION: measured off a screenshot at ~17.5px pitch, r6.6, 1.5 stroke.
   THE REAL ASSET IS:
     assets/img/longitude-texture.svg
   This mockup is a standalone file and cannot load it, so shell 4 replaces
   the --lattice value below with
     url("<?php echo get_template_directory_uri(); ?>/assets/img/longitude-texture.svg")
   and drops the mask-size override if the real tile has its own pitch.
   That is the ONLY line that changes at install.
   Drawn as a MASK, not an image, so no colour literal enters the build: the
   white in the data URI is mask alpha, and the visible tint comes from
   --cream through color-mix, exactly like --rule-on-dark. */
/* --lattice now points at the real asset — defined in the prelude above. */
.band-plum::before,.band-accent::before{content:"";position:absolute;inset:0;z-index:-1;
  pointer-events:none;
  -webkit-mask-image:var(--lattice);mask-image:var(--lattice);
  -webkit-mask-size:var(--tex-tile) var(--tex-tile);mask-size:var(--tex-tile) var(--tex-tile);
  -webkit-mask-repeat:repeat;mask-repeat:repeat}
.band-plum::before{background:color-mix(in srgb, var(--cream) 5%, transparent)}
.band-accent::before{background:color-mix(in srgb, var(--white) 7%, transparent)}

h1,h2,h3{font-family:var(--serif);font-weight:600;margin:0;letter-spacing:-.012em}
.band-h2{font-size:clamp(24px,2.2vw,32px);line-height:1.18;max-width:26ch}
h3{font-size:19px;line-height:1.3}
p{margin:0 0 1.1em}
.lede{max-width:66ch;font-size:17.5px;line-height:1.62;color:var(--on-page-body)}
.band-plum .lede{color:var(--on-dark-body)}
.band-accent .lede,.band-accent .kick,.band-accent .sub-cta{color:var(--on-accent)}
.kick{font-family:var(--mono);font-size:11px;letter-spacing:.26em;
  text-transform:uppercase;color:var(--slate);margin:0 0 22px}
.band-plum .kick{color:var(--on-dark-body)}
/* on accent the button inverts the other way: white ground, accent text */
.band-accent .btn--invert{background:var(--on-accent);color:var(--ground-accent)}
.band-accent .btn--invert:hover{background:var(--white)}

/* .btn now comes from the real components/buttons.css above — removed */

/* ---- shared keyframes: defined once, never inside a component block ---- */
@keyframes drawX{to{background-size:100% 100%}}
@keyframes rise{to{opacity:1;transform:none}}

/* ============ S1 — EDITORIAL HERO (no competing object) ============ */
/* measured with the real chrome in place: at 92px the CGT mark cleared the
   fixed header by 12px at 1400 and sat BEHIND it by 15px at 760. The hero's
   top padding now pays the header's 80px before its own breathing room. */
/* RICK'S LAYOUT. Three changes from v5-16, each with a consequence:
   1. The mark is the CGT globe ALONE, at 88px rather than a 46px lockup. The
      wordmark leaving the page body is a fix, not a loss: the fixed header
      already carries LONGITUDE°, so the lockup was printing it twice within
      ~130px of vertical space. This closes the open "double logo" decision.
   2. Headline and lede sit SIDE BY SIDE from the top. The hairline rule is
      gone — with two columns the gutter does the dividing the rule used to.
   3. The pull-quote and the ruled clarity block leave the hero. Neither is
      lost: "Built by health systems, for health systems." is already the H2
      of S4a, and the clarity sentence is promoted to S1b below. */
.hero{padding-top:calc(var(--head-h) + 54px);padding-bottom:100px}
.u-mark{display:block;height:88px;width:auto;margin:0 0 42px}
.hero-top{display:grid;grid-template-columns:1.62fr 1fr;gap:5.5vw;align-items:start}
.hero h1{
  /* 16ch, measured not guessed: at 14ch the headline broke to five lines and
     split "and gene therapy" across two. 15-17ch all hold the four-line break
     Rick drew, so 16 sits in the middle of that stable band. */
  font-size:clamp(40px,5.7vw,80px);line-height:1.03;max-width:16ch;
  letter-spacing:-.022em;margin:0
}
.hero h1 em{font-style:normal;color:var(--accent)}
/* the lede column is narrow by design — at 42ch it sets a 7-9 line block that
   finishes near the headline's last line, so the CTA lands on the same optical
   baseline as "programs." rather than floating above or below it. */
.hero-sub{font-size:17px;line-height:1.62;color:var(--on-page-body);margin:0 0 30px;max-width:42ch}

/* ============ S1b — THE STATEMENT ============ */
/* Gold carrying type, which it does nowhere else on this page. The reason is
   measured, not stylistic: --gold #F0B83F on --plum #292631 is 8.22, while the
   same token on cream is 1.59. Plum is the only ground in the palette where
   gold can hold a sentence. */
.statement{padding-top:100px;padding-bottom:100px}
.statement .in{max-width:1100px}
.statement-line{
  font-family:var(--serif);text-align:center;margin:0;
  font-size:clamp(25px,3.4vw,45px);line-height:1.24;letter-spacing:-.012em;
  color:var(--on-dark);text-wrap:balance
}
.statement-line em{font-style:normal;color:var(--gold)}

/* ============ S2 — FIVE CAPABILITIES ============ */
/* Centred heading and lede. The ledger below is the section's whole argument
   now, so it gets real air above it rather than sitting under a diagram. */
/* measured against Rick's comp: his heading sits on ONE line at desktop and
   runs ~1042px wide inside the 1180 spine. 24ch was forcing a two-line break
   that isn't in the drawing, so the measure comes off and the container does
   the bounding. It breaks to two lines on its own below ~1270px. */
.caps .band-h2{font-size:clamp(28px,3.9vw,54px);line-height:1.1;
  max-width:none;margin:0 auto;text-align:center;letter-spacing:-.015em;
  text-wrap:balance}
.caps .band-h2 em{font-style:normal;color:var(--accent)}
.caps-lede{max-width:86ch;margin:36px auto 0;text-align:center;
  font-size:17.5px;line-height:1.62;color:var(--on-page-body)}

.caplist{list-style:none;margin:92px 0 0;padding:0;
  display:grid;grid-template-columns:repeat(5,1fr);
  border-top:1px solid var(--rule-hair)}
.caprow{position:relative;display:block;width:100%;text-align:left;
  border-right:1px solid var(--rule-hair);padding:26px 28px 28px 28px;margin:0}
/* only the first column sits flush on the spine, so the ledger's left edge
   lines up with the rule above it and with every other section's spine. */
.caplist li:first-child .caprow{padding-left:0}
.caplist li:last-child .caprow{border-right:0}
.caprow .n{display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.18em;
  color:var(--accent);margin-bottom:9px}
.caprow h3{font-family:var(--serif);font-size:17px;line-height:1.28;margin:0 0 7px;font-weight:600}
.caprow p{margin:0;color:var(--on-page-body);font-size:14.5px;line-height:1.55}

/* ============ S3 — pillars, meridian-derived marks ============ */
.pillars{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;margin-top:50px}
.pillar{border:1px solid var(--rule-hair);border-radius:8px;
  padding:30px 28px 32px;background:var(--ground-page)}
.pillar svg{display:block;margin:0 0 22px}
.pillar h3{font-family:var(--serif);margin-bottom:10px}
.pillar p{margin:0;color:var(--on-page-body);font-size:16px;max-width:60ch}

/* ============ S4 — outcome cards (plum) ============ */
/* Each card is self-contained and carries its own marker, so 4-up, 2x2 and
   1-col reflow for free. The old shared dotted line with absolutely-placed
   nodes could only ever work as a single row — it broke the moment it wrapped. */
.oline{margin-top:56px}
.outcomes{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.outcome{position:relative;background:var(--tint-on-dark);
  border:1px solid var(--rule-on-dark);border-radius:8px;
  padding:30px 24px 28px;overflow:hidden;
  opacity:0;transform:translateY(12px);
  transition:opacity .5s ease, transform .55s cubic-bezier(.2,.9,.25,1),
             border-color .25s ease, background .25s ease}
.outcome::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;
  background:var(--gold);transform:scaleX(0);transform-origin:left center;
  transition:transform .55s cubic-bezier(.4,0,.2,1)}
.oline.is-in .outcome{opacity:1;transform:none}
.oline.is-in .outcome::before{transform:scaleX(1)}
.oline.is-in .outcome:nth-child(1)::before{transition-delay:0s}
.oline.is-in .outcome:nth-child(2)::before{transition-delay:.14s}
.oline.is-in .outcome:nth-child(3)::before{transition-delay:.28s}
.oline.is-in .outcome:nth-child(4)::before{transition-delay:.42s}
.oline.is-in .outcome:nth-child(1){transition-delay:.18s}
.oline.is-in .outcome:nth-child(2){transition-delay:.32s}
.oline.is-in .outcome:nth-child(3){transition-delay:.46s}
.oline.is-in .outcome:nth-child(4){transition-delay:.60s}
.oline.is-in .outcome:hover{transform:translateY(-3px);
  border-color:color-mix(in srgb,var(--cream) 38%,transparent);
  background:color-mix(in srgb,var(--cream) 12%,transparent)}
.outcome h3{font-family:var(--serif);font-size:19px;margin:0 0 9px;color:var(--on-dark)}
.outcome p{margin:0;color:var(--on-dark-body);font-size:15.5px;line-height:1.55;max-width:60ch}

/* ============ Partner strip — the /our-team treatment ============ */
/* Three changes from the old strip, to match Governing Members on /our-team:
   a serif heading instead of a mono kicker, a NODE on the rule above each
   logo, and the logos in full colour instead of greyscale.
   The nodes are each column's own ::before rather than hand-placed points, so
   a node is dead-centre over its logo at every width and cannot drift on
   reflow — the failure the absolutely-placed nodes in the old outcome row hit.
   That requires the grid items to share a top edge, hence align-items:stretch
   on the row with the centring done inside each cell. */
.mstrip-h2{font-family:var(--serif);text-align:center;margin:0 0 58px;
  font-size:clamp(28px,3.4vw,44px);line-height:1.12;letter-spacing:-.012em;
  color:var(--on-alt)}
.mstrip{text-align:center}
.mstrip .row{position:relative;display:grid;grid-template-columns:repeat(5,1fr);
  align-items:stretch;gap:2vw;max-width:1040px;margin:0 auto;padding-top:46px}
.mstrip .row::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;
  background-image:repeating-linear-gradient(to right,var(--stone) 0 3px,transparent 3px 9px);
  background-repeat:no-repeat;background-size:0 100%}
.mstrip.is-in .row::before{animation:drawX 1.3s linear forwards}
.mem{position:relative;display:flex;align-items:center;justify-content:center;
  opacity:0;transform:translateY(8px)}
/* 9px node, pulled back onto the 1px rule 46px above the cell's top edge.
   46 measured off /our-team: the rule sits ~32px clear of the shortest logo,
   and the cells are as tall as the tallest mark, so the padding carries the
   difference. */
.mem::before{content:"";position:absolute;top:-46px;left:50%;
  width:9px;height:9px;margin:-4px 0 0 -4.5px;border-radius:50%;
  background:var(--ink)}
.mstrip.is-in .mem{animation:rise .52s ease forwards}
.mstrip.is-in .m-mic{animation-delay:.123s}
.mstrip.is-in .m-pro{animation-delay:.386s}
.mstrip.is-in .m-nov{animation-delay:.635s}
.mstrip.is-in .m-mem{animation-delay:.899s}
.mstrip.is-in .m-bay{animation-delay:1.177s}
/* full colour, as on /our-team — no grayscale filter, no opacity knockback */
.mem img{display:block;height:auto;max-width:100%;max-height:72px;width:auto}

/* measured: at 430px the five columns squeezed every logo to 53px wide, which
   is unreadable. Below 640 they wrap to two columns — and the nodes come OFF,
   because a node-per-column only reads as a row of stops while the logos are
   one row. Five dots scattered over two rows is noise, so the rule reverts to
   a plain divider. */
@media (max-width:640px){
  .mstrip-h2{margin-bottom:42px}
  .mstrip .row{grid-template-columns:repeat(2,1fr);gap:42px 26px;padding-top:44px}
  .mem::before{display:none}
  .mem img{max-height:58px}
  /* the fifth logo is an orphan on a 2-up grid, so it spans both columns —
     and its image is capped at half width, or spanning would print it at
     325px against the 169px its row-mates get. */
  .mstrip .row .mem:last-child{grid-column:1 / -1}
  .mstrip .row .mem:last-child img{max-width:50%}
}

/* ============ S5 — PROOF, in the established quote style ============
   Rebuilt to the component already running on longitudehealth.org: slate
   ground with the lattice, oversized gold quote mark, big circular portrait
   on the left, serif quote on the right, mono attribution beneath.
   MEASURED on --slate #5E7484:
     white 4.88  -> passes AA for normal text, not just large
     gold  2.70  -> which is why the gold is ONLY the decorative mark. It is
                    aria-hidden and carries no content, consistent with the
                    standing rule that gold is ornament and never carries
                    state or meaning on its own.
   The two quotes cycle. Timing is measured, not picked: the longer quote is
   40 words, ~12s at 200wpm, so the dwell is 14s — anything near the usual
   5-8s carousel interval would pull the slide before it can be read. It
   pauses on hover and on keyboard focus, stops for good on any interaction,
   and never runs under prefers-reduced-motion. */
.band-slate{background:var(--ground-slate);color:var(--on-slate);
  position:relative;isolation:isolate}
.band-slate::before{content:"";position:absolute;inset:0;z-index:-1;
  pointer-events:none;
  -webkit-mask-image:var(--lattice);mask-image:var(--lattice);
  -webkit-mask-size:var(--tex-tile) var(--tex-tile);mask-size:var(--tex-tile) var(--tex-tile);
  background:color-mix(in srgb, var(--ink) 16%, transparent)}

.qstage{position:relative}
/* MEASURED FIX. First pass locked the whole stage — nav included — to the
   tallest slide, which left 155px of dead slate BELOW the dots whenever the
   shorter quote was showing. The frame now holds only the stacked slides and
   is locked to the tallest of them; the nav sits under the frame in normal
   flow, so the dots never move and the slack falls above them.
   Slides are anchored to the frame's TOP (inset:0 0 auto 0), not stretched to
   it — stretching plus align-items:center would re-centre the shorter slide
   and make the portrait jump vertically on every change. */
.qframe{position:relative}
/* MEASURED FIX 2. align-items:center made the portrait sit 144px down on the
   short quote and 222px down on the long one — a 78px vertical jump every
   time the slide changed, with the portrait being the largest object on the
   band. Top-aligned instead, with the portrait pushed down by exactly the
   quote mark's own height (52 + 16 margin), so it starts level with the first
   line of the quote and lands in the same place on every slide. */
.qslide{margin:0;display:grid;grid-template-columns:320px 1fr;gap:5vw;
  align-items:start;
  position:absolute;inset:0 0 auto 0;opacity:0;visibility:hidden;
  transition:opacity .55s ease}
.qport{margin-top:68px}
.qslide.is-on{opacity:1;visibility:visible}

.qport{position:relative;width:320px;height:320px;justify-self:center}
/* the soft halo behind the circle, as on the live component */
.qport::before{content:"";position:absolute;inset:-14px;border-radius:50%;
  background:radial-gradient(circle,
    color-mix(in srgb, var(--white) 22%, transparent) 55%, transparent 72%)}
.qport img{position:relative;width:100%;height:100%;border-radius:50%;
  object-fit:cover;display:block}

.qmark{display:block;font-family:var(--serif);font-size:84px;line-height:1;
  height:52px;overflow:hidden;color:var(--gold);margin:0 0 16px}
.qslide blockquote{margin:0}
.qslide blockquote p{font-family:var(--serif);font-weight:600;
  font-size:clamp(21px,2.1vw,31px);line-height:1.32;margin:0;
  max-width:24ch;color:var(--on-slate)}
.qslide figcaption{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--on-slate);margin-top:30px;line-height:1.7}

/* controls — hairlines, not plates, to match the rest of the page */
.qnav{display:flex;gap:10px;margin-top:34px}
.qdot{width:11px;height:11px;padding:0;border-radius:50%;cursor:pointer;
  background:none;border:1px solid color-mix(in srgb, var(--white) 55%, transparent);
  transition:background .2s ease,border-color .2s ease}
.qdot[aria-current="true"]{background:var(--gold);border-color:var(--gold)}
.qdot:focus-visible{outline:3px solid var(--white);outline-offset:3px}

/* measured: at 430px the fixed 320px portrait column left 114px for the quote
   and pushed the document into horizontal overflow. Below 860 the slide
   stacks, the portrait drops to 200px and loses the 68px offset that only
   exists to align it with the first line of a quote sitting beside it. */
@media (max-width:860px){
  .qslide{grid-template-columns:1fr;gap:30px}
  .qport{width:200px;height:200px;margin-top:0;justify-self:start}
  .qslide blockquote p{max-width:30ch}
  .qmark{font-size:68px;height:44px;margin-bottom:12px}
  .qslide figcaption{margin-top:24px}
}

/* ============ S6 — CTA, now the homepage form block ============
   The accent band is GONE. This section was the page's one dark terminal
   beat; it is now the cream-ground heading-plus-form block the homepage uses
   for Join Us, carrying the CGT copy and an accent button.

   CONSEQUENCE WORTH NAMING: --ground-accent is no longer used anywhere on
   this page. The token pair stays in :root because the Rural page may still
   want it, but CGT no longer forces that tokens.css ruling by itself.

   MEASURED on --paper #FBF8F2:
     --accent  5.42  -> carries "demo." as display type, and the button fill
     --ink    13.99  -> labels and field borders
     --focus   3.93  -> the only true purple in the palette. It FAILS AA for
                        normal text, and it is the focus-ring token, so
                        borrowing it for display type would both dim the word
                        and overload a reserved role.
   Button: white on accent = 5.74. */
.cta{background:var(--ground-page);color:var(--on-page);
  padding-top:118px;padding-bottom:118px}
.cta-grid{display:grid;grid-template-columns:1fr 1.15fr;gap:6vw;align-items:start}
.cta-h2{font-family:var(--serif);font-weight:600;letter-spacing:-.02em;
  font-size:clamp(34px,4.6vw,60px);line-height:1.04;max-width:9ch;margin:0}
.cta-h2 em{font-style:normal;color:var(--accent)}
.cta-lede{margin-top:26px;max-width:42ch;font-size:17px;line-height:1.62;
  color:var(--on-page-body)}

/* ---- the form. A VISUAL STAND-IN, not a working form: no action, and the
   script hard-stops submit. Field names, order and labels mirror the live
   homepage form so the HubSpot embed drops in against a known shape. ---- */
.f-note{font-size:14px;color:var(--on-page-soft);margin:0 0 24px}
.f-row{display:grid;grid-template-columns:1fr 1fr;gap:22px}
.f-field{margin-bottom:22px}
.f-field > label{display:block;font-family:var(--mono);font-size:10.5px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--on-page);
  margin-bottom:9px}
.f-field input,.f-field select,.f-field textarea{
  display:block;width:100%;box-sizing:border-box;
  background:var(--white);color:var(--on-page);
  border:1px solid var(--ink);border-radius:6px;
  padding:13px 14px;font-family:var(--sans);font-size:16px;line-height:1.3}
.f-field textarea{min-height:124px;resize:vertical}
.f-field input:focus-visible,.f-field select:focus-visible,
.f-field textarea:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.f-send{margin-top:8px;border:0;cursor:pointer;font-family:var(--sans)}
.f-standin{margin:18px 0 0;font-family:var(--mono);font-size:10.5px;
  letter-spacing:.12em;text-transform:uppercase;color:var(--on-page-soft)}
.sub-cta{font-size:15px;color:var(--on-page-soft);margin:0}

@media (max-width:860px){
  .cta-grid{grid-template-columns:1fr;gap:46px}
  .cta-h2{max-width:14ch}
  .cta-lede{max-width:58ch}
}
@media (max-width:560px){
  .f-row{grid-template-columns:1fr;gap:0}
}

.rv{opacity:0;transform:translateY(14px);transition:opacity .6s ease,transform .6s ease}
.rv.is-in{opacity:1;transform:none}

@media (max-width:920px){
  section{padding:84px 34px}
  .hero-top{grid-template-columns:1fr;gap:38px}
  .hero h1{max-width:18ch}
  .hero-sub{max-width:62ch}
  .caplist{grid-template-columns:1fr 1fr;margin-top:64px}
  .caprow{border-right:1px solid var(--rule-hair);
    border-bottom:1px solid var(--rule-hair);padding:24px 22px 26px 22px}
  .caplist li:nth-child(odd) .caprow{padding-left:0}
  .caplist li:nth-child(even) .caprow{border-right:0}
  .caplist li:last-child .caprow{border-right:0}
  .cta{padding-top:96px;padding-bottom:96px}
}
/* measured: 4-up outcome paragraphs fall to 18.8ch at 921 — a 40px window
   that is worse than the 2-up it was about to become. Break at 960, where
   two columns pick up at 44ch. */
@media (max-width:960px){
  .outcomes{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:1000px){
  .quotes{gap:40px}
  
  blockquote p{font-size:18px}
  /* measured: 4-up outcomes fell to 20.6ch at 940 with 24px sides;
     reclaiming 6px a side holds them above 22ch until the 2-col break. */
  .outcome{padding:26px 18px 24px}
}
@media (max-width:900px){
  /* measured: with gap 16 and 18px side padding, three columns hold a
     one-line heading and a 24-25ch measure all the way to 740px.
     Stacking at 920 was ~160px premature. */
  .pillars{gap:16px}
  .pillar{padding:22px 18px 24px}
  .pillar h3{font-size:17.5px}
  .pillar p{font-size:15px}
  .pillar svg{width:48px;height:48px;margin-bottom:18px}
}
@media (max-width:760px){
  section{padding:64px 34px}
  .quotes{grid-template-columns:1fr;gap:46px}
  
  blockquote p{font-size:18.5px;max-width:52ch}
  .hero{padding-top:calc(var(--head-h) + 34px)}
  .u-mark{height:68px;margin-bottom:34px}
  .statement{padding-top:72px;padding-bottom:72px}
  .pillars{grid-template-columns:1fr;gap:20px}
  .pillar{padding:26px 24px 28px}
  .pillar h3{font-size:19px}
  .pillar p{font-size:16px}
  .caplist{grid-template-columns:1fr}
  .caprow,.caplist li:nth-child(odd) .caprow{border-right:0;padding:24px 0 26px 0}
  .outcomes{grid-template-columns:1fr;gap:14px}
  .outcome{padding:26px 22px 24px}
  .mstrip .row{flex-direction:column;gap:24px}
  .mstrip .line{display:none}
  /* one column at last: the full 692px spine carries the portrait beside the
     text again, with the measure capped so it does not run to 63ch. */
  .quotes{grid-template-columns:1fr;gap:40px}
  /* the unit is capped, not the paragraph inside it, so the text fills its
     own cell exactly and leaves no hole beside itself. */
  blockquote{grid-template-columns:78px 1fr;gap:20px;max-width:580px}
  
  blockquote p{font-size:18px;max-width:none}
  blockquote .qt{padding-top:4px}
  blockquote .qt::before{top:-20px;left:-5px;font-size:54px}
  .cta{padding-top:76px;padding-bottom:76px}
  .cta-rule{margin-bottom:32px}
}
@media (prefers-reduced-motion:reduce){
  .rv{opacity:1;transform:none;transition:none}
  .dw{stroke-dashoffset:0;animation:none !important}
  .nd,.nlab{opacity:1;transform:none;animation:none !important}
  .mstrip .line{background-size:100% 100%!important;animation:none!important}
  .outcome,.outcome::before{opacity:1!important;transform:none!important;transition:none!important}
  .mem{opacity:1;transform:none;animation:none!important}
  .cta-rule{transform:none!important;transition:none!important}
  .btn{transition:none}
}

/* ===== S5 attribution layout — appended to the PAGE SHEET so it wins,
   the manifest's load order being tokens -> base -> components -> page ===== */

/* ---- the portrait joins the ATTRIBUTION rather than leading the quote.
   The quote is what the section is for, so it reads first; the face and the
   credential arrive together as one block, which is what a reader checks after
   deciding the claim is interesting. 96px is nearly a third taller than the
   86px it replaces and now carries the name and title with it, so it reads as
   a credential rather than an avatar.
   The pair is bottom-aligned: the two quotes are different lengths, so without
   this the bylines float at unrelated heights. ---- */
.quotes{align-items:stretch}
blockquote{display:flex;flex-direction:column}
.portrait{margin-bottom:0;flex:0 0 auto}
.byline{display:flex;align-items:center;gap:20px;margin-top:auto;padding-top:32px}
.byline cite{margin-top:0}
blockquote p{margin-bottom:0}

.portrait{width:96px;height:96px}
.byline cite{font-size:10.5px;letter-spacing:.12em;line-height:1.75}
/* The portrait must not shrink below its 96px baseline on the way down —
   that was the original complaint. Between 1000 and 761 the two columns are
   genuinely tight, so it gives up 8px; at one column there is more room than
   at desktop, not less, so it goes back up. */
@media (max-width:1000px){.portrait{width:88px;height:88px}}
@media (max-width:760px){.portrait{width:104px;height:104px}.byline{gap:22px}}

