/* Measure — landing-page stylesheet, v2 design language, navy + white.
 *
 * WHAT THIS IS. site/v2.css is the reference frame: full-bleed bands with
 * generous padding, a centred sticky nav pill, huge tight-tracked
 * headings, rounded cards on hairline borders, uppercase letterspaced
 * eyebrows, and a fail-open scroll reveal. This sheet takes that
 * structural language and drops v2's four-hue accent palette entirely.
 *
 * TWO COLOURS. Navy and white, and nothing else. The navy is the LOGO
 * navy, not a guess and not v2's #0f1e33 terrain ink: logo-ink.png is a
 * single flat colour across all 21,081 of its opaque pixels, and that
 * colour is #16324e. Everything else in here is that navy at a lower
 * luminance step or white. No violet, no cyan, no lime, no coral —
 * v2's accents belong to v2.
 *
 * WHY A SEPARATE SHEET AND NOT AN EDIT TO lp.css. lp.css @imports
 * tokens.css, which carries `color-scheme: dark`, a --lime that is a
 * fill rather than a text colour, and a --cyan the whole sheet leans on.
 * Unpicking those in place would have left the old pages half-restyled
 * for however long the work took. This sheet imports nothing and
 * declares every value it uses.
 *
 * INHERITED BUGS FIXED HERE, not carried forward. lp.css was written for
 * a dark page and the site went light underneath it, so three rules were
 * still painting near-white text on white ground and were invisible on
 * all 26 pages:
 *     h3            { color: #dbe6ec }        (invisible)
 *     .faq summary  { color: #dbe6ec }        (invisible)
 *     .claim        { color: var(--lime) }    (#c9f542, invisible)
 * Nothing in this sheet sets a text colour lighter than 4.5:1 on the
 * ground it actually sits on.
 *
 * MOBILE FIRST is NOT the convention here, deliberately, because v2 is
 * not built that way and a sheet that borrows half of another sheet's
 * structure and inverts its breakpoint direction is a sheet nobody can
 * hold in their head. Base rules are the desktop composition; the media
 * queries narrow.
 */

:root {
  /* ---- the two colours ---- */
  --navy:  #16324e;        /* the logo ink, sampled from logo-ink.png */
  --white: #ffffff;

  /* ---- the navy, stepped down. Every one of these is measured
     against white, because white is the only ground they sit on:
       --navy    13.1:1   headings, body copy, the accent itself
       --navy-2   6.5:1   secondary prose, captions, sub-copy
       --navy-3   5.1:1   tertiary detail, micro-labels, breadcrumbs
     Nothing lighter than --navy-3 ever carries text. ---- */
  --navy-2: #4b6076;
  --navy-3: #5d7089;

  /* ---- grounds. White, and one very light navy-tinted wash. ---- */
  --wash:   #f4f7fb;
  --wash-2: #eaf0f7;       /* the wash, one step down, for band-on-band */
  --line:   #dde5ee;       /* the hairline */
  --line-2: #c3d0e0;       /* the hairline, when it has to be seen */

  /* v2's type stack verbatim, so a reader crossing from v2.html to a
     landing page does not watch the furniture change face. System faces
     only: no @font-face, no external URL. The last brand face shipped
     woff2 rules for files that did not exist and 404'd on every load,
     and the CSP blocks outside hosts anyway. */
  --geo: "Poppins", "Sofia Pro", "Century Gothic", "Avenir Next",
         "Segoe UI Variable Display", system-ui, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;

  /* tokens.css says `color-scheme: dark` — a leftover from when this was
     a black site. On a white page that hands the UA a dark scrollbar and
     dark form controls against white content. */
  color-scheme: light;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  /* THE PAGE GROUND IS THE WASH, NOT WHITE, and only so that the masthead
     reads as a band. The nav pill lives outside <main>, above .lphero, so
     painting the hero alone left a ~50px white shelf above a wash hero and
     the band started in the wrong place. Every band below the hero paints
     its own ground (.prose and .foot white, .ctaband navy, .relband wash),
     so this colour is only ever seen behind the nav and the hero. */
  background: var(--wash);
  color: var(--navy);
  font-family: var(--geo);
  font-size: 17.5px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
}

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

a { color: var(--navy); text-underline-offset: .18em; }
a:hover { color: #0d2137; }

/* VISIBLE FOCUS, ON EVERYTHING FOCUSABLE. */
:is(a, button, summary, input, [tabindex]):focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
  border-radius: 4px;
}
/* On the navy band a navy ring is a ring you cannot see. */
.ctaband :is(a, button, summary, input, [tabindex]):focus-visible {
  outline-color: var(--white);
}

/* ------------------------------------------------------------- skip */
.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--navy); color: var(--white);
  padding: .7rem 1rem; font-weight: 600; z-index: 99;
  text-decoration: none; border-radius: 0 0 10px 0;
}
.skip:focus { left: 0; }


/* =====================================================================
   THE NAV — a centred pill, not a full-width bar
   Straight from v2: fit-content, sticky at 14px, hairline, blurred
   white, pill radius.

   NOTHING IN THIS SHEET SETS `overflow: hidden` ON AN ANCESTOR OF THE
   NAV, and that is not an oversight. An ancestor with overflow:hidden
   becomes the containing block for position:sticky, and a container
   that does not itself scroll cannot hold anything stuck — so the pill
   silently degrades into a static element that scrolls away. v2 lost
   its nav to exactly that once. There is no wrapper around <header>
   here and no clip anywhere above it.
   ===================================================================== */
.nav {
  position: sticky; top: 14px; z-index: 20;
  width: fit-content; max-width: calc(100% - 32px);
  margin: 18px auto 0;
  display: flex; align-items: center; gap: 26px;
  padding: 8px 20px;
  background: rgba(255,255,255,.92);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border: 1px solid var(--line); border-radius: 999px;
  box-shadow: 0 1px 2px rgba(22,50,78,.05), 0 10px 24px rgba(22,50,78,.08);
}
.wordmark { display: inline-flex; align-items: center; text-decoration: none; }
.wordmark img { height: 19px; width: auto; display: block; }

.nav-links { display: flex; align-items: center; gap: 22px; }
.nav-links a {
  color: var(--navy); text-decoration: none;
  font-weight: 500; font-size: .875rem; letter-spacing: .004em;
  opacity: .82; white-space: nowrap;
  transition: opacity .16s;
}
.nav-links a:hover, .nav-links a:focus-visible { opacity: 1; color: var(--navy); }


/* =====================================================================
   BANDS — full bleed, no card wrapper, generous padding

   .wrap keeps its name because 27 pages and the footer use it, but it
   is no longer the page's ceiling: it is the measure inside a band that
   already reaches both edges of the viewport.

   THE CAP IS DERIVED FROM THE GUTTER, NOT GUESSED ALONGSIDE IT. The old
   sheet capped at a bare 44rem while the gutter changed at a breakpoint
   underneath it, and between about 679px and 720px of viewport the
   container gave out more width than the paragraphs would take: two
   right edges, every capped block sitting ~13px left of centre, in a
   40px-wide band nobody had resized into. Deriving the cap from the
   gutter makes the content box the same width at every viewport.
   ===================================================================== */
.wrap {
  --gut: 1.25rem;

  /* THREE WIDTHS, ONE LADDER, DECLARED ONCE. Every band and every
     component picks one of these three; nothing in this sheet invents a
     fourth.
         --shell    76rem  1216px   figure rows, tables, related grid, CTA
         --wide     60rem   960px   callouts, FAQ, diagrams, pull quotes
         --measure  44rem   704px   paragraphs, lists, headings
     --shell lands on 1216px because that is what the main page already
     uses (v2.css caps .grid and .wire at 1220px), and a landing page that
     is wider than the site it belongs to reads as a different site.
     --measure is 75 characters a line on the shipped stack - 9.39px
     average advance at 17.5px, measured in the browser rather than
     guessed. The old 46rem ran 78. The pages did not read narrow because
     the LINE was short; they read narrow because the line was the only
     thing on the page. */
  --shell:   76rem;
  --wide:    60rem;
  --measure: 44rem;

  max-width: calc(var(--shell) + 2 * var(--gut));
  margin: 0 auto;
  padding: 0 var(--gut);
}
@media (min-width: 46rem) { .wrap { --gut: 2rem; } }

/* =====================================================================
   THE PROSE BAND IS A BREAKOUT GRID, NOT A NARROW BOX

   The old sheet capped .prose > .wrap at 48rem, and then at the very
   bottom of the file tried to let figures and tables escape it with
   `max-width: min(78rem, 100%)`. That could never work: 100% of a 768px
   parent is 768px, so every breakout rule in that block resolved to
   exactly the width it was breaking out of, and the page stayed a
   ribbon. Measured before this change, on four pages at a 1440px
   viewport: .figs, .tbl-scroll, .faq, .limits and .box were all 768px.

   A container cannot both cap its text and let its children exceed it.
   So the cap moves off the container and onto a TRACK. Five columns -
   two gutters, two shoulders, one measure - and children sit in `text`
   by default and opt up to `wide` or `full`.

   THE MEASURE TRACK IS `min(--measure, 100% - 2*--gut)` AND NOT
   `minmax(0, --measure)`, which is the version I wrote first and which
   collapses on a phone. With an fr track in the same template, grid's
   maximize-tracks step hands free space out EQUALLY to every growable
   track before flexible tracks expand - so at 375px the 44rem track and
   the two shoulders took a third of the viewport each and the paragraph
   came out 112px wide. A min() track is definite, sizes itself first,
   and leaves the shoulders on zero where there is no room for them.
   ===================================================================== */
.prose > .wrap {
  padding: 0;
  display: grid;
  align-content: start;
  grid-template-columns:
    [bleed-start] minmax(var(--gut), 1fr)
    [full-start]  minmax(0, calc((var(--shell) - var(--wide))    / 2))
    [wide-start]  minmax(0, calc((var(--wide)  - var(--measure)) / 2))
    [text-start]  min(var(--measure), 100% - 2 * var(--gut)) [text-end]
                  minmax(0, calc((var(--wide)  - var(--measure)) / 2)) [wide-end]
                  minmax(0, calc((var(--shell) - var(--wide))    / 2)) [full-end]
    minmax(var(--gut), 1fr) [bleed-end];
}

/* THE GUTTER TRACKS SIT OUTSIDE `full`, not inside it, and that pair of
   extra shoulders is the whole reason there are seven tracks rather than
   five. With five, `full-start` was the outermost line, so a figure row
   ran the entire 1280px of the wrap while .cta and .rel-grid - which
   live in ordinary padded .wraps in the bands below - ran 1216px. The
   figure row overhung them by 32px a side: measured it, two left edges.
   Now `full` is the wrap width minus its gutters at every viewport,
   which is exactly what a padded .wrap gives its own children, so the
   bands line up whether or not the tracks have reached their caps. */

/* Grid items do not shrink below min-content unless told to, and one
   unbreakable citation URL inside .claim is enough to widen a track. */
.prose > .wrap > * { grid-column: text; min-width: 0; }

/* --- WHAT LEAVES THE MEASURE ----------------------------------------
   Running prose stays put. Things that are looked at rather than read
   take the shell; things that are a block of their own take the
   shoulders. This is the whole layout change: the page is wide because
   the furniture is wide, not because the sentences got longer. */
.prose > .wrap > :is(.figs, .tbl-scroll, .hublist) { grid-column: full; }
.prose > .wrap > :is(.limits, .box, .claim, .faq, .dia, figure, table) {
  grid-column: wide;
}

/* The library index (lp/index.html) is a directory, not an essay. It has
   no running prose to protect, so it opts out of the grid and runs the
   full shell in ordinary block flow. */
.prose.wide > .wrap {
  display: block;
  padding: 0 var(--gut);
  max-width: calc(var(--shell) + 2 * var(--gut));
}

/* THE BANDS, AND THE AIR BETWEEN THEM. The old paddings were sized for a
   768px column; at 1216px the same numbers read as no separation at all,
   because vertical rhythm has to scale with the width it is separating.
   .lphero paints no ground of its own and inherits the body wash - see
   the note on body{} - and closes on the hairline where the white page
   starts. */
.lphero  { padding: 86px 0 64px; text-align: left; border-bottom: 1px solid var(--line); }
.prose   { padding: 56px 0 40px; background: var(--white); }
.ctaband { padding: 112px 0 118px; background: var(--navy); color: var(--white); }
.relband { padding: 104px 0 112px; background: var(--wash); }
main     { display: block; }

/* The second prose band is the FAQ. It follows the navy CTA and closes
   the white page, so it carries tail padding the first one does not. */
.ctaband ~ .prose { padding: 84px 0 92px; }


/* =====================================================================
   TYPE — big, tight, 700, the way v2 sets it
   ===================================================================== */
.eyebrow {
  font-size: .72rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--navy-3);
  margin: 0 0 14px;
}

h1 {
  font-size: clamp(2.3rem, 4.6vw, 4.1rem);
  line-height: 1.02; font-weight: 700;
  letter-spacing: -.035em;
  margin: 0 0 18px; text-wrap: balance;
  color: var(--navy);
}

.lede {
  font-size: 1.14rem; line-height: 1.55; color: var(--navy-2);
  margin: 0 0 4px; max-width: 46rem;
}
.lede b, .lede strong { color: var(--navy); font-weight: 700; }

h2 {
  font-size: clamp(1.6rem, 3vw, 2.25rem);
  line-height: 1.08; font-weight: 700;
  letter-spacing: -.03em;
  margin: 4.2rem 0 1.15rem; text-wrap: balance;
  color: var(--navy);
}

/* A SECTION MARK, because a wide page has to announce its sections. On a
   768px column a heading and 3rem of space says "new section" on its
   own; across 1216px it does not. The obvious alternative - spanning the
   H2 out to the shoulders - gives the band two left edges, with every
   heading hanging 8rem left of its own first paragraph. A short rule
   above the heading marks the section without moving anything into a
   second column. Navy, at a weight the palette already carries. */
.prose > .wrap > h2 { position: relative; padding-top: 1.15rem; }
.prose > .wrap > h2::before {
  content: ""; position: absolute; left: 0; top: 0;
  width: 3rem; height: 3px; border-radius: 2px;
  background: var(--navy); opacity: .9;
}

h3 {
  /* WAS #dbe6ec — near-white, left over from the dark theme, so every
     H3 on all 26 pages rendered white on white and the page read as a
     paragraph break where a heading was meant to be. */
  font-size: 1.12rem; font-weight: 700; line-height: 1.3;
  letter-spacing: -.015em;
  margin: 2rem 0 .55rem; color: var(--navy);
}

p { margin: 0 0 1.05rem; }

/* Oliver's standing note: long paragraphs make people leave. The prose
   band's own cap is the guard rail; this is the belt on top of it for
   anything that escapes into a wide band. */
/* THE MEASURE IS NOT WHAT MAKES A PAGE LOOK SKINNY, and I nearly got
   this wrong. Oliver said the pages look thin, so my first move was to
   stretch the text column - 56rem, which at 17.5px is about 117
   characters a line. That is roughly twice a comfortable measure and
   would have fixed the look by wrecking the read.
   The real problem in the screenshot is a single narrow column with
   acres of white either side. The answer is not longer lines, it is
   more of the page doing something: the shell widens, and everything
   that is not running prose - diagrams, lists of measurements, the CTA,
   the related grid - breaks out to fill it.
   The cap itself now lives on the grid TRACK (see .prose > .wrap), so
   the blanket `.prose p, .prose li` rule is gone: being a descendant
   selector it was also capping paragraphs nested inside the callouts and
   the FAQ answers, which have widths of their own to keep. Only those
   nested cases are named here. */
.faq .a, .limits p, .box p { max-width: var(--measure); }

strong, b { color: var(--navy); font-weight: 700; }
em { color: var(--navy-2); }

hr { border: 0; border-top: 1px solid var(--line); margin: 2.8rem 0; }

/* ------------------------------------------------------------ lists */
ul, ol { margin: 0 0 1.2rem; padding-left: 1.2rem; }
li { margin-bottom: .5rem; }
li::marker { color: var(--navy-3); }

ul.dashed { list-style: none; padding-left: 0; }
ul.dashed li { position: relative; padding-left: 1.3rem; }
ul.dashed li::before {
  content: ""; position: absolute; left: 0; top: .72em;
  width: 13px; height: 2px; border-radius: 2px; background: var(--navy);
  opacity: .55;
}

/* ------------------------------------------------------ breadcrumbs */
.crumb {
  font-size: .78rem; color: var(--navy-3); margin: 0 0 1.5rem;
  letter-spacing: .01em;
}
.crumb a { color: var(--navy-3); text-decoration: none; }
.crumb a:hover { color: var(--navy); }
/* The separator is the ONE piece of text in this sheet that is not held
   to 4.5:1, because it is a "/" between two links rather than something
   anyone reads. It is still held to 3:1 — the hairline colour it started
   out as measured 1.56:1 on white, which is not a faint separator, it is
   an absent one, and this file exists partly because three rules like
   that shipped invisible across 26 pages. */
.crumb span { color: #5f7286; padding: 0 .4rem; }


/* =====================================================================
   CARDS — rounded, hairline, white
   ===================================================================== */
/* THE FIGURE ROW IS THE WIDEST THING ON MOST OF THESE PAGES. At the old
   768px it fitted three 246px cards; on the shell it fits four at 290px,
   which is what the pages carrying four figures were written for. */
/* THE TRACK MINIMUM IS min(Xrem, 100%), NOT Xrem, on all three of the
   auto-placed grids. A bare `minmax(19rem, 1fr)` track cannot shrink
   below 19rem, so at a 320px viewport - where the band gives its
   children 280px - the cards stood 304px wide and took the page 4px
   sideways. Inherited: .rel-grid and .hublist both did this before this
   change, on every one of the 27 pages. Measured at 320px: body
   scrollWidth 324 against a 320 viewport, gone after the min(). */
.figs {
  display: grid; gap: 18px; margin: 2.6rem 0 2.8rem;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  max-width: none;
}
.fig {
  border: 1px solid var(--line); border-radius: 18px;
  padding: 24px 24px 22px; background: var(--white);
  box-shadow: 0 1px 2px rgba(22,50,78,.04), 0 10px 26px rgba(22,50,78,.05);
  transition: transform .18s, box-shadow .18s;
}
.fig:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(22,50,78,.06), 0 18px 40px rgba(22,50,78,.09);
}
.fig b {
  display: block; font-size: 1.9rem; line-height: 1;
  color: var(--navy); font-weight: 700; letter-spacing: -.035em;
  font-variant-numeric: tabular-nums; margin-bottom: .5rem;
}
.fig span { display: block; font-size: .86rem; color: var(--navy-2); line-height: 1.5; }

/* --------------------------------------------------------- callouts */
/* Two callouts, one palette. They are told apart by structure rather
   than by hue: the note is a filled wash card, the limits box is white
   with a solid navy rule down its edge. */
.box {
  border: 1px solid var(--line); border-radius: 18px;
  padding: 26px 30px; margin: 2.8rem 0;
  background: var(--wash);
}
.box p:last-child { margin-bottom: 0; }
.box .k {
  font-size: .68rem; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: var(--navy-3); margin: 0 0 .6rem;
}

/* The claims box. Every page carries one. It is the sentence the whole
   estate is legally standing on, so it gets the heaviest device in a
   two-colour palette: a solid navy edge and the deepest ink. */
.limits {
  border: 1px solid var(--line); border-left: 4px solid var(--navy);
  border-radius: 4px 18px 18px 4px;
  padding: 26px 30px; margin: 3rem 0;
  background: var(--white);
  box-shadow: 0 1px 2px rgba(22,50,78,.04), 0 10px 26px rgba(22,50,78,.05);
}
.limits .k {
  font-size: .68rem; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: var(--navy); margin: 0 0 .6rem;
}
.limits p { color: var(--navy-2); font-size: .95rem; }
.limits p:last-child { margin-bottom: 0; }

/* The one permitted sentence, quoted from lead.py.
   WAS color: var(--lime) — #c9f542 on a pale ground, which is the same
   invisible-text bug as the H3s. */
.claim {
  font-family: var(--mono); font-size: .88rem; line-height: 1.6;
  color: var(--navy);
  border: 1px dashed var(--line-2); border-radius: 14px;
  padding: 20px 24px; margin: 2.4rem 0; background: var(--wash);
  /* THIS IS THE ONE BLOCK THAT CARRIES BARE URLS, because a sourced
     competitor fact cites where it came from. A citation host plus path
     is a single unbreakable token, and in mono at 360px one of them ran
     24px past this box and took the whole page sideways with it. */
  overflow-wrap: break-word;
}
.claim .src {
  display: block; margin-top: .55rem;
  font-size: .64rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--navy-3); font-weight: 700;
}

/* Screen-reader-only. Used for <caption> on the data tables, which has
   to exist for assistive tech and would be redundant beside the H2. */
.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;
}

/* ----------------------------------------------------------- tables */
/* NOT CHANGED, DELIBERATELY: table{min-width:30rem} inside an
   overflow-x:auto scroller is why a 480px comparison table sits inside a
   337px viewport and the PAGE still does not move sideways. That is the
   pattern, not a bug. */
.tbl-scroll {
  overflow-x: auto; margin: 2.6rem 0 2.8rem;
  border: 1px solid var(--line); border-radius: 18px;
  background: var(--white);
}
table { width: 100%; border-collapse: collapse; font-size: .89rem; min-width: 30rem; }
th, td {
  text-align: left; padding: 15px 22px;
  border-bottom: 1px solid var(--line); vertical-align: top;
}
tr:last-child td { border-bottom: 0; }
th {
  font-size: .66rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--navy-3); font-weight: 700; background: var(--wash);
  white-space: nowrap;
}
td { color: var(--navy-2); }
td.n { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--navy); }


/* =====================================================================
   BUTTONS — v2's pill, in navy and white
   ===================================================================== */
.btn-solid, .btn-ghost {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .55rem;
  font: 700 .9rem/1 var(--geo); letter-spacing: .004em;
  padding: .85rem 1.5rem; border-radius: 999px;
  text-decoration: none; white-space: nowrap;
  /* THE TRANSPARENT BORDER IS LOAD-BEARING. Without it the two buttons
     are 2px different in height, which is invisible when they sit on
     separate rows and obvious in .cta-row, where they stand shoulder to
     shoulder. Both carry the border; only the colour changes. */
  border: 1px solid transparent;
  transition: transform .18s, background .18s, border-color .18s, color .18s;
}
.btn-solid { background: var(--navy); color: var(--white); }
.btn-solid:hover { background: #0d2137; color: var(--white); transform: translateY(-1px); }
.btn-ghost { background: var(--white); color: var(--navy); border-color: var(--line); }
.btn-ghost:hover { border-color: var(--line-2); color: var(--navy); transform: translateY(-1px); }
.arr { font-size: .9em; display: inline-block; transition: transform .22s cubic-bezier(.2,1.4,.4,1); }
.btn-solid:hover .arr, .btn-ghost:hover .arr { transform: translateX(4px); }

/* ---- the same two buttons, standing on the navy band ---- */
.ctaband .btn-solid {
  background: var(--white); color: var(--navy);
  box-shadow: 0 10px 26px rgba(0,0,0,.18);
}
.ctaband .btn-solid:hover { background: #eef3f9; color: var(--navy); }
.ctaband .btn-ghost {
  background: transparent; color: var(--white);
  border-color: rgba(255,255,255,.42);
}
.ctaband .btn-ghost:hover { border-color: var(--white); color: var(--white); }


/* =====================================================================
   THE CLOSE — the only band that asks for anything, so it is the only
   one that gets the colour. Same decision v2 makes, in one hue.
   ===================================================================== */
/* LEFT, NOT CENTRED, and the same decision as the masthead. A centred
   34rem paragraph inside a 1216px navy band is the narrow-column problem
   in its purest form. The desktop composition is in THE WIDE
   COMPOSITIONS at the foot of this file; this is the single-column
   fallback it starts from. */
.ctaband { text-align: left; }
.cta { max-width: none; margin: 0; }
.cta h2 {
  margin: 0 0 14px; color: var(--white);
  font-size: clamp(1.9rem, 3.8vw, 2.9rem);
}
.cta p {
  color: rgba(255,255,255,.86); font-size: 1.06rem;
  max-width: 40rem; margin: 0 0 1.1rem;
}
.cta p b, .cta p strong { color: var(--white); }
.cta-row {
  display: flex; flex-wrap: wrap; gap: .7rem;
  justify-content: flex-start; margin-top: 1.6rem;
}
.cta .fine {
  font-size: .84rem; color: rgba(255,255,255,.64);
  margin: 1.6rem 0 0; max-width: 40rem;
}


/* =====================================================================
   FAQ
   ===================================================================== */
.faq { margin: 2.4rem 0 2.8rem; border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; padding: 1.05rem 0;
  /* WAS #dbe6ec — the third of the three invisible-text rules. Every
     question on every page was white on white until you selected it. */
  font-weight: 700; font-size: 1rem; color: var(--navy);
  letter-spacing: -.01em;
  list-style: none; display: flex; gap: .8rem; align-items: flex-start;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::before {
  content: "+"; color: var(--navy-3); font-family: var(--mono);
  font-weight: 400; flex: 0 0 auto; line-height: 1.5;
}
.faq details[open] summary::before { content: "\2013"; }
.faq details[open] summary { color: var(--navy); }
.faq .a { padding: 0 0 1rem 1.6rem; color: var(--navy-2); font-size: .95rem; }
.faq .a p:last-child { margin-bottom: 0; }


/* =====================================================================
   RELATED — a wash band of rounded hairline cards
   ===================================================================== */
.related { max-width: none; margin: 0; }
.related h2 {
  margin: 0 0 2rem; font-size: clamp(1.5rem, 2.6vw, 2rem);
  text-align: left;
}
/* auto-fit against the shell rather than against 1180px: three 392px
   cards at 1216, two at tablet, one on a phone, with no breakpoints.
   min(19rem, 100%) for the reason given over .figs. */
.rel-grid {
  display: grid; gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
}
.rel {
  display: block; text-decoration: none; color: var(--navy);
  background: var(--white);
  border: 1px solid var(--line); border-radius: 18px;
  padding: 26px 28px;
  box-shadow: 0 1px 2px rgba(22,50,78,.04);
  transition: transform .2s, box-shadow .2s, border-color .2s;
}
.rel:hover {
  transform: translateY(-3px); border-color: var(--line-2); color: var(--navy);
  box-shadow: 0 2px 4px rgba(22,50,78,.06), 0 18px 40px rgba(22,50,78,.10);
}
.rel .rk {
  display: block; font-weight: 700; font-size: 1.02rem;
  letter-spacing: -.015em; margin-bottom: .4rem;
}
.rel .rd { display: block; font-size: .88rem; color: var(--navy-2); line-height: 1.5; }


/* =====================================================================
   LIBRARY (lp/index.html)
   ===================================================================== */
.hubsec { margin: 4rem 0 0; }
.hubsec h2 { font-size: clamp(1.4rem, 2.4vw, 1.8rem); margin: 0 0 .4rem; }
.hubsec > p { color: var(--navy-2); font-size: .96rem; margin: 0 0 1.1rem; max-width: 56rem; }
.hublist {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr));
}
.hublist li { margin: 0; }
.hublist a {
  display: block; padding: 16px 18px; background: var(--white);
  border: 1px solid var(--line); border-radius: 16px;
  text-decoration: none; color: var(--navy);
  font-size: .96rem; font-weight: 600; letter-spacing: -.01em;
  box-shadow: 0 1px 2px rgba(22,50,78,.04);
  transition: transform .18s, border-color .18s, box-shadow .18s;
}
.hublist a:hover {
  transform: translateY(-2px); border-color: var(--line-2); color: var(--navy);
  box-shadow: 0 2px 4px rgba(22,50,78,.06), 0 14px 32px rgba(22,50,78,.09);
}


/* =====================================================================
   FOOTER

   WHITE GROUND, NOT NAVY, and that is a deliberate choice rather than a
   missed opportunity. The footer's first child is the wordmark, and the
   only wordmark these pages reference is logo-ink.png — navy artwork.
   Painting the band navy would have made the logo vanish into it, and
   the fixes for that are all worse than the problem: swapping in
   logo-white.png changes 27 <img> sources for decoration, and a CSS
   filter to invert it is a trick that fails silently on the day someone
   re-exports the asset with a different ink.
   ===================================================================== */
.foot {
  border-top: 1px solid var(--line);
  margin-top: 0; padding: 54px 0 62px;
  background: var(--white);
}
.foot .wrap > * { margin-bottom: 1.1rem; }
.foot .wordmark img { height: 21px; }
.foot-links { display: flex; flex-wrap: wrap; gap: .5rem 1.6rem; }
.foot-links a {
  color: var(--navy-2); text-decoration: none; font-size: .875rem; font-weight: 500;
}
.foot-links a:hover { color: var(--navy); }
.foot-legal {
  color: var(--navy-3); font-size: .8rem; line-height: 1.6;
  max-width: 42rem; margin: 0;
}
.foot-small { color: var(--navy-2); font-size: .86rem; margin: .4rem 0 0; }


/* =====================================================================
   DIAGRAMS
   The inline SVGs read their colours from these custom properties. If
   they are not declared the presentation attributes fall back to their
   initial value and the whole figure renders solid black, so this block
   is load-bearing rather than cosmetic.

   MONOCHROME BY NECESSITY. The originals used a green/red pair for the
   good and bad grade. There is no second hue in this palette, so the
   two cases are told apart by the labels the figure already carries
   ("falls away / −5%" against "tips toward / +2%") and by weight, not
   by colour. That is a real loss of one glanceable signal, traded for
   the palette holding.
   ===================================================================== */
/* The width now comes from the grid track (.dia sits in `wide`), so the
   old 56rem cap would only have fought it. */
.dia { margin: 2.8rem 0 2.4rem; max-width: none; }
.dia svg {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--line); border-radius: 18px; background: var(--white);
  --dia-sky:  #f4f7fb;
  --dia-soil: #dde5ee;
  --dia-wall: #b7c6d8;
  /* THE DIAGRAM HAS TWO CASES AND ONE HUE.
     These were green and red. A two-colour palette has no second hue,
     so collapsing both to the same navy left the good case and the bad
     case identical - the reader could only tell them apart by reading
     the labels, which is not what a diagram is for.
     Encoded in WEIGHT and DASH instead, which is what cartography does
     when it runs out of colour: the condition that matters is heavy and
     solid, the benign one is lighter and dashed. It also survives
     greyscale printing and every form of colour blindness, which the
     green/red version did not. */
  --dia-ok:   #6a7f97;
  --dia-bad:  #16324e;
  --dia-dim:  #8b9db2;
}
.dia .dl { font: 600 13px var(--geo); fill: var(--navy-2); }
.dia .dv { font: 700 23px var(--geo); fill: var(--navy); letter-spacing: -.03em; }
.dia .dv.bad { fill: var(--navy); }
.dia .dm { font: 500 11px var(--mono); fill: var(--navy-3); }
.dia .mid { text-anchor: middle; }
.dia figcaption { font-size: .88rem; color: var(--navy-2); margin-top: .7rem; }


/* =====================================================================
   SCROLL REVEAL

   IT FAILS OPEN. The hidden state is scoped to html.js, which an inline
   script in the head sets, so no-JS, blocked-JS and a browser without
   IntersectionObserver all get the page rather than a blank band. v2
   learned this the expensive way: `.sr { opacity: 0 }` unconditionally
   meant the content depended on a script running to exist at all, and
   requestAnimationFrame does not fire in a hidden tab.

   `.on` IS OWNED BY THIS AND NOTHING ELSE in this sheet. v2 had one
   class doing duty for both the reveal and a step highlighter, and the
   two erased each other on every tick.
   ===================================================================== */
html.js .sr { opacity: 0; transform: translateY(16px); }
html.js .sr.on {
  opacity: 1; transform: none;
  transition: opacity .6s cubic-bezier(.2,.7,.2,1),
              transform .6s cubic-bezier(.2,.7,.2,1);
}
@media (prefers-reduced-motion: reduce) {
  html.js .sr { opacity: 1; transform: none; }
}


/* =====================================================================
   NARROWING

   Everything above is the desktop composition. These two queries take
   it down to a phone: the bands lose about a third of their padding,
   the nav stops being sticky (a pill that wraps to two rows and then
   pins costs 90px of a 640px-tall screen), and every navigation target
   grows to a thumb.
   ===================================================================== */
@media (max-width: 900px) {
  .nav { gap: 18px; padding: 8px 16px; }
  .nav-links { gap: 15px; }
  .nav-links a { font-size: .82rem; }
  .lphero  { padding: 56px 0 40px; }
  .prose   { padding: 40px 0 30px; }
  .ctaband { padding: 78px 0 84px; }
  .ctaband ~ .prose { padding: 60px 0 66px; }
  .relband { padding: 72px 0 78px; }
}

@media (max-width: 735.98px) {
  /* NOT STICKY DOWN HERE. The pill has to wrap to two rows at this
     width, and a two-row pinned header on a phone is a permanent 90px
     bite out of the viewport. It scrolls away instead; every link in it
     is repeated verbatim in the footer. */
  .nav {
    position: static; width: auto; max-width: none;
    margin: 12px 12px 0;
    border-radius: 22px; flex-wrap: wrap; justify-content: center;
    gap: 6px 14px; padding: 10px 16px;
  }
  .nav-links { flex-wrap: wrap; justify-content: center; gap: 0 14px; }

  /* --- thumbs. min-height plus inline-flex: the anchor keeps its type
     and its colour and only grows the box that is hit-tested. "Data" is
     four characters and drew a 29px-wide target in a real navigation
     bar, so min-width too — min-width rather than padding, so the gap
     between the items stays the gap that was designed.
     Inline links inside a sentence are left alone on purpose: 44px on
     those means a 44px line height in the middle of a paragraph. --- */
  .nav-links a, .foot-links a, .crumb a {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  .nav-links a, .foot-links a { min-width: 44px; justify-content: center; }
  .wordmark { min-height: 44px; }
  .btn-solid, .btn-ghost { min-height: 44px; }
  .faq summary { padding: 1.1rem 0; }
  .rel { padding: 18px 18px; }

  /* --- the 13px of running copy the old sheet shipped --- */
  .fig span, .rel .rd, .foot-small, .foot-legal, .cta .fine, .crumb,
  .dia figcaption { font-size: .875rem; }
  /* Column heads on the data tables were 9.9px. They are micro-labels,
     but a table you scroll sideways is unreadable if you cannot tell
     which column you are in. */
  th { font-size: .72rem; }

  .lphero  { padding: 40px 0 30px; }
  .prose   { padding: 32px 0 24px; }
  .ctaband { padding: 64px 0 68px; }
  .ctaband ~ .prose { padding: 48px 0 54px; }
  .relband { padding: 56px 0 62px; }
  .foot    { padding: 42px 0 50px; }

  /* The section mark shrinks with everything else rather than sitting on
     a phone at desktop scale. */
  .prose > .wrap > h2 { padding-top: .95rem; }
  .prose > .wrap > h2::before { width: 2.25rem; }

  .box, .limits { padding: 20px 22px; }
  .claim { padding: 16px 18px; }
  th, td { padding: 13px 16px; }
  .rel { padding: 20px 20px; }
}


/* The two cases are told apart by line quality, not colour. Attribute
   selectors, so this needs no edit to the 27 pages and applies anywhere
   the tokens are used. */
[stroke="var(--dia-ok)"]  { stroke-dasharray: 9 6; stroke-width: 2.4; }
[stroke="var(--dia-bad)"] { stroke-dasharray: none; stroke-width: 4; }


/* =====================================================================
   THE WIDE COMPOSITIONS

   Everything above this line is the single-column page, and it is what a
   phone and a small tablet get. Higher up, four components that were one
   stacked column each become two, because a component that cannot fill
   1216px is a component that puts the white space back. Two of them turn
   here at 62rem; the masthead and the CTA need more room and turn at
   72rem, for the reason set out over that block.

   WHAT REPLACED WHAT. This block used to hold five rules that gave
   .prose .dia / figure / table / .callout / .measurelist
   `max-width: min(78rem, 100%)`. Two of those class names
   (.callout, .measurelist) appear nowhere in the 27 pages, and the other
   three were inside a 768px container, so `100%` was 768px and the
   "breakout" was a no-op. The breakout is now a grid track. Also gone:
   `.prose table { display: block; overflow-x: auto }`, which put a
   second horizontal scroller inside .tbl-scroll - every table in the
   estate is already wrapped in one (checked: 13 tables, 13 wrappers).
   ===================================================================== */
@media (min-width: 62rem) {

  /* --- THE CALLOUTS -------------------------------------------------
     .limits is on all 26 content pages and .box on ten, so these two are
     the most common furniture in the estate and the widening is most
     visible in them. The uppercase key line moves into a rail and the
     paragraphs sit beside it, which uses the width instead of leaving a
     10rem gutter of wash inside the card. Structural: `> .k` and
     `> :not(.k)` rather than :first-child and + p, so a callout that
     grows a list or a third paragraph still lands correctly. */
  .limits, .box {
    display: grid;
    grid-template-columns: minmax(8rem, 13rem) minmax(0, 1fr);
    column-gap: 2.5rem;
    align-items: start;
  }
  .limits > .k, .box > .k {
    grid-column: 1; grid-row: 1 / span 99;
    margin: .2rem 0 0; line-height: 1.5;
  }
  .limits > :not(.k), .box > :not(.k) { grid-column: 2; }
  .limits > :last-child, .box > :last-child { margin-bottom: 0; }

  /* --- THE FAQ ------------------------------------------------------
     Two columns of <details>. The borders are left exactly as they were:
     the rule on .faq spans both columns as the list's opening line, and
     each item keeps its own bottom border, so laying the list out in two
     columns produces no doubled hairlines and needs no :nth-child()
     patching. An odd item count leaves the last row half full, which
     reads as the list ending rather than as a hole. */
  .faq {
    display: grid; grid-template-columns: 1fr 1fr;
    column-gap: 3.5rem;
  }
}


/* =====================================================================
   THE WIDE COMPOSITIONS, PART TWO — the two that need more room

   TWO BREAKPOINTS, NOT ONE, AND THIS IS THE MEASUREMENT THAT FORCED IT.
   I wrote all four of these compositions against a single 62rem gate
   first, which is tidy to read and wrong on the page. Measured across
   all 27 pages at a 1000px viewport:

     the CTA   the button row is two nowrap pills and needs 425px flat.
               Against `minmax(0,1fr) auto` that left the headline column
               424px on the narrowest page - a 50/50
               split where one half is a heading and a paragraph and the
               other half is two buttons and air.
     the hero   the headline column came out 485px, which put ten of the
               27 H1s onto four lines and one onto five, with an
               eleven-line lede stood beside a five-line headline.

   Neither is an overflow and neither would have shown up in a
   scrollWidth check. They are just bad, and only between about 992px and
   1150px. The FAQ and the callouts have no such floor - two 385px FAQ
   columns and an 8rem callout rail are both fine at 1000px - so holding
   all four back to 72rem would cost those two 160px of range for
   nothing. The components gate where they actually stop working.
   ===================================================================== */
@media (min-width: 72rem) {

  /* --- THE MASTHEAD -------------------------------------------------
     Eyebrow and headline left, lede in a column beside it, breadcrumb
     across the top. Rows are assigned explicitly rather than left to
     auto-placement because lp/index.html is the one page with no
     breadcrumb, and under auto-placement its missing first row would
     have pulled the lede up out of alignment with the headline.
     1.1/0.9 rather than an even split: at 1440 that is a 634px headline
     column running 2-4 lines against a 518px lede running 4-8, so the
     two sides land within about 40px of each other on every page in the
     estate. They are bottom-aligned, which is what absorbs the rest. */
  .lphero > .wrap {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
    column-gap: 4rem;
  }
  .lphero .crumb   { grid-column: 1 / -1; grid-row: 1; }
  .lphero .eyebrow { grid-column: 1; grid-row: 2; }
  .lphero h1       { grid-column: 1; grid-row: 3; margin-bottom: 0; }
  .lphero .lede    {
    grid-column: 2; grid-row: 2 / 4;
    align-self: end; max-width: none; margin: 0;
  }

  /* --- THE CLOSE ----------------------------------------------------
     Copy left, buttons right, fine print under the copy. Explicit rows
     again: seven of the 26 content pages have no .fine paragraph. */
  .cta {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 4.5rem;
    align-items: center;
  }
  .cta h2            { grid-column: 1; grid-row: 1; }
  .cta > p:not(.fine){ grid-column: 1; grid-row: 2; }
  .cta-row           { grid-column: 2; grid-row: 1 / span 2;
                       justify-content: flex-end; margin-top: 0; }
  .cta .fine         { grid-column: 1 / -1; grid-row: 3; }
}
