@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/archivo-400-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/ibm-plex-mono-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/ibm-plex-mono-500-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(/fonts/literata-400-600-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/archivo-400-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/ibm-plex-mono-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/ibm-plex-mono-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(/fonts/literata-400-600-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
:root {
  /* -- surfaces ---------------------------------------------------------- */
  --paper:      #FAF7F2;
  --surface:    #FFFFFF;
  --raised:     #F2ECE1;
  --sunken:     #EFE8DC;

  /* -- ink --------------------------------------------------------------- */
  --ink:        #14161C;  /* 16.9:1 paper · 18.1:1 surface · 15.4:1 raised */
  --ink-soft:   #3A3F49;  /*  9.9:1 paper · 10.6:1 surface ·  9.0:1 raised */
  --muted:      #5F6570;  /*  5.5:1 paper ·  5.9:1 surface ·  5.0:1 raised · 4.8:1 sunken */

  /* -- lines ------------------------------------------------------------- */
  --rule:       #E6DFD3;  /* decorative hairline only — 1.2:1, never carries meaning */
  --rule-firm:  #8E8574;  /*  3.4:1 paper · 3.7:1 surface — UI edges, figure strokes */

  /* -- accent: structure, navigation and links --------------------------- */
  --accent:     #1E3EA8;  /*  8.5:1 paper · 9.1:1 surface · 7.7:1 raised · 7.8:1 accent-bg */
  --accent-ink: #17307F;  /* 11.1:1 paper · 10.3:1 accent-bg */
  --accent-bg:  #EAEEFA;  /* muted on it: 5.1:1 */
  --on-accent:  #FFFFFF;  /*  9.1:1 on an --accent fill */

  /* -- data and signal ---------------------------------------------------- */
  --data:       #8A4A05;  /*  6.4:1 paper · 6.9:1 surface · 6.1:1 data-bg · 5.8:1 raised */
  --data-bg:    #FBF0DF;
  --good:       #14664A;  /*  6.5:1 paper · 6.9:1 surface */
  --warn:       #8A4A05;  /*  6.4:1 paper · 6.9:1 surface */
  /* ON THE FIELD ONLY. The ratios that matter are the painted ones, not the
     ones against flat --field: the top of the band is --field-2 under the
     glow, with a --field-tint pill on top of that, and the kicker's worst
     pixel there measures 4.7:1 at 390px. 8.5:1 on flat --field. */
  --signal:     #F3A73F;
  --signal-ink: #8A4A05;  /*  the same hue at body weight on paper: 6.4:1 · 5.8:1 on signal-tint */
  --signal-tint:#FBEAD2;

  /* -- the field: the brand colour, used large ---------------------------- */
  /* This is the answer to "there is no colour". It is painted edge to edge
     behind the masthead of every page that has one. In dark mode it moves UP
     rather than down: against a #0D0F16 ground a #131A36 band is 1.09:1 and
     simply disappears, so the dark field is a lighter, more saturated indigo
     that still reads as a block of colour. */
  --field:        #131A36; /* 16.0:1 against --paper — the band reads as a band */
  --field-2:      #1F2850;
  --on-field:     #F4F2ED; /* 15.3:1 on field · 12.7:1 on field-2 */
  --on-field-soft:#BFC6E0; /* 10.1:1 on field · 8.4:1 on field-2 · 7.4:1 on a tile */
  /* Pill fill. Measured under the kicker on the rendered band rather than
     against flat --field: the wash and the glow together took --signal to
     4.19:1 at 390px, on the pill's top-right corner. */
  --field-tint:   rgba(255,255,255,.05); /* signal on it, over the glow: 4.7:1 */
  --field-tint-2: rgba(255,255,255,.13); /* tile fill and 1px separators */
  --field-edge:   rgba(255,255,255,.17); /* decorative inner edge */
  --field-edge-firm: rgba(255,255,255,.46); /* 4.5:1 light / 3.8:1 dark vs field —
                                               the boundary value for a real control
                                               on the field, e.g. a hero CTA */
  --field-line:   rgba(255,255,255,.10); /* the drafting grid */
  --field-glow:   rgba(126,140,216,.24);
  --field-warm:   rgba(243,167,63,.13);

  /* Not a colour: an alpha channel for mask-image, which has no theme. Written
     as a token so this sheet contains no bare colour literal at all. */
  --mask-on: #000000;

  /* Paper is paper. A browser prints with backgrounds off by default, so every
     band on this site vanishes and its --on-field text would land near-white on
     white; and a reader whose OS is in dark mode still prints on white, where
     --ink is #E9E6E0. These two are deliberately constant across all three
     theme states and are used only inside @media print. */
  --print-ink:  #14161C;
  --print-soft: #3A3F49;

  /* -- type --------------------------------------------------------------- */
  --serif:   "Literata", Georgia, "Times New Roman", serif;
  --sans:    "Archivo", -apple-system, "Segoe UI", system-ui, sans-serif;
  --display: "Archivo", -apple-system, "Segoe UI", system-ui, sans-serif;
  --mono:    "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;

  /* Fluid, and checked at both ends. --t-display is 42px on a 390px phone,
     where it is comfortably the loudest thing on the screen, and 78px at
     1440px. The old h1 topped out at 54px, which is why the page had no voice. */
  --t-display:   clamp(2.625rem, 1.79rem + 3.43vw, 4.875rem); /* 42 → 78 */
  --t-display-2: clamp(2.125rem, 1.60rem + 2.15vw, 3.500rem); /* 34 → 56 */
  --t-h1:        clamp(2.100rem, 1.55rem + 2.25vw, 3.375rem); /* 34 → 54 */
  --t-h2:        clamp(1.500rem, 1.20rem + 1.25vw, 2.125rem); /* 24 → 34 */
  --t-h3:        clamp(1.200rem, 1.08rem + 0.50vw, 1.450rem); /* 19 → 23 */
  --t-body:  19px;
  --t-sm:    15px;
  --t-xs:    13.5px;
  /* 12px is the floor, not a preference: below it iOS Safari zooms the page on
     focus and Android's "small text" accessibility setting scales it away to
     nothing. --t-micro fed .kicker, .card .n and the mobile TOC count, which
     put 11.5px uppercase mono on the home page, all eight category pages,
     /tools/, /figures/, /search/ and the 404. */
  --t-micro: 12px;

  /* -- radius: moderate. Forms stay crisp, bands and cards may round. ------ */
  --r-xs: 4px; --r-sm: 8px; --r: 12px; --r-lg: 20px; --r-full: 999px;

  /* -- elevation: depth from layered surfaces, not from more borders -------
     A three-rung scale. --e3 is unused in this file and is here for the hero
     and page-component modules, so they lift something without inventing a
     fourth shadow. */
  --e1: 0 1px 2px rgba(20,22,28,.05), 0 4px 12px -4px rgba(20,22,28,.07);
  --e2: 0 2px 4px rgba(20,22,28,.05), 0 14px 30px -12px rgba(20,22,28,.14);
  --e3: 0 4px 10px rgba(20,22,28,.06), 0 32px 64px -20px rgba(20,22,28,.20);
  --ring: inset 0 0 0 1px rgba(20,22,28,.07);

  --shell: 1200px;
  --measure: 68ch;
  --pad: clamp(18px, 4vw, 40px);
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:      #0D0F16;
    --surface:    #141821;
    --raised:     #1B202B;
    --sunken:     #101520;
    --ink:        #E9E6E0; /* 15.4:1 paper · 14.3:1 surface · 13.1:1 raised */
    --ink-soft:   #C6C3BC; /* 10.9:1 paper · 10.1:1 surface */
    --muted:      #969CA8; /*  6.9:1 paper ·  6.4:1 surface · 5.9:1 raised · 6.6:1 sunken */
    --rule:       #262B36;
    --rule-firm:  #6E7484; /*  4.1:1 paper ·  3.8:1 surface */
    --accent:     #9EB7F2; /*  9.6:1 paper ·  8.9:1 surface · 7.7:1 accent-bg */
    --accent-ink: #C3D2F8; /* 12.7:1 paper · 10.2:1 accent-bg */
    --accent-bg:  #1A2340;
    --on-accent:  #141821; /*  8.9:1 on an --accent fill */
    --data:       #F0B266; /* 10.3:1 paper ·  8.5:1 data-bg */
    --data-bg:    #2C2010;
    --good:       #5FBE9A; /*  8.5:1 paper */
    --warn:       #F0B266; /* 10.3:1 paper */
    /* Measured on the rendered band, not against the flat token: the top of the
       band is --field-2 under the glow, and #F3A73F landed at 3.9:1 there — the
       kicker on every masthead. Lifted until the worst painted pixel clears 4.5.
       Light mode keeps #F3A73F; its band is 1.9x darker. */
    --signal:     #F8BE6D; /*  4.7:1 on the band top · 7.9:1 on flat --field */
    --signal-ink: #F0B266; /*  8.5:1 on signal-tint */
    --signal-tint:#2C2010;
    --field:      #26346B; /* 1.63:1 against --paper — still reads as a block */
    --field-2:    #2C3A78;
    /* The band's top edge is --field-2 plus the glow, not flat --field, and the
       dark band starts 1.9x lighter than the light one. Measured on the rendered
       page, --on-field-soft at #BFC6E0 fell to 3.65:1 on the stat tiles there.
       This is the same hue lifted until the worst painted pixel clears 4.5:1. */
    --on-field-soft: #D5DBEE; /* 4.6:1 on a doubly-tinted tile · 12.3:1 on flat --field */
    /* The pill and tile fill. On the light band a 7% white wash is invisible;
       on the dark band it lifts the very patch the kicker and the stat labels
       sit on, and it stacks — the research tiles paint --field-tint over
       --field-tint-2. Halved here so the fill still reads as a fill without
       eating the 4.5:1 those two labels need. */
    --field-tint:   rgba(255,255,255,.04);
    --field-glow: rgba(142,158,236,.10);
    --field-warm: rgba(243,167,63,.10);
    --e1: 0 1px 2px rgba(0,0,0,.50), 0 4px 12px -4px rgba(0,0,0,.50);
    --e2: 0 2px 4px rgba(0,0,0,.50), 0 14px 30px -12px rgba(0,0,0,.60);
    --e3: 0 4px 10px rgba(0,0,0,.50), 0 32px 64px -20px rgba(0,0,0,.70);
    --ring: inset 0 0 0 1px rgba(255,255,255,.08);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --paper: #0D0F16; --surface: #141821; --raised: #1B202B; --sunken: #101520;
  --ink: #E9E6E0; --ink-soft: #C6C3BC; --muted: #969CA8;
  --rule: #262B36; --rule-firm: #6E7484;
  --accent: #9EB7F2; --accent-ink: #C3D2F8; --accent-bg: #1A2340; --on-accent: #141821;
  --data: #F0B266; --data-bg: #2C2010; --good: #5FBE9A; --warn: #F0B266;
  --signal: #F8BE6D; --signal-ink: #F0B266; --signal-tint: #2C2010;
  --field: #26346B; --field-2: #2C3A78;
  --on-field-soft: #D5DBEE;
  --field-tint: rgba(255,255,255,.04);
  --field-glow: rgba(142,158,236,.10);
  --field-warm: rgba(243,167,63,.10);
  --e1: 0 1px 2px rgba(0,0,0,.50), 0 4px 12px -4px rgba(0,0,0,.50);
  --e2: 0 2px 4px rgba(0,0,0,.50), 0 14px 30px -12px rgba(0,0,0,.60);
  --e3: 0 4px 10px rgba(0,0,0,.50), 0 32px 64px -20px rgba(0,0,0,.70);
  --ring: inset 0 0 0 1px rgba(255,255,255,.08);
  color-scheme: dark;
}

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

/* The hero band is painted by a pseudo-element that reaches 100vw past its own
   box on both sides, which is the only break-out that works no matter how deep
   in the page the band is nested — and it is nested three different ways across
   the seven page kinds. overflow-x: clip contains it. clip rather than hidden
   deliberately: hidden would make the viewport a scroll container and break the
   sticky header. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: clip; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } * { animation: none !important; transition: none !important; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: var(--t-body);
  line-height: 1.68;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

/* ---------------------------------------------------------------- chrome -- */

.skip {
  position: absolute; left: -9999px;
  background: var(--accent); color: var(--on-accent);
  padding: 10px 16px; z-index: 50; border-radius: var(--r-sm);
  font-family: var(--sans); font-weight: 600;
}
.skip:focus { left: 12px; top: 12px; }

header.site {
  border-bottom: 1px solid var(--rule);
  background: var(--surface);
  position: sticky; top: 0; z-index: 20;
}
.bar {
  max-width: var(--shell); margin: 0 auto; padding: 0 var(--pad);
  display: flex; align-items: center; gap: 24px; min-height: 62px;
}
/* min-height, and centre rather than baseline: the two halves are the same
   size and the same font, so baseline and centre place the glyphs identically,
   but centre lets the box grow to a 44px touch target without dropping the
   text to the bottom of it. The link was 28px tall on every page. */
.wordmark {
  font-family: var(--sans); font-weight: 700; font-size: 17.5px;
  letter-spacing: -0.028em; color: var(--ink); text-decoration: none;
  display: flex; align-items: center; gap: 1px; white-space: nowrap;
  min-height: 44px;
}
.wordmark span { color: var(--accent); }
/* The pill hover needs horizontal padding, and padding on nine links is what
   pushed the bar onto two rows at 1440px. 9px a side plus a 2px gap comes to
   20px per link, which is exactly what the old 20px flex gap cost — so the
   affordance is free and the bar stays one row. */
nav.top { margin-left: auto; display: flex; gap: 2px; flex-wrap: wrap; }
/* Nine links measure 920px and the 1200px shell leaves the nav 730px, so the bar
   is two rows at every desktop width — it is not the search field doing it, and
   it is still two rows at 1440 with the field collapsed. Two rows is therefore
   the honest state of this header until a link is dropped from the markup, so
   they are made to look like two rows on purpose: right-aligned, so the short
   second row sits under the end of the first instead of leaving a ragged hole.
   Above 1079px only — below that the nav is a nowrap sideways scroller, and
   justifying a scroll container to the end starts it scrolled. */
@media (min-width: 1080px) { nav.top { justify-content: flex-end; row-gap: 4px; } }
nav.top a {
  font-family: var(--sans); font-size: 14px; font-weight: 500;
  color: var(--ink-soft); text-decoration: none;
  padding: 7px 9px; border-radius: var(--r-full); white-space: nowrap;
  transition: background .14s, color .14s;
}
nav.top a:hover { color: var(--accent-ink); background: var(--accent-bg); }

/* On narrow screens the six links wrapped into a six-row stack, and because
   the header is sticky that stack — ~270px tall — sat over a third of the
   viewport while scrolling. A single row that scrolls sideways keeps the header
   at 56px and needs no JavaScript; the trailing fade tells the thumb there is
   more to the right. */
@media (max-width: 1079px) {
  .bar { flex-wrap: nowrap; gap: 12px; min-height: 56px; }
  nav.top {
    flex-wrap: nowrap; gap: 2px; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; margin-left: 0; padding-right: 28px;
    mask-image: linear-gradient(to right, var(--mask-on) calc(100% - 28px), transparent);
    -webkit-mask-image: linear-gradient(to right, var(--mask-on) calc(100% - 28px), transparent);
  }
  nav.top::-webkit-scrollbar { display: none; }
}

/* Below 760px the one-row version stopped working, and the measurement says so
   plainly: the nav shares the row with a 130px wordmark that cannot wrap and a
   search field, so its scroll window was 156px at 390px wide and 86px at 320px
   — 9 links and 920px of content read through a slit under a tenth of the
   screen. Nobody scrolls a nav they cannot see is a nav.

   Giving it its own row widens the window to 354px / 284px, 2.3x and 3.3x, and
   is what lets the links become real 44px targets: the row already exists, so
   the height they need costs nothing extra. The header goes from 56px to about
   96px and stays sticky, which is the trade — a tenth of the viewport for a nav
   that works at all.

   flex-basis 100% inside the padding box, NOT a bled negative margin: body is
   overflow-x: clip, so a miscalculated full-bleed row would not scroll, it
   would silently cut the last link off. */
@media (max-width: 759px) {
  .bar {
    flex-wrap: wrap; column-gap: 12px; row-gap: 0;
    min-height: 0; padding-block: 4px; align-items: center;
  }
  .bar > .wordmark { order: 1; }
  .bar > .rgs { order: 2; margin-left: auto; }
  nav.top {
    order: 3; flex: 1 0 100%; min-width: 0; width: 100%;
    padding-right: 32px; margin-bottom: 2px;
  }
  nav.top a {
    display: inline-flex; align-items: center; min-height: 44px;
    padding: 0 11px;
  }
}

/* The search field's own sheet gives it flex: 1 1 190px, and nine nav links plus
   the wordmark left it 165px — narrower than "Search 79 guides", which then sat
   clipped mid-word in the header of all 103 pages. 212px is the placeholder's
   own width plus the icon and clear-button gutters.

   Fenced at 1200 and not 1080 on purpose: lib/ux/search.mjs collapses the field
   to a 44px magnifier all the way up to 1199px, because between 1080 and 1199 a
   full-width field pushes the nav onto three rows. This rule outranks that one
   on class count, so overlapping them would have undone it exactly where it was
   written to help. Two class names because that sheet is concatenated after this
   one and would otherwise win an even tie. */
@media (min-width: 1200px) {
  .bar .rgs { flex: 0 0 auto; width: 212px; }
}

/* ------------------------------------------------------------------ page -- */

main { max-width: var(--shell); margin: 0 auto; padding: 0 var(--pad) 96px; }

.layout { display: block; }
@media (min-width: 1080px) {
  .layout { display: grid; grid-template-columns: minmax(0, 1fr) 232px; gap: 56px; align-items: start; }
}

article { max-width: var(--measure); min-width: 0; }

/* ----------------------------------------------------------------- type --- */

h1 {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-h1); line-height: 1.04;
  letter-spacing: -0.032em; margin: 0 0 16px; text-wrap: balance;
}
h2 {
  font-family: var(--display); font-weight: 650;
  font-size: var(--t-h2); line-height: 1.14;
  letter-spacing: -0.026em; margin: 2.2em 0 0.5em; text-wrap: balance;
  padding-top: 0.45em; border-top: 1px solid var(--rule);
}
h3 {
  font-family: var(--display); font-weight: 650; font-size: var(--t-h3);
  letter-spacing: -0.018em; line-height: 1.24; margin: 1.9em 0 0.4em; text-wrap: balance;
}
h4 {
  font-family: var(--sans); font-weight: 600; font-size: 1rem;
  letter-spacing: 0.005em; margin: 1.6em 0 0.3em; color: var(--ink-soft);
}
h2 .anchor, h3 .anchor, h4 .anchor {
  font-family: var(--mono); color: var(--rule-firm); text-decoration: none;
  margin-left: 8px; opacity: 0; font-size: 0.8em; font-weight: 400;
}
h2:hover .anchor, h3:hover .anchor, h4:hover .anchor { opacity: 1; }
.anchor:focus { opacity: 1; }
/* A device with no hover never reveals these, so on a phone they were an
   invisible 22x35px link sitting immediately after every heading — small enough
   to fail the touch target floor and, worse, invisible enough that hitting one
   read as the page jumping for no reason. They are a pointer affordance; where
   there is no pointer there is nothing for them to afford. */
@media (hover: none) and (pointer: coarse) {
  h2 .anchor, h3 .anchor, h4 .anchor { display: none; }
}

p { margin: 0 0 1.15em; }
article > p:first-of-type { font-size: 1.06em; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--accent-ink); }

strong { font-weight: 650; }
code { font-family: var(--mono); font-size: 0.88em; background: var(--raised); padding: 1px 5px; border-radius: var(--r-xs); }

ul, ol { margin: 0 0 1.3em; padding-left: 1.35em; }
li { margin-bottom: 0.45em; }
li::marker { color: var(--muted); }

blockquote {
  margin: 1.6em 0; padding: 2px 0 2px 20px;
  border-left: 3px solid var(--signal-ink); color: var(--ink-soft); font-style: italic;
}

/* --------------------------------------------------------------- lede ----- */

.lede { color: var(--muted); font-family: var(--sans); font-size: var(--t-xs); margin: 0 0 26px; }
.lede .dot { margin: 0 8px; color: var(--rule-firm); }

/* The eyebrow. On paper it is a line of small caps; on the field it becomes the
   pill, which is the shape every reference site uses to say "this is what kind
   of page you are on" before the headline says what it is about. */
.kicker {
  font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--accent); margin: 0 0 12px;
}

/* =================================================================== HERO ==
   The one large field of saturated colour, and the element the old sheet did
   not have. Used by the home page, the eight category pages, /tools/,
   /figures/, /search/, the four trust pages and the 404 — every page kind that
   has a masthead of its own.

   The band is painted by ::before rather than by a background on .hero itself,
   because the same .hero div appears at three different nesting depths (a
   direct child of main on the indexes, inside .layout > article on the trust
   pages and the 404, and inside main on the home page) and a break-out that
   depends on the element being centred in the viewport would be wrong on two of
   the three. Reaching 100vw past its own box in both directions is correct
   everywhere and costs one clipped pseudo-element.  ========================= */

.hero {
  position: relative;
  isolation: isolate;
  color: var(--on-field);
  padding: clamp(30px, 4vw, 54px) 0 clamp(34px, 4.4vw, 60px);
  margin: 0 0 clamp(32px, 4vw, 52px);
  border: 0;
}
.hero::before {
  content: "";
  position: absolute; z-index: -2; pointer-events: none;
  top: 0; bottom: 0; left: -100vw; right: -100vw;
  background-color: var(--field);
  background-image:
    radial-gradient(110% 130% at 82% 0%, var(--field-glow), transparent 62%),
    radial-gradient(90% 110% at 0% 100%, var(--field-warm), transparent 60%),
    linear-gradient(158deg, var(--field-2) 0%, var(--field) 58%, var(--field) 100%);
}
/* A drafting grid, faded out from the top so it is texture rather than pattern.
   The mask stop uses --field only for its alpha channel; the colour is
   discarded. */
.hero::after {
  content: "";
  position: absolute; z-index: -1; pointer-events: none;
  top: 0; bottom: 0; left: -100vw; right: -100vw;
  background-image:
    linear-gradient(to right, var(--field-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--field-line) 1px, transparent 1px);
  background-size: 84px 84px;
  opacity: .55;
  -webkit-mask-image: radial-gradient(120% 130% at 50% 0%, var(--mask-on) 6%, transparent 74%);
          mask-image: radial-gradient(120% 130% at 50% 0%, var(--mask-on) 6%, transparent 74%);
}

.hero h1 {
  font-size: var(--t-display-2); line-height: 1.02; letter-spacing: -0.034em;
  font-weight: 700; color: var(--on-field); margin: 0 0 18px; max-width: 18ch;
}
.hero h1 em { font-style: normal; color: var(--signal); }
/* :not([class]) matters. The eyebrow, the fine print and the lede are all <p>
   too, and a bare .hero > p rule outranked .hero .kicker on specificity — which
   set the 11px eyebrow in 19.25px and stretched the pill over two lines on a
   phone. Only the unclassed paragraph is the deck. */
.hero > p:not([class]) { color: var(--on-field-soft); max-width: 58ch; font-size: 1.06em; line-height: 1.6; }
.hero > p:last-child { margin-bottom: 0; }
.hero .fine, .hero .lede { color: var(--on-field-soft); }
.hero .lede .dot { color: var(--signal); }
.hero a { color: var(--signal); }
.hero a:hover { color: var(--on-field); }
.hero :focus-visible { outline-color: var(--signal); }

/* The eyebrow pill. --field-tint fill, --signal text: 7.0:1 in light, 4.8:1 in
   dark, so it clears AA for small text in both. */
.hero .kicker {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0 0 20px; padding: 6px 13px 6px 11px;
  border-radius: var(--r-full);
  background: var(--field-tint);
  box-shadow: inset 0 0 0 1px var(--field-edge);
  color: var(--signal); font-size: 12px; letter-spacing: 0.07em;
  /* In normal flow inline-flex shrink-wraps, but once the hero becomes a grid
     to make room for the artwork the pill is a grid item and stretches to the
     full column — a 570px eyebrow. Pin it to the start. */
  justify-self: start;
}
.hero .kicker a { color: inherit; text-decoration: none; }
.hero .kicker::before {
  content: ""; width: 6px; height: 6px; flex: none;
  border-radius: 50%; background: var(--signal);
}
/* A long eyebrow on a narrow phone has to be allowed to wrap, and a wrapped
   pill is a rounded rectangle — a 999px radius round two lines of text reads as
   a mistake. The dot moves to the first line's baseline rather than centring
   against the whole block. */
@media (max-width: 559px) {
  .hero .kicker {
    border-radius: var(--r); align-items: flex-start; line-height: 1.5;
    letter-spacing: 0.06em;
  }
  .hero .kicker::before { margin-top: 5px; }
}

/* The home page states its subject at full volume: 78px at desktop, 42px on a
   390px phone, where it is still the loudest thing on the screen. */
.hero.home { padding: clamp(36px, 5.2vw, 84px) 0 clamp(40px, 5.6vw, 88px); }
.hero.home h1 { font-size: var(--t-display); letter-spacing: -0.038em; line-height: 0.99; max-width: 15ch; }
/* 34em, not the 58ch the other heroes get. A deck set the full width of a
   1200px shell reads as a paragraph that ran out of column, and it is the line
   that has to carry the whole promise. */
.hero.home > p:not([class]) { font-size: 1.1em; max-width: 34em; line-height: 1.56; }

/* Room on the right for the artwork lib/hero.mjs supplies. The contract is one
   element with class .hero-art as the LAST child of .hero — either wrapping an
   inline <svg>, or an <svg class="hero-art"> itself. Below 1000px it drops under
   the copy; where :has() is missing the whole rule is skipped and the layout is
   the single column it already was. */
/* margin: 0 so the container may be a <figure>, which carries a UA margin. */
.hero-art { display: block; min-width: 0; margin: 0; }
.hero-art > svg, svg.hero-art { display: block; width: 100%; height: auto; overflow: visible; }
.hero-art figcaption, .hero-art .cap {
  margin: 16px 0 0; font-family: var(--sans); font-size: var(--t-xs);
  line-height: 1.55; color: var(--on-field-soft);
}
.hero-art figcaption b, .hero-art .cap b {
  color: var(--signal); font-family: var(--mono); font-weight: 500; letter-spacing: 0.04em;
}
.hero > .hero-art { margin-top: clamp(28px, 4vw, 44px); max-width: 480px; }

@media (min-width: 1000px) {
  .hero:has(> .hero-art) {
    display: grid;
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
    column-gap: clamp(36px, 4.5vw, 72px);
    align-items: center;
  }
  .hero:has(> .hero-art) > * { grid-column: 1; }
  /* Spanning far more rows than the copy will ever fill keeps the art centred
     without the copy's own rows absorbing its height and spreading apart. */
  .hero:has(> .hero-art) > .hero-art {
    grid-column: 2; grid-row: 1 / span 40; align-self: center; justify-self: center;
    margin-top: 0; max-width: 520px; width: 100%;
  }
}

/* Articles and tool pages are the 86 of 103 pages that currently have no .hero
   at all: their kicker and h1 sit straight on paper, so those pages get none of
   the colour. The band is tuned for them here and needs only a wrapper in
   build.mjs — put the breadcrumbs, .kicker, h1, .deck and .lede inside
   <div class="hero article"> (or "hero tool") and they pick this up. Shorter
   than an index masthead and set at --t-h1 rather than display size, because a
   3,400-word document's title should introduce the document, not shout over it.
   This is the treatment Mayo and Healthline use on exactly this page type. */
.hero.article, .hero.tool {
  padding: clamp(22px, 2.6vw, 34px) 0 clamp(26px, 3vw, 40px);
  margin-bottom: clamp(28px, 3.4vw, 44px);
}
.hero.article h1, .hero.tool h1 { font-size: var(--t-h1); max-width: 24ch; }
.hero.article .breadcrumbs, .hero.article nav[aria-label="Breadcrumb"] { color: var(--on-field-soft); }
.hero.article .breadcrumbs a, .hero.article nav[aria-label="Breadcrumb"] a { color: var(--on-field-soft); }
.hero.article .breadcrumbs a:hover, .hero.article nav[aria-label="Breadcrumb"] a:hover { color: var(--signal); }

/* Two heroes in a row happens exactly once — the 404 renders its own masthead
   and then embeds the /search/ page, which brings its own. The second one drops
   the field and becomes an ordinary section head on paper, which is what it
   actually is; stacking two gradient bands would show the seam between them. */
.hero + .hero {
  color: var(--ink); padding-top: 0; margin-top: 4px;
}
.hero + .hero::before, .hero + .hero::after { display: none; }
.hero + .hero h1 { font-size: var(--t-h2); color: var(--ink); max-width: none; }
.hero + .hero > p { color: var(--ink-soft); font-size: 1em; }
.hero + .hero .kicker {
  background: var(--accent-bg); box-shadow: none; color: var(--accent-ink);
}
.hero + .hero .kicker::before { background: var(--accent); }
.hero + .hero a { color: var(--accent); }

/* ------------------------------------------------------------- summary ---- */

aside.summary {
  background: var(--accent-bg);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  padding: 22px 26px 6px;
  margin: 0 0 34px;
  border-radius: var(--r-sm);
}
aside.summary h2 {
  border: 0; padding: 0; margin: 0 0 10px;
  font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase;
  font-family: var(--mono); font-weight: 500; color: var(--accent);
}
aside.summary p { font-size: 0.97em; color: var(--ink-soft); }
aside.summary ul { font-size: 0.97em; }

/* ---------------------------------------------------------------- table --- */

.scroll { overflow-x: auto; margin: 1.7em 0; border: 1px solid var(--rule); border-radius: var(--r-sm); background: var(--surface); }
table { border-collapse: collapse; width: 100%; font-family: var(--sans); font-size: var(--t-sm); }
thead th {
  background: var(--raised); text-align: left; font-weight: 600; color: var(--ink-soft);
  padding: 11px 14px; border-bottom: 1px solid var(--rule-firm); white-space: nowrap;
  font-size: 12.5px; letter-spacing: 0.05em; text-transform: uppercase;
}
tbody th { text-align: left; font-weight: 600; }
td, tbody th { padding: 11px 14px; border-bottom: 1px solid var(--rule); vertical-align: top; }
tbody tr:last-child td, tbody tr:last-child th { border-bottom: 0; }
tbody tr:nth-child(even) { background: color-mix(in srgb, var(--raised) 45%, transparent); }
td { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- chart --- */

figure.chart { margin: 2em 0; padding: 0; }
figure.chart svg { display: block; width: 100%; height: auto; }
figure.chart figcaption {
  font-family: var(--sans); font-size: var(--t-xs); color: var(--muted);
  margin-top: 10px; line-height: 1.5;
}
figure.chart figcaption b { color: var(--ink-soft); font-weight: 600; }

/* ----------------------------------------------------------- references --- */

section.refs { margin-top: 3em; }
section.refs h2 { font-size: 1.05rem; }
ol.reflist { font-size: var(--t-sm); font-family: var(--sans); color: var(--ink-soft); padding-left: 1.6em; }
ol.reflist li { margin-bottom: 0.7em; line-height: 1.5; }

section.disclaimer { margin-top: 2.4em; }
section.disclaimer h2 { font-size: 0.95rem; color: var(--muted); }
.fine { font-size: 14.5px; color: var(--muted); font-family: var(--sans); line-height: 1.6; }

/* ------------------------------------------------------------------ toc --- */

.toc { display: none; }
@media (min-width: 1080px) {
  .toc {
    display: block; position: sticky; top: 92px;
    font-family: var(--sans); font-size: 13.5px;
    max-height: calc(100vh - 130px); overflow-y: auto;
  }
  .toc h2 {
    font-family: var(--mono); font-size: 12px; letter-spacing: 0.12em;
    text-transform: uppercase; color: var(--muted);
    margin: 0 0 12px; border: 0; padding: 0; font-weight: 500;
  }
  .toc ol { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--rule); }
  .toc li { margin: 0; }
  .toc a {
    display: block; padding: 5px 0 5px 14px; margin-left: -1px;
    color: var(--muted); text-decoration: none; border-left: 2px solid transparent;
    line-height: 1.35;
  }
  .toc a:hover { color: var(--accent); border-left-color: var(--accent); }
}

/* ----------------------------------------------------------------- home --- */

/* The card grid was a 1px lattice on a grey background, which is the single
   most dated construction on the site after the missing hero. Same information,
   same 1px crispness at the edge, but as separated surfaces with real
   elevation. */
.cards { display: grid; gap: 14px; margin: 30px 0; }
@media (min-width: 720px) { .cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .cards.three { grid-template-columns: repeat(3, 1fr); } }
.card {
  background: var(--surface); padding: 22px 24px 20px; text-decoration: none;
  color: inherit; display: block; border-radius: var(--r);
  box-shadow: var(--e1), var(--ring);
  transition: transform .18s cubic-bezier(.2,.7,.3,1), box-shadow .18s;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--e2), var(--ring); }
.card h3 { margin: 0 0 6px; font-size: var(--t-h3); line-height: 1.2; color: var(--ink); }
.card p { margin: 0; font-size: 14.5px; color: var(--muted); font-family: var(--sans); line-height: 1.5; }
.card .n {
  font-family: var(--mono); font-size: var(--t-micro); color: var(--data);
  letter-spacing: 0.1em; text-transform: uppercase; display: block; margin-bottom: 10px;
}

.index-list { list-style: none; padding: 0; margin: 0; }
.index-list li { border-bottom: 1px solid var(--rule); }
.index-list li:first-child { border-top: 1px solid var(--rule); }
.index-list a {
  display: block; padding: 17px 10px; text-decoration: none; color: inherit;
  border-radius: var(--r-sm); transition: background .14s, padding .14s;
}
.index-list a:hover { background: var(--surface); box-shadow: var(--e1); padding-inline: 16px; }
.index-list a:hover .t { color: var(--accent); }
.index-list .t {
  font-family: var(--display); font-weight: 650; font-size: 1.14rem; line-height: 1.24;
  letter-spacing: -0.02em; display: block; margin-bottom: 4px; color: var(--ink);
}
.index-list .d { font-family: var(--sans); font-size: var(--t-xs); color: var(--muted); line-height: 1.5; }

/* ---------------------------------------------------------------- footer -- */

footer.site {
  border-top: 1px solid var(--rule); background: var(--sunken);
  padding: 44px 0 52px; font-family: var(--sans); font-size: 14px; color: var(--muted);
}
footer.site .bar { display: block; min-height: 0; }
/* The footer nav was the worst touch target on the site — eight 23px links in a
   wrapped row on all 103 pages, and the last thing a thumb reaches for. The row
   gap goes to 0 because each link now carries its own 44px of height. */
footer.site nav { display: flex; flex-wrap: wrap; gap: 0 18px; margin-bottom: 14px; }
footer.site nav a { display: inline-flex; align-items: center; min-height: 44px; }
footer.site a { color: var(--ink-soft); text-decoration: none; }
footer.site a:hover { color: var(--accent); text-decoration: underline; }
footer.site p { margin: 0 0 8px; max-width: 70ch; line-height: 1.6; }

/* The focus ring is --accent on paper (8.5:1) and --signal on the field
   (8.5:1). Never --signal on paper, where it is 1.9:1. */
:focus-visible { outline: 2.5px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

@media (max-width: 620px) {
  body { font-size: 17.5px; line-height: 1.62; }
  h2 { margin-top: 2em; }
  .hero h1 { max-width: none; }
}
.deck {
  font-family: var(--sans);
  font-size: clamp(1.02rem, 2.1vw, 1.18rem);
  line-height: 1.45;
  font-weight: 500;
  color: var(--muted);
  margin: -2px 0 24px;
  max-width: 48ch;
  text-wrap: balance;
}
.hero .deck { color: var(--on-field-soft); max-width: 52ch; }
.tool { margin: 8px 0 0; }

.tool fieldset {
  border: 0; border-radius: var(--r);
  padding: 20px 22px 22px; margin: 0 0 18px;
  background: var(--surface); box-shadow: var(--e1), var(--ring);
}
.tool legend {
  font-family: var(--mono); font-size: var(--t-micro); letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--data); padding: 0 10px;
  background: var(--data-bg); border-radius: var(--r-full);
}

.tool label { display: block; font-family: var(--sans); font-size: var(--t-sm); font-weight: 500; margin: 0 0 6px; color: var(--ink); }
.tool .hint { display: block; font-family: var(--sans); font-size: 13.5px; color: var(--muted); font-weight: 400; margin-top: 3px; line-height: 1.45; }

.tool .field { margin: 0 0 18px; }
.tool .field:last-child { margin-bottom: 0; }

.tool input[type="text"], .tool input[type="number"], .tool input[type="date"], .tool select, .tool textarea {
  font-family: var(--sans); font-size: 16px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule-firm); border-radius: var(--r-xs);
  padding: 11px 12px; width: 100%; max-width: 26rem; min-height: 44px;
}
.tool input:focus-visible, .tool select:focus-visible, .tool textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.tool input[type="range"] { width: 100%; max-width: 26rem; accent-color: var(--accent); min-height: 44px; }

/* Radio and checkbox groups as tappable cards — 44px targets, obvious state. */
.tool .choices { display: flex; flex-wrap: wrap; gap: 8px; }
.tool .choices label {
  display: inline-flex; align-items: center; gap: 8px; margin: 0;
  border: 1px solid var(--rule-firm); border-radius: var(--r-full);
  padding: 9px 15px; min-height: 44px; cursor: pointer;
  font-size: 14.5px; font-weight: 500; background: var(--surface);
  transition: border-color .12s, background .12s;
}
.tool .choices label:hover { border-color: var(--accent); }
.tool .choices input { accent-color: var(--accent); margin: 0; width: 16px; height: 16px; }
.tool .choices input:checked + span,
.tool .choices label:has(input:checked) { color: var(--accent-ink); }
.tool .choices label:has(input:checked) { border-color: var(--accent); background: var(--accent-bg); }
.tool .choices input:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.tool button, .tool .btn {
  font-family: var(--sans); font-size: var(--t-sm); font-weight: 600;
  background: var(--accent); color: var(--on-accent);
  border: 1px solid var(--accent); border-radius: var(--r-full);
  padding: 12px 22px; min-height: 44px; cursor: pointer;
  transition: background .14s, border-color .14s, transform .14s;
}
.tool button:hover { background: var(--accent-ink); border-color: var(--accent-ink); }
.tool button.secondary { background: transparent; color: var(--accent); }
.tool button.secondary:hover { background: var(--accent-bg); }
.tool button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The result panel. Deliberately distinct from the article body so nobody
   mistakes a computed projection for prose that was written and reviewed. */
.tool .result {
  border: 0; border-left: 3px solid var(--data);
  background: var(--data-bg); border-radius: var(--r-sm);
  padding: 20px 22px; margin: 22px 0 0; box-shadow: var(--ring);
}
.tool .result h2, .tool .result h3 {
  font-family: var(--display); border: 0; padding: 0; margin: 0 0 10px;
  font-size: 1.12rem; letter-spacing: -0.02em;
}
.tool .result p { font-size: 15.5px; }
.tool .result[hidden] { display: none; }

.tool .readout {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.6rem; font-weight: 500; color: var(--ink);
}
.tool .readout .unit { font-size: 0.6em; color: var(--muted); margin-left: 3px; }

/* A number's provenance, shown inline. This is the whole trust mechanism:
   every figure carries the guide it came from. */
.tool .src {
  font-family: var(--mono); font-size: var(--t-micro); color: var(--muted);
  letter-spacing: 0.04em; white-space: nowrap;
}

.tool .flag {
  border: 0; border-left: 3px solid var(--warn);
  background: color-mix(in srgb, var(--warn) 10%, transparent);
  padding: 14px 16px; margin: 16px 0; border-radius: var(--r-sm);
  font-family: var(--sans); font-size: 14.5px; line-height: 1.55;
}
.tool .flag strong { color: var(--warn); }

.tool-foot { margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--rule); }
.tool-disclaimer { font-family: var(--sans); font-size: 14px; color: var(--muted); line-height: 1.6; margin: 0 0 10px; }
.tool-disclaimer strong { color: var(--ink-soft); }
.tool-sources { font-family: var(--mono); font-size: 12px; color: var(--muted); margin: 0 0 10px; }
.tool-related { font-family: var(--sans); font-size: 14px; color: var(--muted); display: flex; flex-wrap: wrap; gap: 0 12px; align-items: baseline; }
/* 22px tall before, on all seven tool pages */
.tool-related a { text-transform: capitalize; display: inline-flex; align-items: center; min-height: 44px; }

/* Drawn figures inside articles. */
figure.figure-drawn svg { display: block; width: 100%; height: auto; margin: 0 auto; max-width: 640px; }

@media (max-width: 620px) {
  .tool fieldset { padding: 16px 16px 18px; }
  .tool .choices label { font-size: 14px; padding: 9px 13px; }
}
.toc-mobile { display: none; }
@media (max-width: 1079px) {
  .toc-mobile {
    display: block; margin: 0 0 28px;
    border: 0; border-radius: var(--r-sm); background: var(--surface);
    box-shadow: var(--e1), var(--ring);
  }
  .toc-mobile > summary {
    font-family: var(--sans); font-size: 14px; font-weight: 600; color: var(--ink-soft);
    padding: 13px 16px; cursor: pointer; list-style: none;
    display: flex; align-items: center; justify-content: space-between; min-height: 44px;
  }
  .toc-mobile > summary::-webkit-details-marker { display: none; }
  .toc-mobile > summary::after {
    content: ""; width: 8px; height: 8px; margin-left: 10px; flex: none;
    border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
    transform: rotate(45deg) translateY(-2px); transition: transform .15s;
  }
  .toc-mobile[open] > summary::after { transform: rotate(-135deg) translateY(-2px); }
  .toc-mobile > summary .n { font-family: var(--mono); font-size: var(--t-micro); color: var(--muted); font-weight: 400; margin-left: auto; }
  .toc-mobile ol { margin: 0; padding: 0 16px 10px 34px; }
  /* The list item margin was doing the spacing and the link was 29px tall, so
     the gaps between entries were dead space a thumb could land in and miss.
     The margin moves inside the link: same rhythm, whole row is the target. */
  .toc-mobile li { margin: 0; }
  .toc-mobile a { font-family: var(--sans); font-size: 14.5px; color: var(--ink-soft); text-decoration: none; line-height: 1.4; display: flex; align-items: center; min-height: 44px; padding: 4px 0; }
  .toc-mobile a:hover { color: var(--accent); }
}
.stats {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px;
  margin: 0 0 44px;
}
@media (min-width: 760px) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat {
  background: var(--surface); padding: 20px 20px 18px;
  border-radius: var(--r); box-shadow: var(--e1), var(--ring);
}
.stat .v {
  display: block; font-family: var(--display); font-weight: 700;
  font-size: clamp(32px, 5vw, 44px); line-height: 1; letter-spacing: -0.04em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.stat .l {
  display: block; margin-top: 9px; font-family: var(--sans); font-size: var(--t-xs);
  line-height: 1.35; color: var(--muted);
}

/* On the field: one hairline lattice again, but of light rather than of grey,
   which is what makes it read as a single instrument panel instead of four
   floating cards. */
.hero .stats {
  gap: 1px; margin: clamp(28px, 3.6vw, 44px) 0 0;
  background: var(--field-tint-2); border-radius: var(--r); overflow: hidden;
}
.hero .stat {
  background: var(--field-tint); box-shadow: none; border-radius: 0;
}
.hero .stat .v { color: var(--on-field); }
.hero .stat .l { color: var(--on-field-soft); }
.hero .stat:last-child .v { color: var(--signal); }

.asks { display: grid; gap: 14px; margin: 22px 0 12px; }
@media (min-width: 720px) { .asks { grid-template-columns: repeat(2, 1fr); } }
.ask {
  background: var(--surface); padding: 24px 24px 20px; text-decoration: none;
  color: inherit; display: flex; flex-direction: column; gap: 8px;
  border-radius: var(--r); box-shadow: var(--e1), var(--ring);
  position: relative; overflow: hidden;
  transition: transform .18s cubic-bezier(.2,.7,.3,1), box-shadow .18s;
}
.ask::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 4px;
  background: var(--signal-ink); transform: scaleY(0); transform-origin: top;
  transition: transform .22s;
}
.ask:hover { transform: translateY(-3px); box-shadow: var(--e2), var(--ring); }
.ask:hover::before { transform: scaleY(1); }
.ask .q {
  font-family: var(--display); font-weight: 650; font-size: var(--t-h3);
  line-height: 1.22; letter-spacing: -0.022em; color: var(--ink);
}
.ask .a { font-family: var(--sans); font-size: 14.5px; line-height: 1.5; color: var(--muted); }
.ask .go {
  margin-top: auto; padding-top: 10px;
  font-family: var(--sans); font-size: 13.5px; font-weight: 600; color: var(--accent);
  display: inline-flex; align-items: center; gap: 6px;
}
.ask .go svg { transition: transform .15s; }
.ask:hover .go svg { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) { .ask .go svg { transition: none; } }
.asks-note { margin: 0 0 34px; }
html { scroll-padding-top: 80px; }
h2[id], h3[id], h4[id], [id^="fig-"], .refs, .disclaimer { scroll-margin-top: 80px; }
@media (max-width: 1079px) { html { scroll-padding-top: 66px; } h2[id], h3[id], h4[id], [id^="fig-"] { scroll-margin-top: 66px; } }
h2[id]:target, h3[id]:target, h4[id]:target { animation: anchor-land 1.4s ease-out 1; }
@keyframes anchor-land {
  0%, 45% { background: var(--accent-bg); box-shadow: -10px 0 0 var(--accent-bg), 10px 0 0 var(--accent-bg); }
  100%    { background: transparent; box-shadow: none; }
}
@media (prefers-reduced-motion: reduce) { h2[id]:target, h3[id]:target, h4[id]:target { animation: none; } }
details.embed { margin: 14px 0 0; border-top: 1px solid var(--rule); padding-top: 10px; }
details.embed > summary {
  font-family: var(--sans); font-size: 12.5px; font-weight: 600; color: var(--muted);
  cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 7px;
  padding: 3px 0; min-height: 44px;
}
details.embed > summary::-webkit-details-marker { display: none; }
details.embed > summary::before {
  content: ""; width: 6px; height: 6px; flex: none;
  border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor;
  transform: rotate(-45deg); transition: transform .15s;
}
details.embed[open] > summary::before { transform: rotate(45deg); }
details.embed > summary:hover { color: var(--accent); }
details.embed .fine { margin: 8px 0; font-size: 12.5px; }
details.embed textarea {
  width: 100%; box-sizing: border-box; resize: vertical;
  font-family: var(--mono); font-size: 12px; line-height: 1.55;
  color: var(--ink-soft); background: var(--raised);
  border: 1px solid var(--rule); border-radius: var(--r-xs); padding: 10px 12px;
}
details.embed textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (prefers-reduced-motion: reduce) { details.embed > summary::before { transition: none; } }

.fig-entry { margin: 0 0 54px; padding-bottom: 8px; border-bottom: 1px solid var(--rule); }
.fig-entry:last-child { border-bottom: 0; }
.fig-entry > h2 { margin-top: 0; }
.fig-entry .fine a { color: var(--accent); }
.qa { margin: 0 0 4px; padding: 0 0 0 16px; border-left: 2px solid var(--rule); }
.qa + .qa { margin-top: 18px; }
.qa > h3.q {
  margin: 0 0 6px; font-family: var(--display); font-size: 1.05rem; font-weight: 650;
  line-height: 1.35; color: var(--ink); letter-spacing: -0.012em;
}
.qa > p { margin: 0; color: var(--ink-soft); }
.qa:hover { border-left-color: var(--signal-ink); }
.qa > h3.q > .anchor { font-size: 0.85em; }
@media (max-width: 560px) {
  figure.chart.figure-drawn {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x pan-y;
    overscroll-behavior-x: contain;
    border: 1px solid var(--rule);
    border-radius: var(--r-sm);
    padding: 10px 10px 0;
    background: var(--surface);
  }
  figure.chart.figure-drawn > svg { min-width: 430px; margin: 0; }
  figure.chart.figure-drawn figcaption { padding: 0 2px 12px; }
}

/* ================================================== THE REST OF THE SITE ===
   lib/theme-pages.mjs and lib/theme-article.mjs were written in the same pass
   as this file and were reachable from nothing: build.mjs imports only from
   this module, so 46 KB of the redesign — every tool page, /research/,
   /figures/, /search/ and all 79 guides — was dead code and the live site
   still carried the pre-redesign look on 89 of its 103 pages.

   They are pulled in here rather than added to build.mjs's import list so the
   fix lives in a file this pass owns. Order is load-bearing and matches what
   each sheet documents about itself: pages first, then the article sheet,
   which states it is loaded last so it wins on ties. Both land after
   FIGURE_MOBILE_CSS, which the article sheet deliberately does not fight — its
   figure rules are all fenced above 561px. */
.hero-art { position: relative; width: 100%; max-width: 560px; margin-inline: auto }
.hero-art > svg { display: block; width: 100%; height: auto }
.hero-art > svg.ha-narrow { display: none }

/* Slip typography, in viewBox units, so it scales with the artwork: about 1.55x
   authored size on a 1440px desktop and about 1.12x on a 390px phone. */
.ha-code { font-family: var(--mono), ui-monospace, Menlo, Consolas, monospace; font-size: 11px; font-weight: 500; letter-spacing: .05em }
.ha-src  { font-family: var(--sans), -apple-system, "Segoe UI", system-ui, sans-serif; font-size: 9.5px; font-weight: 600; letter-spacing: .07em }
.ha-val  { font-family: var(--display), var(--serif), Georgia, serif; font-size: 34px; font-weight: 600; letter-spacing: -.03em }
.ha-unit { font-size: 17px; letter-spacing: -.01em }
.ha-lab  { font-family: var(--sans), -apple-system, "Segoe UI", system-ui, sans-serif; font-size: 11px; font-weight: 500 }
.ha-q    { font-family: var(--serif), Georgia, serif; font-size: 10.5px; font-style: italic }

.ha-cap {
  display: flex; gap: 12px; align-items: baseline;
  max-width: 560px; margin: 22px auto 0;
  font-family: var(--sans), -apple-system, "Segoe UI", system-ui, sans-serif;
  font-size: 13px; line-height: 1.55; color: var(--on-field-soft);
}
.ha-cap b {
  flex: none; font-family: var(--mono), ui-monospace, Menlo, Consolas, monospace;
  font-weight: 500; font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--signal);
}

/* A slow drift: five viewBox units deep over twenty-odd seconds, which is enough
   for the slips to read as floating above the field and not enough to move while
   anybody is reading them. Nothing at all for reduced-motion users — the rule
   only exists inside no-preference, so there is nothing to switch off. */
@media (prefers-reduced-motion: no-preference) {
  .ha-float { animation: ha-drift 21s ease-in-out infinite }
  .ha-float-2 { animation-duration: 26s; animation-delay: -7s }
  .ha-float-3 { animation-duration: 31s; animation-delay: -14s }
}
@keyframes ha-drift {
  0%, 100% { transform: translateY(0) }
  50% { transform: translateY(-5px) }
}

/* Phone: the narrow cut, two slips in a 300-unit box. See LAYOUTS. The caption
   drops its hanging label onto its own line so the sentence keeps a full measure. */
@media (max-width: 559px) {
  .hero-art > svg.ha-wide { display: none }
  .hero-art > svg.ha-narrow { display: block }
  .hero-art { max-width: 430px }
  .ha-cap { flex-direction: column; gap: 6px; margin-top: 18px }
}
/* ===================================================== FULL-WIDTH PAGES ===
   /figures/, /search/, /404 and the four trust pages are emitted inside the
   article layout: capped at the 68ch reading measure, with an empty 232px
   sidebar column parked beside them holding nothing. A figure gallery and a
   card grid both want the page. The measure is handed straight back to the
   elements that actually want it, which is the prose and nothing else. */

main .layout:has(> article > .hero) { display: block; }
main .layout:has(> article > .hero) > article { max-width: none; }
main .layout:has(> article > .hero) > article > * { max-width: var(--measure); }
main .layout:has(> article > .hero) > article
  > :is(.hero, .cards, .index-list, h2) { max-width: none; }
/* The gallery cards go wider than the reading measure but not to the full
   page: every drawn figure carries an inline max-width of 460px, authored so
   its 10px labels stay legible, and a 1,060px card around a 460px drawing is
   mostly empty card. This is the width where the plate looks like the point of
   it and the captions still set at a comfortable measure. */
main .layout:has(> article > .hero) > article > .fig-entry { max-width: 820px; }

/* ======================================================== SECTION HEADS ===
   An h2 on an article is a section of an argument and earns the rule above it.
   An h2 on an index page is a shelf label, and a hairline over every one of
   them was a large part of what "dated" described. A short warm bar instead —
   starting at --signal-ink, which clears 6.4:1 on paper, so the mark is visible
   before the gradient brightens it into --signal, which on paper is not. */

main > h2,
main .layout:has(> article > .hero) > article > h2 {
  border-top: 0; padding-top: 0;
  margin: clamp(44px, 5vw, 72px) 0 0.45em;
}
main > h2::before,
main .layout:has(> article > .hero) > article > h2::before {
  content: ""; display: block; width: 42px; height: 3px; margin-bottom: 18px;
  border-radius: var(--r-full);
  background: linear-gradient(90deg, var(--signal-ink), var(--signal));
}

/* ================================================= THE TOOL PAGE FIELD ===
   Seven pages that had no masthead. There is no .hero div to give them one and
   no wrapper to add, so the band is painted across the three elements the page
   does have — .kicker, h1, .deck — by the same mechanism .hero uses: a
   pseudo-element reaching 100vw past its own box, contained by the
   overflow-x: clip on <html>.

   Two constraints follow from painting one band as three boxes. The margins
   between them go to zero and become padding, or a stripe of paper shows
   through at each join. And the fill is flat --field with no gradient at all:
   a gradient is resolved against each box's own width, the three boxes are
   three different widths (the eyebrow is its own content, the h1 wraps at 18ch,
   the deck at 58ch), and the first draft of this drew two visible horizontal
   seams straight across the masthead. Flat colour has no geometry to disagree
   about, and a flat band of the brand indigo is what the page needed anyway.

   The eyebrow is a rule and a word rather than the pill .hero uses. A pill
   needs its own background, and an element's background paints under its
   negative-z-index pseudo-element, so the band would cover the pill. The rule
   costs nothing and the band is what matters. */

main .layout:has(> article > .tool) > article > :is(.kicker, h1, .deck) {
  position: relative; isolation: isolate;
  max-width: none;
}
main .layout:has(> article > .tool) > article > :is(.kicker, h1, .deck)::after {
  content: "";
  position: absolute; z-index: -2; pointer-events: none;
  /* One pixel of overlap at each join. The three boxes abut exactly — measured
     at 165.65 and 354.99 — but they abut on a FRACTIONAL pixel, so Chrome
     antialiases both edges against the page behind and draws a hairline across
     the masthead at each seam. Overlapping removes the shared edge entirely. */
  top: -1px; bottom: -1px; left: -100vw; right: -100vw;
  background-color: var(--field);
}
main .layout:has(> article > .tool) > article > .kicker {
  display: flex; align-items: center; gap: 10px;
  width: -moz-max-content; width: max-content; max-width: 100%;
  margin: 0; padding: clamp(30px, 4vw, 54px) 0 0;
  color: var(--signal); letter-spacing: 0.13em;
}
main .layout:has(> article > .tool) > article > .kicker::before {
  content: ""; flex: none; width: 22px; height: 2px;
  border-radius: var(--r-full); background: var(--signal);
}
main .layout:has(> article > .tool) > article > h1 {
  margin: 0; padding: 18px 0 0;
  font-size: var(--t-display-2); line-height: 1.02; letter-spacing: -0.034em;
  color: var(--on-field); max-width: 18ch;
}
main .layout:has(> article > .tool) > article > .deck {
  margin: 0 0 clamp(30px, 4vw, 48px);
  padding: 14px 0 clamp(34px, 4.4vw, 60px);
  color: var(--on-field-soft); font-weight: 400; font-size: 1.06em;
  line-height: 1.6; max-width: 58ch;
}
/* Every tool has an intent line today. If one ever ships without, the h1 has to
   close the band itself rather than ending it flush against its own baseline. */
main .layout:has(> article > .tool) > article > h1:not(:has(+ .deck)) {
  padding-bottom: clamp(34px, 4.4vw, 60px);
  margin-bottom: clamp(30px, 4vw, 48px);
}
main .layout:has(> article > .tool) > article > .kicker :focus-visible,
main .layout:has(> article > .tool) > article > .deck :focus-visible {
  outline-color: var(--signal);
}

/* ================================================== THE TOOL'S ANSWER =====
   The answer — the thing the reader came for — is painted on the brand colour,
   which makes it the second field on the page and impossible to mistake for
   the prose around it.

   Not touched, deliberately: fieldset, legend, the inputs, .choices and the
   buttons. Three tools declare their own <fieldset> and <legend> and style them
   through a .tool-<slug> prefix, and an override here outranks that on element
   count. A first draft filled the legend as an accent pill and it landed on top
   of blood-tests' and receding-or-maturing's own numbered legends, dark on
   dark. The shared controls are TOOL_CSS's to change and a tool's own controls
   are the tool's; what is left below is the part no tool restyles. */

main .tool .result {
  border: 0; border-radius: var(--r);
  padding: clamp(22px, 2.6vw, 30px) clamp(22px, 2.6vw, 32px);
  color: var(--on-field);
  background-color: var(--field);
  background-image:
    radial-gradient(110% 130% at 88% 0%, var(--field-glow), transparent 62%),
    linear-gradient(150deg, var(--field-2) 0%, var(--field) 58%);
}
main .tool .result :is(h2, h3) {
  border-top: 0; padding-top: 0; color: var(--on-field);
}
main .tool .result p { color: var(--on-field-soft); }
main .tool .result strong, main .tool .result b { color: var(--on-field); }
main .tool .result a { color: var(--signal); }
main .tool .result :focus-visible { outline-color: var(--signal); }
main .tool .result .readout {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(2rem, 3.4vw, 2.75rem); line-height: 1;
  letter-spacing: -0.04em; color: var(--signal);
}
main .tool .result .readout .unit { color: var(--on-field-soft); }
main .tool .result .src { color: var(--on-field-soft); }

main .tool .flag {
  border: 0; border-left: 4px solid var(--signal);
  border-radius: var(--r-sm);
  background: var(--signal-tint); color: var(--signal-ink);
}
main .tool .flag strong { color: var(--signal-ink); }

main .tool-foot {
  margin-top: 36px; padding: 22px 24px;
  border-top: 0; border-radius: var(--r);
  background: var(--sunken);
}

/* ============================================================== FIGURES ==
   Eleven diagrams that were eleven blocks under eleven hairlines. Each is now a
   sunken card holding a paper plate: two real surfaces, no border and no blur,
   which is where the depth in this redesign comes from everywhere else.

   The plate stays --paper specifically. Several of these figures fill shapes
   with var(--paper) to mean "bare scalp" — a cut-out that only reads as a
   cut-out while the ground behind it is the same paper. Putting the plate on
   --surface would turn every one of those into a visible pale blob. */

main .fig-entry {
  margin: 0 0 clamp(24px, 3vw, 38px);
  padding: clamp(18px, 2vw, 28px);
  border: 0; border-bottom: 0;
  border-radius: var(--r-lg);
  background: var(--sunken);
}
main .fig-entry > h2 {
  border-top: 0; padding-top: 0; margin: 0 0 16px;
}
main .fig-entry > h2::before { content: none; }
main .fig-entry figure.chart.figure-drawn {
  margin: 0 0 14px;
  padding: clamp(14px, 1.8vw, 22px) clamp(8px, 1.4vw, 18px);
  background: var(--paper);
  border-radius: var(--r);
  /* The plate is separated from the card by tone alone, and in dark that tone
     gap is --paper on --sunken: 1.05:1. Measured, and not enough to see. This
     is --ring's job — a surface edge, not a decorative hairline — and it is the
     one place in this file where a border earns its keep. */
  box-shadow: var(--ring);
}
main .fig-entry figure.chart figcaption { max-width: 80ch; }
main .fig-entry .fine { margin: 0; max-width: 80ch; }

/* The embed offer. A control, so it looks like one rather than like a line of
   small print with a triangle in front of it. */
main details.embed { margin: 14px 0 0; padding: 0; border-top: 0; }
main details.embed > summary {
  background: var(--surface); color: var(--ink-soft);
  border-radius: var(--r-full); box-shadow: var(--ring);
  padding: 7px 16px;
  width: -moz-max-content; width: max-content; max-width: 100%;
}
main details.embed[open] > summary { margin-bottom: 10px; }
main details.embed textarea {
  background: var(--surface); border: 0;
  box-shadow: var(--ring); border-radius: var(--r-sm);
}

/* ============================================================= RESEARCH ==
   The PubMed listing arrived built to the old system and inlines its own
   stylesheet, so it kept an accent-tinted card where every other page now has
   the field. This gives it the same masthead — the identical ::before / ::after
   pair .hero uses, so the two are the same band and not two attempts at one —
   and moves its four counters onto the instrument-panel language the home page
   uses on the field. Nothing else about the page is touched: the listing, the
   warning and the saved queries are its own and they are good. */

main .rsrch .rs-hero {
  position: relative; isolation: isolate;
  border: 0; border-radius: 0;
  background: none;
  color: var(--on-field);
  margin: 0 0 clamp(32px, 4vw, 52px);
  padding: clamp(30px, 4vw, 54px) 0 clamp(34px, 4.4vw, 60px);
}
main .rsrch .rs-hero::before {
  content: "";
  position: absolute; z-index: -2; pointer-events: none;
  top: 0; bottom: 0; left: -100vw; right: -100vw;
  background-color: var(--field);
  background-image:
    radial-gradient(110% 130% at 82% 0%, var(--field-glow), transparent 62%),
    radial-gradient(90% 110% at 0% 100%, var(--field-warm), transparent 60%),
    linear-gradient(158deg, var(--field-2) 0%, var(--field) 58%, var(--field) 100%);
}
main .rsrch .rs-hero::after {
  content: "";
  position: absolute; z-index: -1; pointer-events: none;
  top: 0; bottom: 0; left: -100vw; right: -100vw;
  background-image:
    linear-gradient(to right, var(--field-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--field-line) 1px, transparent 1px);
  background-size: 84px 84px;
  opacity: .55;
  -webkit-mask-image: radial-gradient(120% 130% at 50% 0%, var(--mask-on) 6%, transparent 74%);
          mask-image: radial-gradient(120% 130% at 50% 0%, var(--mask-on) 6%, transparent 74%);
}
main .rsrch .rs-kicker {
  display: inline-flex; align-items: center; gap: 9px;
  margin: 0 0 20px; padding: 6px 14px;
  border-radius: var(--r-full);
  background: var(--field-tint);
  box-shadow: inset 0 0 0 1px var(--field-edge);
  color: var(--signal); font-size: var(--t-micro); letter-spacing: 0.11em;
}
main .rsrch .rs-kicker::before {
  content: ""; width: 6px; height: 6px; flex: none;
  border-radius: 50%; background: var(--signal);
}
main .rsrch .rs-hero h1 {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-display-2); line-height: 1.02; letter-spacing: -0.034em;
  color: var(--on-field); max-width: 18ch; margin: 0 0 18px;
}
main .rsrch .rs-hero h1 em {
  font-style: normal; color: var(--signal); text-decoration: none;
}
main .rsrch .rs-deck { color: var(--on-field-soft); max-width: 58ch; }
main .rsrch .rs-fetched { color: var(--on-field-soft); }
main .rsrch .rs-hero a { color: var(--signal); }
main .rsrch .rs-hero :focus-visible { outline-color: var(--signal); }
main .rsrch .rs-stats {
  border: 0; border-radius: var(--r); overflow: hidden;
  background: var(--field-tint-2); gap: 1px;
  margin: clamp(28px, 3.6vw, 44px) 0 0;
}
main .rsrch .rs-stats > div { background: var(--field-tint); padding: 18px 18px 16px; }
main .rsrch .rs-stats dt { color: var(--on-field-soft); }
main .rsrch .rs-stats dd {
  font-family: var(--display); font-weight: 700;
  letter-spacing: -0.03em; color: var(--on-field);
}

/* The body of the page, onto the same surfaces as everything else. */
main .rsrch .rs-banner {
  border: 0; border-left: 4px solid var(--accent);
  border-radius: var(--r-sm); background: var(--sunken);
}
main .rsrch .rs-banner.rs-bad {
  border-left-color: var(--signal); background: var(--signal-tint);
}
main .rsrch .rs-banner.rs-bad p { color: var(--signal-ink); }
main .rsrch .rs-warn {
  border: 0; border-radius: var(--r-lg); background: var(--sunken);
}
main .rsrch .rs-warn li { border-left-color: var(--signal); }
main .rsrch .rs-listing-head { border-bottom: 3px solid var(--signal); }
main .rsrch .rs-item {
  border-radius: var(--r-sm); padding: 20px 12px;
}
main .rsrch .rs-item:hover { background: var(--surface); box-shadow: var(--e1); }
main .rsrch .rs-type {
  border: 0; border-radius: var(--r-full);
  background: var(--signal-tint); color: var(--signal-ink);
}
main .rsrch .rs-topic { border-radius: var(--r-full); }

/* The 12px floor on /research/. lib/research.mjs sets these at 11 and 11.5px
   and its sheet is INLINED into the page head, so it lands after the linked
   stylesheet and wins any tie — the extra "main" is what carries these over it,
   which is the same reason every rule in this block has one.

   Only the size changes. .rs-id and .rs-topic keep the 24px min-height their own
   file argues for in a comment; that is a live disagreement with this pass's
   44px brief and is written up in the report rather than settled here. */
main .rsrch .rs-stats dt,
main .rsrch .rs-note,
main .rsrch .rs-type,
main .rsrch .rs-id,
main .rsrch .rs-topic,
main .rsrch .rs-qn { font-size: 12px; }
main .rsrch .rs-queries { border-top: 3px solid var(--signal); }
main .rsrch .rs-q {
  border: 0; border-radius: var(--r);
  background: var(--surface); box-shadow: var(--e1), var(--ring);
}
main .rsrch .rs-term {
  border: 0; border-radius: var(--r-sm); background: var(--sunken);
}

/* =============================================================== SEARCH ==
   The header's search box belongs to the search module and is fine. This is
   /search/'s own form, which sits directly under the field and was still a
   hairline rectangle. */

main .rgs-pform label { color: var(--ink); font-size: var(--t-sm); }
main .rgs-pin {
  background: var(--surface); border: 0;
  box-shadow: inset 0 0 0 1px var(--rule-firm);
  border-radius: var(--r-full); padding-inline: 20px; min-height: 50px;
}
main .rgs-pgo {
  border-radius: var(--r-full); padding: 0 26px; min-height: 50px;
}
/* 11.5px, and it is the live region that tells a screen-reader user and a
   sighted user how many results they got — on /search/ and on the 404. */
main .rgs-pcount { font-size: 12px; }
main .rgs-noscript, main .rgs-pnone {
  background: var(--sunken); border: 0; border-radius: var(--r);
  padding: 18px 20px; color: var(--ink-soft);
}

/* ================================================================ PHONE == */

@media (max-width: 620px) {
  main .fig-entry { border-radius: var(--r); padding: 14px; }
  main .fig-entry figure.chart.figure-drawn { border-radius: var(--r-sm); padding: 12px 8px 0; }
  main .tool-foot { padding: 18px 18px 20px; }
  main .rsrch .rs-item { padding-inline: 6px; }
  main > h2::before,
  main .layout:has(> article > .hero) > article > h2::before { margin-bottom: 14px; }
}
/* ================================================================ PRINT ===
   Three of the surfaces in this file are painted fields — the tool masthead,
   the tool's answer panel and the /research/ masthead — and a browser prints
   with backgrounds off, which would leave their --on-field text on white paper.
   --print-ink and --print-soft come from lib/theme.mjs and are constant across
   all three theme states, because a reader whose OS is dark still prints white. */
@media print {
  main .layout:has(> article > .tool) > article > :is(.kicker, h1, .deck),
  main .rsrch .rs-hero,
  main .rsrch .rs-hero :is(h1, h1 em, .rs-kicker, .rs-deck, .rs-fetched, a),
  main .rsrch .rs-stats > div,
  main .rsrch .rs-stats :is(dt, dd) {
    background: none; box-shadow: none; color: var(--print-ink);
    margin-inline: 0; padding-inline: 0; border-radius: 0;
  }
  main .layout:has(> article > .tool) > article > .deck,
  main .rsrch .rs-hero :is(.rs-deck, .rs-fetched),
  main .rsrch .rs-stats dt { color: var(--print-soft); }
  main .layout:has(> article > .tool) > article > .kicker::before,
  main .rsrch .rs-hero::before, main .rsrch .rs-hero::after,
  main .rsrch .rs-kicker::before { display: none; }
  main .tool .result {
    background: none; color: var(--print-ink);
    border: 1px solid var(--rule-firm); break-inside: avoid;
  }
  main .tool .result :is(h2, h3, strong, b, a) { color: var(--print-ink); }
  main .tool .result p, main .tool .result .src { color: var(--print-soft); }
  main .tool .result .readout { color: var(--print-ink); }
  main .fig-entry, main .rsrch .rs-item { background: none; break-inside: avoid; }
}
/* ============================================================== TOKENS === */
/* Constant across themes by design: the band is a dark field in light mode and
   in dark mode, the way the chosen direction's hero is. Redeclared in both dark
   blocks anyway, so no colour has its only definition inside a media query. */
:root {
  /* The theme's --display is currently an alias of --sans, because only Archivo,
     Literata and IBM Plex Mono are self-hosted and no display serif exists to
     point it at. A reading page is the one place where that costs something:
     Examine sets its h1 in Lora, Mayo in a bespoke serif, and the whole argument
     of a reference work is carried by the difference between a title face and an
     interface face. So the article's own display face is the text serif at 600 —
     Literata holds up at 54px — while h3, labels and every control stay Archivo.
     One line to change if the theme ever ships a real display face:
     var(--display, var(--serif)) restores the alias. */
  --art-display:      var(--serif);
  --art-field:        var(--field);
  --art-on-field:     var(--on-field);
  --art-on-field-soft:var(--on-field-soft);
  --art-signal:       var(--signal);
  /* text-weight amber and its tint. --data and --data-bg already flip per theme,
     so these need no override of their own. */
  --art-hot:          var(--signal-ink);
  --art-tint:         var(--signal-tint);

  --art-measure: 61ch;
  --art-r:  14px;
  --art-rs: 10px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --art-field:        var(--field);
    --art-on-field:     var(--on-field);
    --art-on-field-soft:var(--on-field-soft);
    --art-signal:       var(--signal);
  }
}
:root[data-theme="dark"] {
  --art-field:        var(--field);
  --art-on-field:     var(--on-field);
  --art-on-field-soft:var(--on-field-soft);
  --art-signal:       var(--signal);
}

/* ========================================================== THE COLUMN === */
/* 61ch at 21px Literata is 744px and 65 real characters. Scoped to the layout's
   own article so the <article class="tc-card"> elements a tool nests inside
   itself keep their own width. */
.layout > article {
  max-width: var(--art-measure);
  font-size: 21px;
  line-height: 1.7;
}
/* Below the sticky-contents breakpoint the column was pinned left with up to
   225px of dead space beside it. */
@media (max-width: 1079px) { .layout > article { margin-inline: auto; } }
@media (max-width: 620px)  { .layout > article { font-size: 18.5px; line-height: 1.66; } }

.layout > article p { margin: 0 0 1.1em; }

/* ============================================================ THE HEAD === */
/* One field made of four sibling boxes. They must not have vertical margins or
   the paper shows through between them as a stripe. */
.layout > article > .crumbs,
.layout > article > .kicker,
.layout > article > h1,
.layout > article > .lede,
.layout > article > h1 + .deck {
  background: var(--art-field);
  color: var(--art-on-field);
  margin-block: 0;
  /* The bleed is the theme's own gutter, so the band's text keeps the same left
     edge as the wordmark above it. The fallback matters: if --pad is ever
     renamed, calc() on an undefined variable is invalid at computed-value time
     and the whole band silently loses its bleed with no other symptom. */
  margin-inline: calc(var(--pad, 24px) * -1);
  padding-inline: var(--pad, 24px);
  /* Four boxes stacked at fractional y positions antialias their own edges, and
     two half-covered edge pixels do not add up to one opaque one: the band came
     out with three hairline seams across it. Each member paints one extra pixel
     of its own background below itself, which the next member then covers. */
  box-shadow: 0 1px 0 var(--art-field);
}
/* first member: crumbs on a guide, the kicker on a tool */
.layout > article > .crumbs,
.layout > article > .kicker:first-child {
  padding-top: 30px;
  border-radius: var(--art-r) var(--art-r) 0 0;
  box-shadow: inset 0 4px 0 var(--art-signal), 0 1px 0 var(--art-field);
}
/* last member: the byline on a guide, the deck on a tool. Kept in its own rule,
   away from the :has() variant below — one invalid selector invalidates the
   whole list, so a browser without :has() would otherwise lose the band's bottom
   padding and rounded corners rather than just the h1-only case. */
.layout > article > .lede,
.layout > article > h1 + .deck {
  padding-bottom: 30px;
  border-radius: 0 0 var(--art-r) var(--art-r);
  margin-bottom: 36px;
  box-shadow: none;   /* nothing below this one to seam against */
}
/* and the shape with neither: a bare title closes the band itself */
.layout > article > h1:not(:has(+ .lede, + .deck)) {
  padding-bottom: 30px;
  border-radius: 0 0 var(--art-r) var(--art-r);
  margin-bottom: 36px;
  box-shadow: none;
}
@media (max-width: 719px) {
  /* full bleed on a phone: --pad and main's own padding are the same value, so
     the negative margin lands exactly on the viewport edge */
  .layout > article > .crumbs,
  .layout > article > .kicker:first-child,
  .layout > article > .lede,
  .layout > article > h1 + .deck { border-radius: 0; }
  .layout > article > h1:not(:has(+ .lede, + .deck)) { border-radius: 0; }
}

.layout > article > .crumbs { font-size: 13px; }
/* 38px tall on a phone. inline-flex rather than padding so the crumb separators,
   which are ::before on the li, stay on the text baseline. */
.layout > article > .crumbs a { color: var(--art-on-field-soft); display: inline-flex; align-items: center; min-height: 44px; }
.layout > article > .crumbs a:hover { color: var(--art-signal); }
.layout > article > .crumbs li + li::before { color: var(--art-on-field-soft); opacity: 0.5; }
.layout > article > .crumbs [aria-current="page"] { color: var(--art-on-field); }

/* The theme's "article > p:first-of-type { font-size: 1.06em }" was written for
   the opening paragraph of the body, but on all 79 guides and all 7 tools the
   first <p> child of <article> is the category kicker — so the rule has been
   setting an 11px mono label at 20.14px instead. Restated here at the size it
   was always meant to be. */
.layout > article > p.kicker {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--art-signal);
  padding-top: 16px;
}
.layout > article > p.kicker a { color: inherit; }
.layout > article > p.kicker a:hover { color: var(--art-on-field); }

.layout > article h1 {
  font-family: var(--art-display);
  font-weight: 600;
  font-size: clamp(2.15rem, 5.2vw, 3.4rem);
  line-height: 1.03;
  letter-spacing: -0.028em;
  text-wrap: balance;
}
.layout > article > h1 { color: var(--art-on-field); padding-top: 12px; margin-bottom: 0; }

.layout > article > .lede {
  font-family: var(--sans);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--art-on-field-soft);
  padding-top: 18px;
}
.layout > article > .lede .dot { color: var(--art-signal); opacity: 0.75; }

/* A tool's intent line, closing the band.
   No max-width: this element IS the bottom of the band, so limiting its width
   limits the painted box and leaves a step cut out of the band's bottom-right
   corner. The measure is shortened with padding instead, which shortens the line
   without narrowing the field. */
.layout > article > h1 + .deck {
  font-family: var(--sans);
  font-weight: 400;
  font-size: clamp(1rem, 1.6vw, 1.14rem);
  line-height: 1.5;
  color: var(--art-on-field-soft);
  padding-top: 16px;
  max-width: none;   /* DECK_CSS caps it at 46ch, which cuts the band */
}
@media (min-width: 720px) {
  .layout > article > h1 + .deck { padding-right: 26%; }
}

/* The structural accent is a navy; a focus ring drawn in it on a navy field is
   invisible. Inside the band the ring is the signal amber, 8.27:1 on the field. */
.layout > article > .crumbs a:focus-visible,
.layout > article > .kicker a:focus-visible {
  outline: 2px solid var(--art-signal);
  outline-offset: 3px;
}

/* ====================================================== KEY-FACTS SHELF === */
/* Five guides carry a verified strip. Where one follows the byline it is pulled
   up so it overlaps the band and reads as a lit shelf rather than a third box
   in a stack; the extra padding underneath the byline makes room for it. */
.layout > article > .lede:has(+ aside.keyfacts) { padding-bottom: 58px; margin-bottom: 0; }
/* position, so the strip paints over the band it is pulled into rather than
   under it — an in-flow block loses to any positioned sibling, whatever the
   document order. */
.layout > article > .lede + aside.keyfacts { margin-top: -34px; position: relative; }

aside.keyfacts {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-top: 0;
  border-radius: var(--art-r);
  padding: 22px 24px 18px;
  margin: 0 0 34px;
  box-shadow:
    inset 0 3px 0 var(--art-hot),
    0 16px 38px -20px color-mix(in srgb, var(--ink) 55%, transparent);
}
aside.keyfacts h2 {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--art-hot);
  margin: 0 0 16px;
}
.keyfacts ul { gap: 18px 26px; }
/* the label wraps to two lines on one tile and one on the next, which left the
   guide codes on three different baselines */
.keyfacts li { display: flex; flex-direction: column; }
.kf-v {
  font-family: var(--mono);
  font-size: 1.6rem;
  font-weight: 500;
  line-height: 1.05;
  color: var(--ink);
  margin: 0 0 6px;
}
.kf-u { font-size: 0.52em; color: var(--art-hot); margin-left: 3px; }
.kf-l { font-family: var(--sans); font-size: 13.5px; line-height: 1.4; color: var(--ink-soft); margin: 0 0 6px; flex: 1 1 auto; }
/* Scoped to .keyfacts, not bare .kf-s: lib/ux/enhancements.mjs ships its own
   copy of .kf-s at 10.5px, and build.mjs emits the UX sheets AFTER this
   one, so a bare .kf-s here loses the tie and the guide code stayed at 10.5px.
   One extra class is enough to win it without an !important. */
.keyfacts .kf-s { font-family: var(--mono); font-size: 12px; letter-spacing: 0.09em; color: var(--muted); margin: 0; }
.kf-note {
  font-family: var(--sans); font-size: 12.5px; line-height: 1.5; color: var(--muted);
  margin: 16px 0 0; padding-top: 14px; border-top: 1px solid var(--rule);
}

/* ============================================================= THE BODY === */
/* Section heads take the display serif. The full-width hairline stays — a guide
   has thirteen of these and they need real separation — and the amber block
   sitting on it is the homepage's section rule, repeated down the page.
   Direct children only, so the summary, the strip, the references, the
   disclaimer and the "More in" list keep their own smaller heads. */
.layout > article > h2 {
  font-family: var(--art-display);
  font-weight: 600;
  font-size: clamp(1.55rem, 2.7vw, 2rem);
  line-height: 1.16;
  letter-spacing: -0.022em;
  color: var(--ink);
  margin: 2.5em 0 0.5em;
  padding-top: 26px;
  border-top: 1px solid var(--rule);
  position: relative;
  text-wrap: balance;
}
.layout > article > h2::before {
  content: "";
  position: absolute;
  top: -2px; left: 0;
  width: 46px; height: 3px;
  background: var(--art-hot);
  border-radius: 2px;
}
.layout > article > h2:first-of-type { margin-top: 1.6em; }

.layout > article > h3 {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 1.02em;
  letter-spacing: 0.01em;
  line-height: 1.35;
  color: var(--ink);
  margin: 2em 0 0.45em;
}
.layout > article > h4 { margin: 1.7em 0 0.3em; }

/* A link inside prose: the underline is quiet until it is wanted, so a paragraph
   with six internal links does not read as a fence. */
.layout > article p a,
.layout > article li a,
.layout > article td a {
  text-decoration-color: color-mix(in srgb, currentColor 38%, transparent);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color .14s;
}
.layout > article p a:hover,
.layout > article li a:hover,
.layout > article td a:hover { text-decoration-color: currentColor; }

.layout > article > ul, .layout > article > ol { margin: 0 0 1.25em; padding-left: 1.3em; }
.layout > article > ul > li, .layout > article > ol > li { margin-bottom: 0.4em; padding-left: 0.15em; }
.layout > article > ul > li::marker { color: var(--art-hot); }
.layout > article > ol > li::marker { font-family: var(--mono); font-size: 0.85em; color: var(--art-hot); }
.layout > article li > strong:first-child { color: var(--ink); font-weight: 600; }

/* :not([class]) — a tool embedded in a guide (finasteride-minoxidil-together
   carries the shedding check) draws its own quote as a classed <blockquote>, and
   restyling that would overwrite a tool module's own design. Only the four
   markdown blockquotes in the corpus are unclassed. */
.layout > article blockquote:not([class]) {
  margin: 1.9em 0;
  padding: 18px 24px;
  border-left: 3px solid var(--art-hot);
  border-radius: 0 var(--art-rs) var(--art-rs) 0;
  background: var(--raised);
  color: var(--ink-soft);
  font-style: italic;
  font-size: 1.02em;
}
.layout > article blockquote:not([class]) p:last-child { margin-bottom: 0; }

/* =============================================================== IN SHORT === */
/* Warm tint rather than the blue wash, and the label as a filled navy chip:
   amber text on the amber tint is 4.28:1 and would have failed at 11px. */
aside.summary {
  background: var(--art-tint);
  border: 0;
  border-radius: var(--art-r);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--art-hot) 26%, transparent);
  padding: 26px 28px 8px;
  margin: 0 0 40px;
}
aside.summary h2 {
  display: inline-block;
  background: var(--art-field);
  color: var(--art-on-field);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 6px 13px 5px;
  border-radius: 999px;
  margin: 0 0 16px;
}
aside.summary p { font-size: 1.01em; color: var(--ink); }
aside.summary ul { font-size: 1em; color: var(--ink); }
aside.summary li::marker { color: var(--art-hot); }

/* The guide's standfirst. The markdown puts it below the strip and the mobile
   contents rather than under the title, so it is set as a lead-in to the
   summary that follows it, not as a subtitle competing with the h1. */
.layout > article > .deck {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.16em;
  line-height: 1.45;
  color: var(--ink-soft);
  max-width: 40ch;
  margin: 0 0 26px;
}

/* ================================================================ TABLES === */
/* 58 of the 79 guides carry one. The header row is the second place the brand
   colour appears at size on a reading page. */
.layout > article .scroll {
  margin: 2.1em 0;
  border: 1px solid var(--rule);
  border-radius: var(--art-rs);
}
.layout > article .scroll table { font-size: 15.5px; }
.layout > article .scroll thead th {
  background: var(--art-field);
  color: var(--art-on-field);
  border-bottom: 0;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.09em;
  padding: 13px 14px;
}
.layout > article .scroll tbody tr:nth-child(even) { background: color-mix(in srgb, var(--art-tint) 42%, transparent); }
.layout > article .scroll td, .layout > article .scroll tbody th { padding: 12px 14px; }
.layout > article .scroll tbody th { color: var(--ink); }

/* =============================================================== FIGURES === */
/* Everything below is fenced above 561px so that FIGURE_MOBILE_CSS keeps the
   pannable box it gives a drawn figure on a phone. */
@media (min-width: 561px) {
  .layout > article figure.chart {
    margin: 2.4em 0;
    padding: 20px 22px 18px;
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--art-r);
  }
  .layout > article figure.chart::before {
    content: "Figure";
    display: block;
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--art-hot);
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--rule);
  }
  .layout > article figure.chart figcaption {
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px solid var(--rule);
  }
  /* the gallery gives every entry its own h2, so the plate label is redundant
     there and only there */
  .fig-entry figure.chart::before { display: none; }
}
.layout > article figure.chart figcaption { font-size: 14px; line-height: 1.55; color: var(--muted); }
.layout > article figure.chart figcaption b { color: var(--ink); font-weight: 600; }
.layout > article figure.chart details.embed { border-top-color: var(--rule); }

/* ================================================================== Q&A === */
/* 608 pairs across 76 guides, and the part of a guide a reader scans rather
   than reads. Each pair becomes its own card so eight in a row are eight
   answers rather than one grey block. */
.qa {
  margin: 0;
  padding: 18px 20px 16px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rule-firm);
  border-radius: var(--art-rs);
  transition: border-left-color .15s;
}
.qa + .qa { margin-top: 10px; }
.qa:hover { border-left-color: var(--art-hot); }
.qa > h3.q {
  font-family: var(--art-display);
  font-size: 1.12em;
  font-weight: 600;
  line-height: 1.28;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0 0 8px;
}
.qa > p { font-size: 0.96em; color: var(--ink-soft); }

/* ========================================================== END MATTER === */
.layout > article > section.refs {
  margin-top: 3.4em;
  padding-top: 26px;
  border-top: 3px solid var(--rule-firm);
}
.layout > article > section.refs > h2 {
  font-family: var(--art-display);
  font-weight: 600;
  font-size: 1.4rem;
  letter-spacing: -0.02em;
  color: var(--ink);
  border: 0; padding: 0; margin: 0 0 16px;
}
ol.reflist { font-size: 14.5px; line-height: 1.55; padding-left: 1.9em; }
ol.reflist li { margin-bottom: 0.6em; }
ol.reflist li::marker { font-family: var(--mono); font-size: 12px; color: var(--art-hot); }

.layout > article > section.disclaimer {
  margin-top: 2.4em;
  padding: 20px 22px 6px;
  background: var(--raised);
  border-radius: var(--art-rs);
}
.layout > article > section.disclaimer > h2 {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  border: 0; padding: 0; margin: 0 0 10px;
}
.fine { font-size: 14px; line-height: 1.65; }

/* "More in <category>" — the last thing on 79 pages, and the only thing offered
   after 3,000 words. */
.layout > article > section:not(.refs):not(.disclaimer) > h2 {
  font-family: var(--art-display);
  font-weight: 600;
  font-size: 1.4rem;
  letter-spacing: -0.02em;
  border: 0; padding: 0; margin: 3em 0 6px;
}
.layout > article .index-list a { padding: 16px 12px 16px 0; border-radius: var(--art-rs); transition: background .14s, padding .14s; }
.layout > article .index-list a:hover { background: var(--raised); padding-inline: 12px; }
.layout > article .index-list .t { font-family: var(--art-display); font-weight: 600; font-size: 1.06rem; letter-spacing: -0.015em; }

/* ============================================================== CONTENTS === */
@media (min-width: 1080px) {
  .toc { top: 96px; font-size: 14px; max-height: calc(100vh - 140px); }
  .toc h2 { font-size: 12px; letter-spacing: 0.16em; color: var(--art-hot); margin-bottom: 14px; }
  .toc ol { border-left: 2px solid var(--rule); }
  .toc a {
    padding: 7px 0 7px 16px; margin-left: -2px;
    border-left: 2px solid transparent; color: var(--muted); line-height: 1.35;
    transition: color .12s, border-color .12s;
  }
  .toc a:hover { color: var(--ink); border-left-color: var(--rule-firm); }
  /* nav.toc, not .toc: lib/ux/enhancements.mjs sets .toc a.is-here to the
     structural accent and its sheet is concatenated after every theme sheet in
     build.mjs, so an equal-specificity rule here silently lost and the active
     entry kept a blue rail instead of the amber one. One element name settles
     it, and the element really is a <nav>. */
  nav.toc a.is-here { color: var(--ink); font-weight: 600; border-left-color: var(--art-hot); }
}
@media (max-width: 1079px) {
  .toc-mobile { border-radius: var(--art-rs); background: var(--surface); margin: 0 0 30px; }
  .toc-mobile > summary { font-size: 14.5px; color: var(--ink); }
  .toc-mobile > summary::after { border-color: var(--art-hot); }
  .toc-mobile > summary .n { letter-spacing: 0.06em; }
  .toc-mobile a { font-size: 15px; padding: 4px 0; }
}

/* ============================================================ FURNITURE === */
/* Filled rather than outlined: at the foot of a 3,400-word page this is the one
   control on screen, and it now carries the brand colour instead of a hairline. */
/* button.totop, for the same reason as nav.toc above: the enhancements sheet
   loads last and its outlined white pill was winning the tie, so this filled
   navy never reached the page. */
button.totop {
  background: var(--art-field);
  color: var(--art-on-field);
  border-color: transparent;
  box-shadow: 0 8px 22px -8px color-mix(in srgb, var(--ink) 60%, transparent);
}
button.totop:hover { color: var(--art-signal); border-color: transparent; }
/* The ring sits 2px OUTSIDE the button, which puts it on --paper, and the amber
   is 1.89:1 there — a focus indicator that fails 3:1. The signal is only ever
   legible on the field, and this button is the one field-coloured thing sitting
   on paper. So the ring takes the structural accent, 8.5:1 on paper, which is
   what every other focusable thing on this site already uses. */
button.totop:focus-visible { outline: 2.5px solid var(--accent); outline-offset: 2px; }

/* Print drops backgrounds, so the band disappears and its --on-field text would
   land near-white on white paper. --print-ink rather than --ink because a reader
   whose OS is in dark mode still prints on white: --ink is #E9E6E0 there. */
@media print {
  .layout > article > .crumbs,
  .layout > article > .kicker,
  .layout > article > h1,
  .layout > article > .lede {
    background: transparent; color: var(--print-ink);
    margin-inline: 0; padding-inline: 0; box-shadow: none; border-radius: 0;
  }
  /* p.kicker, not .kicker: the screen rule that sets the eyebrow amber names the
     element too, and amber on white paper is 2.2:1. */
  .layout > article > p.kicker,
  .layout > article > .crumbs a,
  .layout > article > .crumbs,
  .layout > article > .lede { color: var(--print-soft); }
  .layout > article > h1::before, .layout > article > .crumbs::before { display: none; }
  button.totop { display: none; }
  aside.keyfacts { margin-top: 0; break-inside: avoid; }
  .qa, figure.chart, .summary { break-inside: avoid; }
}

/* ---------------------------------------------------------------------------
   The wrapper reconciliation.

   This file styles the article masthead as banded SIBLINGS: a child-combinator
   chain from .layout to article to .crumbs, .kicker, h1 and .lede, each painting
   the same background so they read as one block. lib/theme.mjs, written in
   parallel by a different agent, styles it as a WRAPPER, .hero.article, and
   asked the build to emit that. The build emits the wrapper, so every sibling
   selector above stops matching at its child combinator and silently does
   nothing.

   (Written without backticks on purpose: this comment lives inside a template
   literal, and a backtick here ends the stylesheet mid-sentence.)

   The band itself still renders, because theme.mjs paints it. What did not
   survive was this file's own work inside it — most visibly the breadcrumb's
   current-page span, which kept a paper ink (#3A3F49) on a dark field at about
   1.3:1. The links either side of it were correct, which is what makes this the
   kind of bug that ships: it looks styled.

   Rather than delete either agent's approach, the sibling rules keep working
   wherever the structure is flat, and these repeat them one level deeper.
   --------------------------------------------------------------------------- */

.hero.article > .crumbs,
.hero.tool > .crumbs { font-size: 13px; }
.hero.article > .crumbs a,
.hero.tool > .crumbs a {
  color: var(--art-on-field-soft, var(--on-field-soft));
  /* 44px, the same target the sibling rule set and the wrapper lost. Measured at
     38px on a 375px screen before this — a breadcrumb is a small target already
     and this is the one people reach for to go back up a level. */
  display: inline-flex; align-items: center; min-height: 44px;
}
.hero.article > .crumbs [aria-current],
.hero.tool > .crumbs [aria-current] {
  /* The one that was invisible. */
  color: var(--art-on-field-soft, var(--on-field-soft));
  opacity: 0.72;
}
.hero.article > .crumbs ol,
.hero.tool > .crumbs ol { flex-wrap: wrap; }
.hero.article > .kicker a,
.hero.tool > .kicker a { color: inherit; text-decoration: none; }
.hero.article > .kicker a:hover,
.hero.tool > .kicker a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ------------------------------------------------------------ search panel --
   The results dropdown is lib/ux/search.mjs's, and nobody claimed it in the
   redesign: it kept a 4px radius and a 1px hairline while every other card on
   the site moved to layered surfaces and a 12px radius, so the one component
   that opens over the new design was the one still drawn in the old one. Two
   class names, because that sheet is concatenated after this one. */
.bar .rgs-panel {
  border: 0; border-radius: var(--r);
  box-shadow: var(--e3), var(--ring);
}
.bar .rgs-hit { border-bottom-color: var(--rule); }
.bar .rgs-hit[aria-selected="true"] { background: var(--accent-bg); }
.bar .rgs-all { border-top-color: var(--rule); border-radius: 0 0 var(--r) var(--r); }

/* ------------------------------------------------------------------- print --
   Backgrounds are off by default in every browser's print path, so .hero::before
   stops painting and the band's --on-field foreground lands on white paper. That
   is an invisible headline on the home page, the eight indexes, /tools/,
   /figures/, /search/, the four trust pages and the 404. Print gets ink. */
@media print {
  html { scroll-padding-top: 0; }
  header.site { position: static; }
  .skip, .rgs, .toc, .toc-mobile { display: none !important; }
  .hero { color: var(--print-ink); padding-top: 0; }
  .hero::before, .hero::after { display: none; }
  .hero h1, .hero h1 em, .hero h2, .hero h3 { color: var(--print-ink); }
  .hero > p:not([class]), .hero .fine, .hero .lede { color: var(--print-soft); }
  .hero a { color: var(--print-ink); }
  .hero .lede .dot { color: var(--print-soft); }
  .hero .kicker {
    background: none; box-shadow: none; padding-inline: 0;
    color: var(--print-soft); letter-spacing: 0.1em;
  }
  .hero .kicker::before { background: var(--print-soft); }
  .stat, .card, .ask, figure.chart, .qa { break-inside: avoid; }
  .stat .v { color: var(--print-ink); }
}
/* ===================================================== FULL-WIDTH PAGES ===
   /figures/, /search/, /404 and the four trust pages are emitted inside the
   article layout: capped at the 68ch reading measure, with an empty 232px
   sidebar column parked beside them holding nothing. A figure gallery and a
   card grid both want the page. The measure is handed straight back to the
   elements that actually want it, which is the prose and nothing else. */

main .layout:has(> article > .hero) { display: block; }
main .layout:has(> article > .hero) > article { max-width: none; }
main .layout:has(> article > .hero) > article > * { max-width: var(--measure); }
main .layout:has(> article > .hero) > article
  > :is(.hero, .cards, .index-list, h2) { max-width: none; }
/* The gallery cards go wider than the reading measure but not to the full
   page: every drawn figure carries an inline max-width of 460px, authored so
   its 10px labels stay legible, and a 1,060px card around a 460px drawing is
   mostly empty card. This is the width where the plate looks like the point of
   it and the captions still set at a comfortable measure. */
main .layout:has(> article > .hero) > article > .fig-entry { max-width: 820px; }

/* ======================================================== SECTION HEADS ===
   An h2 on an article is a section of an argument and earns the rule above it.
   An h2 on an index page is a shelf label, and a hairline over every one of
   them was a large part of what "dated" described. A short warm bar instead —
   starting at --signal-ink, which clears 6.4:1 on paper, so the mark is visible
   before the gradient brightens it into --signal, which on paper is not. */

main > h2,
main .layout:has(> article > .hero) > article > h2 {
  border-top: 0; padding-top: 0;
  margin: clamp(44px, 5vw, 72px) 0 0.45em;
}
main > h2::before,
main .layout:has(> article > .hero) > article > h2::before {
  content: ""; display: block; width: 42px; height: 3px; margin-bottom: 18px;
  border-radius: var(--r-full);
  background: linear-gradient(90deg, var(--signal-ink), var(--signal));
}

/* ================================================= THE TOOL PAGE FIELD ===
   Seven pages that had no masthead. There is no .hero div to give them one and
   no wrapper to add, so the band is painted across the three elements the page
   does have — .kicker, h1, .deck — by the same mechanism .hero uses: a
   pseudo-element reaching 100vw past its own box, contained by the
   overflow-x: clip on <html>.

   Two constraints follow from painting one band as three boxes. The margins
   between them go to zero and become padding, or a stripe of paper shows
   through at each join. And the fill is flat --field with no gradient at all:
   a gradient is resolved against each box's own width, the three boxes are
   three different widths (the eyebrow is its own content, the h1 wraps at 18ch,
   the deck at 58ch), and the first draft of this drew two visible horizontal
   seams straight across the masthead. Flat colour has no geometry to disagree
   about, and a flat band of the brand indigo is what the page needed anyway.

   The eyebrow is a rule and a word rather than the pill .hero uses. A pill
   needs its own background, and an element's background paints under its
   negative-z-index pseudo-element, so the band would cover the pill. The rule
   costs nothing and the band is what matters. */

main .layout:has(> article > .tool) > article > :is(.kicker, h1, .deck) {
  position: relative; isolation: isolate;
  max-width: none;
}
main .layout:has(> article > .tool) > article > :is(.kicker, h1, .deck)::after {
  content: "";
  position: absolute; z-index: -2; pointer-events: none;
  /* One pixel of overlap at each join. The three boxes abut exactly — measured
     at 165.65 and 354.99 — but they abut on a FRACTIONAL pixel, so Chrome
     antialiases both edges against the page behind and draws a hairline across
     the masthead at each seam. Overlapping removes the shared edge entirely. */
  top: -1px; bottom: -1px; left: -100vw; right: -100vw;
  background-color: var(--field);
}
main .layout:has(> article > .tool) > article > .kicker {
  display: flex; align-items: center; gap: 10px;
  width: -moz-max-content; width: max-content; max-width: 100%;
  margin: 0; padding: clamp(30px, 4vw, 54px) 0 0;
  color: var(--signal); letter-spacing: 0.13em;
}
main .layout:has(> article > .tool) > article > .kicker::before {
  content: ""; flex: none; width: 22px; height: 2px;
  border-radius: var(--r-full); background: var(--signal);
}
main .layout:has(> article > .tool) > article > h1 {
  margin: 0; padding: 18px 0 0;
  font-size: var(--t-display-2); line-height: 1.02; letter-spacing: -0.034em;
  color: var(--on-field); max-width: 18ch;
}
main .layout:has(> article > .tool) > article > .deck {
  margin: 0 0 clamp(30px, 4vw, 48px);
  padding: 14px 0 clamp(34px, 4.4vw, 60px);
  color: var(--on-field-soft); font-weight: 400; font-size: 1.06em;
  line-height: 1.6; max-width: 58ch;
}
/* Every tool has an intent line today. If one ever ships without, the h1 has to
   close the band itself rather than ending it flush against its own baseline. */
main .layout:has(> article > .tool) > article > h1:not(:has(+ .deck)) {
  padding-bottom: clamp(34px, 4.4vw, 60px);
  margin-bottom: clamp(30px, 4vw, 48px);
}
main .layout:has(> article > .tool) > article > .kicker :focus-visible,
main .layout:has(> article > .tool) > article > .deck :focus-visible {
  outline-color: var(--signal);
}

/* ================================================== THE TOOL'S ANSWER =====
   The answer — the thing the reader came for — is painted on the brand colour,
   which makes it the second field on the page and impossible to mistake for
   the prose around it.

   Not touched, deliberately: fieldset, legend, the inputs, .choices and the
   buttons. Three tools declare their own <fieldset> and <legend> and style them
   through a .tool-<slug> prefix, and an override here outranks that on element
   count. A first draft filled the legend as an accent pill and it landed on top
   of blood-tests' and receding-or-maturing's own numbered legends, dark on
   dark. The shared controls are TOOL_CSS's to change and a tool's own controls
   are the tool's; what is left below is the part no tool restyles. */

main .tool .result {
  border: 0; border-radius: var(--r);
  padding: clamp(22px, 2.6vw, 30px) clamp(22px, 2.6vw, 32px);
  color: var(--on-field);
  background-color: var(--field);
  background-image:
    radial-gradient(110% 130% at 88% 0%, var(--field-glow), transparent 62%),
    linear-gradient(150deg, var(--field-2) 0%, var(--field) 58%);
}
main .tool .result :is(h2, h3) {
  border-top: 0; padding-top: 0; color: var(--on-field);
}
main .tool .result p { color: var(--on-field-soft); }
main .tool .result strong, main .tool .result b { color: var(--on-field); }
main .tool .result a { color: var(--signal); }
main .tool .result :focus-visible { outline-color: var(--signal); }
main .tool .result .readout {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(2rem, 3.4vw, 2.75rem); line-height: 1;
  letter-spacing: -0.04em; color: var(--signal);
}
main .tool .result .readout .unit { color: var(--on-field-soft); }
main .tool .result .src { color: var(--on-field-soft); }

main .tool .flag {
  border: 0; border-left: 4px solid var(--signal);
  border-radius: var(--r-sm);
  background: var(--signal-tint); color: var(--signal-ink);
}
main .tool .flag strong { color: var(--signal-ink); }

main .tool-foot {
  margin-top: 36px; padding: 22px 24px;
  border-top: 0; border-radius: var(--r);
  background: var(--sunken);
}

/* ============================================================== FIGURES ==
   Eleven diagrams that were eleven blocks under eleven hairlines. Each is now a
   sunken card holding a paper plate: two real surfaces, no border and no blur,
   which is where the depth in this redesign comes from everywhere else.

   The plate stays --paper specifically. Several of these figures fill shapes
   with var(--paper) to mean "bare scalp" — a cut-out that only reads as a
   cut-out while the ground behind it is the same paper. Putting the plate on
   --surface would turn every one of those into a visible pale blob. */

main .fig-entry {
  margin: 0 0 clamp(24px, 3vw, 38px);
  padding: clamp(18px, 2vw, 28px);
  border: 0; border-bottom: 0;
  border-radius: var(--r-lg);
  background: var(--sunken);
}
main .fig-entry > h2 {
  border-top: 0; padding-top: 0; margin: 0 0 16px;
}
main .fig-entry > h2::before { content: none; }
main .fig-entry figure.chart.figure-drawn {
  margin: 0 0 14px;
  padding: clamp(14px, 1.8vw, 22px) clamp(8px, 1.4vw, 18px);
  background: var(--paper);
  border-radius: var(--r);
  /* The plate is separated from the card by tone alone, and in dark that tone
     gap is --paper on --sunken: 1.05:1. Measured, and not enough to see. This
     is --ring's job — a surface edge, not a decorative hairline — and it is the
     one place in this file where a border earns its keep. */
  box-shadow: var(--ring);
}
main .fig-entry figure.chart figcaption { max-width: 80ch; }
main .fig-entry .fine { margin: 0; max-width: 80ch; }

/* The embed offer. A control, so it looks like one rather than like a line of
   small print with a triangle in front of it. */
main details.embed { margin: 14px 0 0; padding: 0; border-top: 0; }
main details.embed > summary {
  background: var(--surface); color: var(--ink-soft);
  border-radius: var(--r-full); box-shadow: var(--ring);
  padding: 7px 16px;
  width: -moz-max-content; width: max-content; max-width: 100%;
}
main details.embed[open] > summary { margin-bottom: 10px; }
main details.embed textarea {
  background: var(--surface); border: 0;
  box-shadow: var(--ring); border-radius: var(--r-sm);
}

/* ============================================================= RESEARCH ==
   The PubMed listing arrived built to the old system and inlines its own
   stylesheet, so it kept an accent-tinted card where every other page now has
   the field. This gives it the same masthead — the identical ::before / ::after
   pair .hero uses, so the two are the same band and not two attempts at one —
   and moves its four counters onto the instrument-panel language the home page
   uses on the field. Nothing else about the page is touched: the listing, the
   warning and the saved queries are its own and they are good. */

main .rsrch .rs-hero {
  position: relative; isolation: isolate;
  border: 0; border-radius: 0;
  background: none;
  color: var(--on-field);
  margin: 0 0 clamp(32px, 4vw, 52px);
  padding: clamp(30px, 4vw, 54px) 0 clamp(34px, 4.4vw, 60px);
}
main .rsrch .rs-hero::before {
  content: "";
  position: absolute; z-index: -2; pointer-events: none;
  top: 0; bottom: 0; left: -100vw; right: -100vw;
  background-color: var(--field);
  background-image:
    radial-gradient(110% 130% at 82% 0%, var(--field-glow), transparent 62%),
    radial-gradient(90% 110% at 0% 100%, var(--field-warm), transparent 60%),
    linear-gradient(158deg, var(--field-2) 0%, var(--field) 58%, var(--field) 100%);
}
main .rsrch .rs-hero::after {
  content: "";
  position: absolute; z-index: -1; pointer-events: none;
  top: 0; bottom: 0; left: -100vw; right: -100vw;
  background-image:
    linear-gradient(to right, var(--field-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--field-line) 1px, transparent 1px);
  background-size: 84px 84px;
  opacity: .55;
  -webkit-mask-image: radial-gradient(120% 130% at 50% 0%, var(--mask-on) 6%, transparent 74%);
          mask-image: radial-gradient(120% 130% at 50% 0%, var(--mask-on) 6%, transparent 74%);
}
main .rsrch .rs-kicker {
  display: inline-flex; align-items: center; gap: 9px;
  margin: 0 0 20px; padding: 6px 14px;
  border-radius: var(--r-full);
  background: var(--field-tint);
  box-shadow: inset 0 0 0 1px var(--field-edge);
  color: var(--signal); font-size: var(--t-micro); letter-spacing: 0.11em;
}
main .rsrch .rs-kicker::before {
  content: ""; width: 6px; height: 6px; flex: none;
  border-radius: 50%; background: var(--signal);
}
main .rsrch .rs-hero h1 {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-display-2); line-height: 1.02; letter-spacing: -0.034em;
  color: var(--on-field); max-width: 18ch; margin: 0 0 18px;
}
main .rsrch .rs-hero h1 em {
  font-style: normal; color: var(--signal); text-decoration: none;
}
main .rsrch .rs-deck { color: var(--on-field-soft); max-width: 58ch; }
main .rsrch .rs-fetched { color: var(--on-field-soft); }
main .rsrch .rs-hero a { color: var(--signal); }
main .rsrch .rs-hero :focus-visible { outline-color: var(--signal); }
main .rsrch .rs-stats {
  border: 0; border-radius: var(--r); overflow: hidden;
  background: var(--field-tint-2); gap: 1px;
  margin: clamp(28px, 3.6vw, 44px) 0 0;
}
main .rsrch .rs-stats > div { background: var(--field-tint); padding: 18px 18px 16px; }
main .rsrch .rs-stats dt { color: var(--on-field-soft); }
main .rsrch .rs-stats dd {
  font-family: var(--display); font-weight: 700;
  letter-spacing: -0.03em; color: var(--on-field);
}

/* The body of the page, onto the same surfaces as everything else. */
main .rsrch .rs-banner {
  border: 0; border-left: 4px solid var(--accent);
  border-radius: var(--r-sm); background: var(--sunken);
}
main .rsrch .rs-banner.rs-bad {
  border-left-color: var(--signal); background: var(--signal-tint);
}
main .rsrch .rs-banner.rs-bad p { color: var(--signal-ink); }
main .rsrch .rs-warn {
  border: 0; border-radius: var(--r-lg); background: var(--sunken);
}
main .rsrch .rs-warn li { border-left-color: var(--signal); }
main .rsrch .rs-listing-head { border-bottom: 3px solid var(--signal); }
main .rsrch .rs-item {
  border-radius: var(--r-sm); padding: 20px 12px;
}
main .rsrch .rs-item:hover { background: var(--surface); box-shadow: var(--e1); }
main .rsrch .rs-type {
  border: 0; border-radius: var(--r-full);
  background: var(--signal-tint); color: var(--signal-ink);
}
main .rsrch .rs-topic { border-radius: var(--r-full); }

/* The 12px floor on /research/. lib/research.mjs sets these at 11 and 11.5px
   and its sheet is INLINED into the page head, so it lands after the linked
   stylesheet and wins any tie — the extra "main" is what carries these over it,
   which is the same reason every rule in this block has one.

   Only the size changes. .rs-id and .rs-topic keep the 24px min-height their own
   file argues for in a comment; that is a live disagreement with this pass's
   44px brief and is written up in the report rather than settled here. */
main .rsrch .rs-stats dt,
main .rsrch .rs-note,
main .rsrch .rs-type,
main .rsrch .rs-id,
main .rsrch .rs-topic,
main .rsrch .rs-qn { font-size: 12px; }
main .rsrch .rs-queries { border-top: 3px solid var(--signal); }
main .rsrch .rs-q {
  border: 0; border-radius: var(--r);
  background: var(--surface); box-shadow: var(--e1), var(--ring);
}
main .rsrch .rs-term {
  border: 0; border-radius: var(--r-sm); background: var(--sunken);
}

/* =============================================================== SEARCH ==
   The header's search box belongs to the search module and is fine. This is
   /search/'s own form, which sits directly under the field and was still a
   hairline rectangle. */

main .rgs-pform label { color: var(--ink); font-size: var(--t-sm); }
main .rgs-pin {
  background: var(--surface); border: 0;
  box-shadow: inset 0 0 0 1px var(--rule-firm);
  border-radius: var(--r-full); padding-inline: 20px; min-height: 50px;
}
main .rgs-pgo {
  border-radius: var(--r-full); padding: 0 26px; min-height: 50px;
}
/* 11.5px, and it is the live region that tells a screen-reader user and a
   sighted user how many results they got — on /search/ and on the 404. */
main .rgs-pcount { font-size: 12px; }
main .rgs-noscript, main .rgs-pnone {
  background: var(--sunken); border: 0; border-radius: var(--r);
  padding: 18px 20px; color: var(--ink-soft);
}

/* ================================================================ PHONE == */

@media (max-width: 620px) {
  main .fig-entry { border-radius: var(--r); padding: 14px; }
  main .fig-entry figure.chart.figure-drawn { border-radius: var(--r-sm); padding: 12px 8px 0; }
  main .tool-foot { padding: 18px 18px 20px; }
  main .rsrch .rs-item { padding-inline: 6px; }
  main > h2::before,
  main .layout:has(> article > .hero) > article > h2::before { margin-bottom: 14px; }
}
/* ================================================================ PRINT ===
   Three of the surfaces in this file are painted fields — the tool masthead,
   the tool's answer panel and the /research/ masthead — and a browser prints
   with backgrounds off, which would leave their --on-field text on white paper.
   --print-ink and --print-soft come from lib/theme.mjs and are constant across
   all three theme states, because a reader whose OS is dark still prints white. */
@media print {
  main .layout:has(> article > .tool) > article > :is(.kicker, h1, .deck),
  main .rsrch .rs-hero,
  main .rsrch .rs-hero :is(h1, h1 em, .rs-kicker, .rs-deck, .rs-fetched, a),
  main .rsrch .rs-stats > div,
  main .rsrch .rs-stats :is(dt, dd) {
    background: none; box-shadow: none; color: var(--print-ink);
    margin-inline: 0; padding-inline: 0; border-radius: 0;
  }
  main .layout:has(> article > .tool) > article > .deck,
  main .rsrch .rs-hero :is(.rs-deck, .rs-fetched),
  main .rsrch .rs-stats dt { color: var(--print-soft); }
  main .layout:has(> article > .tool) > article > .kicker::before,
  main .rsrch .rs-hero::before, main .rsrch .rs-hero::after,
  main .rsrch .rs-kicker::before { display: none; }
  main .tool .result {
    background: none; color: var(--print-ink);
    border: 1px solid var(--rule-firm); break-inside: avoid;
  }
  main .tool .result :is(h2, h3, strong, b, a) { color: var(--print-ink); }
  main .tool .result p, main .tool .result .src { color: var(--print-soft); }
  main .tool .result .readout { color: var(--print-ink); }
  main .fig-entry, main .rsrch .rs-item { background: none; break-inside: avoid; }
}
/* ============================================================== TOKENS === */
/* Constant across themes by design: the band is a dark field in light mode and
   in dark mode, the way the chosen direction's hero is. Redeclared in both dark
   blocks anyway, so no colour has its only definition inside a media query. */
:root {
  /* The theme's --display is currently an alias of --sans, because only Archivo,
     Literata and IBM Plex Mono are self-hosted and no display serif exists to
     point it at. A reading page is the one place where that costs something:
     Examine sets its h1 in Lora, Mayo in a bespoke serif, and the whole argument
     of a reference work is carried by the difference between a title face and an
     interface face. So the article's own display face is the text serif at 600 —
     Literata holds up at 54px — while h3, labels and every control stay Archivo.
     One line to change if the theme ever ships a real display face:
     var(--display, var(--serif)) restores the alias. */
  --art-display:      var(--serif);
  --art-field:        var(--field);
  --art-on-field:     var(--on-field);
  --art-on-field-soft:var(--on-field-soft);
  --art-signal:       var(--signal);
  /* text-weight amber and its tint. --data and --data-bg already flip per theme,
     so these need no override of their own. */
  --art-hot:          var(--signal-ink);
  --art-tint:         var(--signal-tint);

  --art-measure: 61ch;
  --art-r:  14px;
  --art-rs: 10px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --art-field:        var(--field);
    --art-on-field:     var(--on-field);
    --art-on-field-soft:var(--on-field-soft);
    --art-signal:       var(--signal);
  }
}
:root[data-theme="dark"] {
  --art-field:        var(--field);
  --art-on-field:     var(--on-field);
  --art-on-field-soft:var(--on-field-soft);
  --art-signal:       var(--signal);
}

/* ========================================================== THE COLUMN === */
/* 61ch at 21px Literata is 744px and 65 real characters. Scoped to the layout's
   own article so the <article class="tc-card"> elements a tool nests inside
   itself keep their own width. */
.layout > article {
  max-width: var(--art-measure);
  font-size: 21px;
  line-height: 1.7;
}
/* Below the sticky-contents breakpoint the column was pinned left with up to
   225px of dead space beside it. */
@media (max-width: 1079px) { .layout > article { margin-inline: auto; } }
@media (max-width: 620px)  { .layout > article { font-size: 18.5px; line-height: 1.66; } }

.layout > article p { margin: 0 0 1.1em; }

/* ============================================================ THE HEAD === */
/* One field made of four sibling boxes. They must not have vertical margins or
   the paper shows through between them as a stripe. */
.layout > article > .crumbs,
.layout > article > .kicker,
.layout > article > h1,
.layout > article > .lede,
.layout > article > h1 + .deck {
  background: var(--art-field);
  color: var(--art-on-field);
  margin-block: 0;
  /* The bleed is the theme's own gutter, so the band's text keeps the same left
     edge as the wordmark above it. The fallback matters: if --pad is ever
     renamed, calc() on an undefined variable is invalid at computed-value time
     and the whole band silently loses its bleed with no other symptom. */
  margin-inline: calc(var(--pad, 24px) * -1);
  padding-inline: var(--pad, 24px);
  /* Four boxes stacked at fractional y positions antialias their own edges, and
     two half-covered edge pixels do not add up to one opaque one: the band came
     out with three hairline seams across it. Each member paints one extra pixel
     of its own background below itself, which the next member then covers. */
  box-shadow: 0 1px 0 var(--art-field);
}
/* first member: crumbs on a guide, the kicker on a tool */
.layout > article > .crumbs,
.layout > article > .kicker:first-child {
  padding-top: 30px;
  border-radius: var(--art-r) var(--art-r) 0 0;
  box-shadow: inset 0 4px 0 var(--art-signal), 0 1px 0 var(--art-field);
}
/* last member: the byline on a guide, the deck on a tool. Kept in its own rule,
   away from the :has() variant below — one invalid selector invalidates the
   whole list, so a browser without :has() would otherwise lose the band's bottom
   padding and rounded corners rather than just the h1-only case. */
.layout > article > .lede,
.layout > article > h1 + .deck {
  padding-bottom: 30px;
  border-radius: 0 0 var(--art-r) var(--art-r);
  margin-bottom: 36px;
  box-shadow: none;   /* nothing below this one to seam against */
}
/* and the shape with neither: a bare title closes the band itself */
.layout > article > h1:not(:has(+ .lede, + .deck)) {
  padding-bottom: 30px;
  border-radius: 0 0 var(--art-r) var(--art-r);
  margin-bottom: 36px;
  box-shadow: none;
}
@media (max-width: 719px) {
  /* full bleed on a phone: --pad and main's own padding are the same value, so
     the negative margin lands exactly on the viewport edge */
  .layout > article > .crumbs,
  .layout > article > .kicker:first-child,
  .layout > article > .lede,
  .layout > article > h1 + .deck { border-radius: 0; }
  .layout > article > h1:not(:has(+ .lede, + .deck)) { border-radius: 0; }
}

.layout > article > .crumbs { font-size: 13px; }
/* 38px tall on a phone. inline-flex rather than padding so the crumb separators,
   which are ::before on the li, stay on the text baseline. */
.layout > article > .crumbs a { color: var(--art-on-field-soft); display: inline-flex; align-items: center; min-height: 44px; }
.layout > article > .crumbs a:hover { color: var(--art-signal); }
.layout > article > .crumbs li + li::before { color: var(--art-on-field-soft); opacity: 0.5; }
.layout > article > .crumbs [aria-current="page"] { color: var(--art-on-field); }

/* The theme's "article > p:first-of-type { font-size: 1.06em }" was written for
   the opening paragraph of the body, but on all 79 guides and all 7 tools the
   first <p> child of <article> is the category kicker — so the rule has been
   setting an 11px mono label at 20.14px instead. Restated here at the size it
   was always meant to be. */
.layout > article > p.kicker {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--art-signal);
  padding-top: 16px;
}
.layout > article > p.kicker a { color: inherit; }
.layout > article > p.kicker a:hover { color: var(--art-on-field); }

.layout > article h1 {
  font-family: var(--art-display);
  font-weight: 600;
  font-size: clamp(2.15rem, 5.2vw, 3.4rem);
  line-height: 1.03;
  letter-spacing: -0.028em;
  text-wrap: balance;
}
.layout > article > h1 { color: var(--art-on-field); padding-top: 12px; margin-bottom: 0; }

.layout > article > .lede {
  font-family: var(--sans);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--art-on-field-soft);
  padding-top: 18px;
}
.layout > article > .lede .dot { color: var(--art-signal); opacity: 0.75; }

/* A tool's intent line, closing the band.
   No max-width: this element IS the bottom of the band, so limiting its width
   limits the painted box and leaves a step cut out of the band's bottom-right
   corner. The measure is shortened with padding instead, which shortens the line
   without narrowing the field. */
.layout > article > h1 + .deck {
  font-family: var(--sans);
  font-weight: 400;
  font-size: clamp(1rem, 1.6vw, 1.14rem);
  line-height: 1.5;
  color: var(--art-on-field-soft);
  padding-top: 16px;
  max-width: none;   /* DECK_CSS caps it at 46ch, which cuts the band */
}
@media (min-width: 720px) {
  .layout > article > h1 + .deck { padding-right: 26%; }
}

/* The structural accent is a navy; a focus ring drawn in it on a navy field is
   invisible. Inside the band the ring is the signal amber, 8.27:1 on the field. */
.layout > article > .crumbs a:focus-visible,
.layout > article > .kicker a:focus-visible {
  outline: 2px solid var(--art-signal);
  outline-offset: 3px;
}

/* ====================================================== KEY-FACTS SHELF === */
/* Five guides carry a verified strip. Where one follows the byline it is pulled
   up so it overlaps the band and reads as a lit shelf rather than a third box
   in a stack; the extra padding underneath the byline makes room for it. */
.layout > article > .lede:has(+ aside.keyfacts) { padding-bottom: 58px; margin-bottom: 0; }
/* position, so the strip paints over the band it is pulled into rather than
   under it — an in-flow block loses to any positioned sibling, whatever the
   document order. */
.layout > article > .lede + aside.keyfacts { margin-top: -34px; position: relative; }

aside.keyfacts {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-top: 0;
  border-radius: var(--art-r);
  padding: 22px 24px 18px;
  margin: 0 0 34px;
  box-shadow:
    inset 0 3px 0 var(--art-hot),
    0 16px 38px -20px color-mix(in srgb, var(--ink) 55%, transparent);
}
aside.keyfacts h2 {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--art-hot);
  margin: 0 0 16px;
}
.keyfacts ul { gap: 18px 26px; }
/* the label wraps to two lines on one tile and one on the next, which left the
   guide codes on three different baselines */
.keyfacts li { display: flex; flex-direction: column; }
.kf-v {
  font-family: var(--mono);
  font-size: 1.6rem;
  font-weight: 500;
  line-height: 1.05;
  color: var(--ink);
  margin: 0 0 6px;
}
.kf-u { font-size: 0.52em; color: var(--art-hot); margin-left: 3px; }
.kf-l { font-family: var(--sans); font-size: 13.5px; line-height: 1.4; color: var(--ink-soft); margin: 0 0 6px; flex: 1 1 auto; }
/* Scoped to .keyfacts, not bare .kf-s: lib/ux/enhancements.mjs ships its own
   copy of .kf-s at 10.5px, and build.mjs emits the UX sheets AFTER this
   one, so a bare .kf-s here loses the tie and the guide code stayed at 10.5px.
   One extra class is enough to win it without an !important. */
.keyfacts .kf-s { font-family: var(--mono); font-size: 12px; letter-spacing: 0.09em; color: var(--muted); margin: 0; }
.kf-note {
  font-family: var(--sans); font-size: 12.5px; line-height: 1.5; color: var(--muted);
  margin: 16px 0 0; padding-top: 14px; border-top: 1px solid var(--rule);
}

/* ============================================================= THE BODY === */
/* Section heads take the display serif. The full-width hairline stays — a guide
   has thirteen of these and they need real separation — and the amber block
   sitting on it is the homepage's section rule, repeated down the page.
   Direct children only, so the summary, the strip, the references, the
   disclaimer and the "More in" list keep their own smaller heads. */
.layout > article > h2 {
  font-family: var(--art-display);
  font-weight: 600;
  font-size: clamp(1.55rem, 2.7vw, 2rem);
  line-height: 1.16;
  letter-spacing: -0.022em;
  color: var(--ink);
  margin: 2.5em 0 0.5em;
  padding-top: 26px;
  border-top: 1px solid var(--rule);
  position: relative;
  text-wrap: balance;
}
.layout > article > h2::before {
  content: "";
  position: absolute;
  top: -2px; left: 0;
  width: 46px; height: 3px;
  background: var(--art-hot);
  border-radius: 2px;
}
.layout > article > h2:first-of-type { margin-top: 1.6em; }

.layout > article > h3 {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 1.02em;
  letter-spacing: 0.01em;
  line-height: 1.35;
  color: var(--ink);
  margin: 2em 0 0.45em;
}
.layout > article > h4 { margin: 1.7em 0 0.3em; }

/* A link inside prose: the underline is quiet until it is wanted, so a paragraph
   with six internal links does not read as a fence. */
.layout > article p a,
.layout > article li a,
.layout > article td a {
  text-decoration-color: color-mix(in srgb, currentColor 38%, transparent);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color .14s;
}
.layout > article p a:hover,
.layout > article li a:hover,
.layout > article td a:hover { text-decoration-color: currentColor; }

.layout > article > ul, .layout > article > ol { margin: 0 0 1.25em; padding-left: 1.3em; }
.layout > article > ul > li, .layout > article > ol > li { margin-bottom: 0.4em; padding-left: 0.15em; }
.layout > article > ul > li::marker { color: var(--art-hot); }
.layout > article > ol > li::marker { font-family: var(--mono); font-size: 0.85em; color: var(--art-hot); }
.layout > article li > strong:first-child { color: var(--ink); font-weight: 600; }

/* :not([class]) — a tool embedded in a guide (finasteride-minoxidil-together
   carries the shedding check) draws its own quote as a classed <blockquote>, and
   restyling that would overwrite a tool module's own design. Only the four
   markdown blockquotes in the corpus are unclassed. */
.layout > article blockquote:not([class]) {
  margin: 1.9em 0;
  padding: 18px 24px;
  border-left: 3px solid var(--art-hot);
  border-radius: 0 var(--art-rs) var(--art-rs) 0;
  background: var(--raised);
  color: var(--ink-soft);
  font-style: italic;
  font-size: 1.02em;
}
.layout > article blockquote:not([class]) p:last-child { margin-bottom: 0; }

/* =============================================================== IN SHORT === */
/* Warm tint rather than the blue wash, and the label as a filled navy chip:
   amber text on the amber tint is 4.28:1 and would have failed at 11px. */
aside.summary {
  background: var(--art-tint);
  border: 0;
  border-radius: var(--art-r);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--art-hot) 26%, transparent);
  padding: 26px 28px 8px;
  margin: 0 0 40px;
}
aside.summary h2 {
  display: inline-block;
  background: var(--art-field);
  color: var(--art-on-field);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 6px 13px 5px;
  border-radius: 999px;
  margin: 0 0 16px;
}
aside.summary p { font-size: 1.01em; color: var(--ink); }
aside.summary ul { font-size: 1em; color: var(--ink); }
aside.summary li::marker { color: var(--art-hot); }

/* The guide's standfirst. The markdown puts it below the strip and the mobile
   contents rather than under the title, so it is set as a lead-in to the
   summary that follows it, not as a subtitle competing with the h1. */
.layout > article > .deck {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.16em;
  line-height: 1.45;
  color: var(--ink-soft);
  max-width: 40ch;
  margin: 0 0 26px;
}

/* ================================================================ TABLES === */
/* 58 of the 79 guides carry one. The header row is the second place the brand
   colour appears at size on a reading page. */
.layout > article .scroll {
  margin: 2.1em 0;
  border: 1px solid var(--rule);
  border-radius: var(--art-rs);
}
.layout > article .scroll table { font-size: 15.5px; }
.layout > article .scroll thead th {
  background: var(--art-field);
  color: var(--art-on-field);
  border-bottom: 0;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.09em;
  padding: 13px 14px;
}
.layout > article .scroll tbody tr:nth-child(even) { background: color-mix(in srgb, var(--art-tint) 42%, transparent); }
.layout > article .scroll td, .layout > article .scroll tbody th { padding: 12px 14px; }
.layout > article .scroll tbody th { color: var(--ink); }

/* =============================================================== FIGURES === */
/* Everything below is fenced above 561px so that FIGURE_MOBILE_CSS keeps the
   pannable box it gives a drawn figure on a phone. */
@media (min-width: 561px) {
  .layout > article figure.chart {
    margin: 2.4em 0;
    padding: 20px 22px 18px;
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--art-r);
  }
  .layout > article figure.chart::before {
    content: "Figure";
    display: block;
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--art-hot);
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--rule);
  }
  .layout > article figure.chart figcaption {
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px solid var(--rule);
  }
  /* the gallery gives every entry its own h2, so the plate label is redundant
     there and only there */
  .fig-entry figure.chart::before { display: none; }
}
.layout > article figure.chart figcaption { font-size: 14px; line-height: 1.55; color: var(--muted); }
.layout > article figure.chart figcaption b { color: var(--ink); font-weight: 600; }
.layout > article figure.chart details.embed { border-top-color: var(--rule); }

/* ================================================================== Q&A === */
/* 608 pairs across 76 guides, and the part of a guide a reader scans rather
   than reads. Each pair becomes its own card so eight in a row are eight
   answers rather than one grey block. */
.qa {
  margin: 0;
  padding: 18px 20px 16px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rule-firm);
  border-radius: var(--art-rs);
  transition: border-left-color .15s;
}
.qa + .qa { margin-top: 10px; }
.qa:hover { border-left-color: var(--art-hot); }
.qa > h3.q {
  font-family: var(--art-display);
  font-size: 1.12em;
  font-weight: 600;
  line-height: 1.28;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0 0 8px;
}
.qa > p { font-size: 0.96em; color: var(--ink-soft); }

/* ========================================================== END MATTER === */
.layout > article > section.refs {
  margin-top: 3.4em;
  padding-top: 26px;
  border-top: 3px solid var(--rule-firm);
}
.layout > article > section.refs > h2 {
  font-family: var(--art-display);
  font-weight: 600;
  font-size: 1.4rem;
  letter-spacing: -0.02em;
  color: var(--ink);
  border: 0; padding: 0; margin: 0 0 16px;
}
ol.reflist { font-size: 14.5px; line-height: 1.55; padding-left: 1.9em; }
ol.reflist li { margin-bottom: 0.6em; }
ol.reflist li::marker { font-family: var(--mono); font-size: 12px; color: var(--art-hot); }

.layout > article > section.disclaimer {
  margin-top: 2.4em;
  padding: 20px 22px 6px;
  background: var(--raised);
  border-radius: var(--art-rs);
}
.layout > article > section.disclaimer > h2 {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  border: 0; padding: 0; margin: 0 0 10px;
}
.fine { font-size: 14px; line-height: 1.65; }

/* "More in <category>" — the last thing on 79 pages, and the only thing offered
   after 3,000 words. */
.layout > article > section:not(.refs):not(.disclaimer) > h2 {
  font-family: var(--art-display);
  font-weight: 600;
  font-size: 1.4rem;
  letter-spacing: -0.02em;
  border: 0; padding: 0; margin: 3em 0 6px;
}
.layout > article .index-list a { padding: 16px 12px 16px 0; border-radius: var(--art-rs); transition: background .14s, padding .14s; }
.layout > article .index-list a:hover { background: var(--raised); padding-inline: 12px; }
.layout > article .index-list .t { font-family: var(--art-display); font-weight: 600; font-size: 1.06rem; letter-spacing: -0.015em; }

/* ============================================================== CONTENTS === */
@media (min-width: 1080px) {
  .toc { top: 96px; font-size: 14px; max-height: calc(100vh - 140px); }
  .toc h2 { font-size: 12px; letter-spacing: 0.16em; color: var(--art-hot); margin-bottom: 14px; }
  .toc ol { border-left: 2px solid var(--rule); }
  .toc a {
    padding: 7px 0 7px 16px; margin-left: -2px;
    border-left: 2px solid transparent; color: var(--muted); line-height: 1.35;
    transition: color .12s, border-color .12s;
  }
  .toc a:hover { color: var(--ink); border-left-color: var(--rule-firm); }
  /* nav.toc, not .toc: lib/ux/enhancements.mjs sets .toc a.is-here to the
     structural accent and its sheet is concatenated after every theme sheet in
     build.mjs, so an equal-specificity rule here silently lost and the active
     entry kept a blue rail instead of the amber one. One element name settles
     it, and the element really is a <nav>. */
  nav.toc a.is-here { color: var(--ink); font-weight: 600; border-left-color: var(--art-hot); }
}
@media (max-width: 1079px) {
  .toc-mobile { border-radius: var(--art-rs); background: var(--surface); margin: 0 0 30px; }
  .toc-mobile > summary { font-size: 14.5px; color: var(--ink); }
  .toc-mobile > summary::after { border-color: var(--art-hot); }
  .toc-mobile > summary .n { letter-spacing: 0.06em; }
  .toc-mobile a { font-size: 15px; padding: 4px 0; }
}

/* ============================================================ FURNITURE === */
/* Filled rather than outlined: at the foot of a 3,400-word page this is the one
   control on screen, and it now carries the brand colour instead of a hairline. */
/* button.totop, for the same reason as nav.toc above: the enhancements sheet
   loads last and its outlined white pill was winning the tie, so this filled
   navy never reached the page. */
button.totop {
  background: var(--art-field);
  color: var(--art-on-field);
  border-color: transparent;
  box-shadow: 0 8px 22px -8px color-mix(in srgb, var(--ink) 60%, transparent);
}
button.totop:hover { color: var(--art-signal); border-color: transparent; }
/* The ring sits 2px OUTSIDE the button, which puts it on --paper, and the amber
   is 1.89:1 there — a focus indicator that fails 3:1. The signal is only ever
   legible on the field, and this button is the one field-coloured thing sitting
   on paper. So the ring takes the structural accent, 8.5:1 on paper, which is
   what every other focusable thing on this site already uses. */
button.totop:focus-visible { outline: 2.5px solid var(--accent); outline-offset: 2px; }

/* Print drops backgrounds, so the band disappears and its --on-field text would
   land near-white on white paper. --print-ink rather than --ink because a reader
   whose OS is in dark mode still prints on white: --ink is #E9E6E0 there. */
@media print {
  .layout > article > .crumbs,
  .layout > article > .kicker,
  .layout > article > h1,
  .layout > article > .lede {
    background: transparent; color: var(--print-ink);
    margin-inline: 0; padding-inline: 0; box-shadow: none; border-radius: 0;
  }
  /* p.kicker, not .kicker: the screen rule that sets the eyebrow amber names the
     element too, and amber on white paper is 2.2:1. */
  .layout > article > p.kicker,
  .layout > article > .crumbs a,
  .layout > article > .crumbs,
  .layout > article > .lede { color: var(--print-soft); }
  .layout > article > h1::before, .layout > article > .crumbs::before { display: none; }
  button.totop { display: none; }
  aside.keyfacts { margin-top: 0; break-inside: avoid; }
  .qa, figure.chart, .summary { break-inside: avoid; }
}

/* ---------------------------------------------------------------------------
   The wrapper reconciliation.

   This file styles the article masthead as banded SIBLINGS: a child-combinator
   chain from .layout to article to .crumbs, .kicker, h1 and .lede, each painting
   the same background so they read as one block. lib/theme.mjs, written in
   parallel by a different agent, styles it as a WRAPPER, .hero.article, and
   asked the build to emit that. The build emits the wrapper, so every sibling
   selector above stops matching at its child combinator and silently does
   nothing.

   (Written without backticks on purpose: this comment lives inside a template
   literal, and a backtick here ends the stylesheet mid-sentence.)

   The band itself still renders, because theme.mjs paints it. What did not
   survive was this file's own work inside it — most visibly the breadcrumb's
   current-page span, which kept a paper ink (#3A3F49) on a dark field at about
   1.3:1. The links either side of it were correct, which is what makes this the
   kind of bug that ships: it looks styled.

   Rather than delete either agent's approach, the sibling rules keep working
   wherever the structure is flat, and these repeat them one level deeper.
   --------------------------------------------------------------------------- */

.hero.article > .crumbs,
.hero.tool > .crumbs { font-size: 13px; }
.hero.article > .crumbs a,
.hero.tool > .crumbs a {
  color: var(--art-on-field-soft, var(--on-field-soft));
  /* 44px, the same target the sibling rule set and the wrapper lost. Measured at
     38px on a 375px screen before this — a breadcrumb is a small target already
     and this is the one people reach for to go back up a level. */
  display: inline-flex; align-items: center; min-height: 44px;
}
.hero.article > .crumbs [aria-current],
.hero.tool > .crumbs [aria-current] {
  /* The one that was invisible. */
  color: var(--art-on-field-soft, var(--on-field-soft));
  opacity: 0.72;
}
.hero.article > .crumbs ol,
.hero.tool > .crumbs ol { flex-wrap: wrap; }
.hero.article > .kicker a,
.hero.tool > .kicker a { color: inherit; text-decoration: none; }
.hero.article > .kicker a:hover,
.hero.tool > .kicker a:hover { text-decoration: underline; text-underline-offset: 3px; }
.hero-art { position: relative; width: 100%; max-width: 560px; margin-inline: auto }
.hero-art > svg { display: block; width: 100%; height: auto }
.hero-art > svg.ha-narrow { display: none }

/* Slip typography, in viewBox units, so it scales with the artwork: about 1.55x
   authored size on a 1440px desktop and about 1.12x on a 390px phone. */
.ha-code { font-family: var(--mono), ui-monospace, Menlo, Consolas, monospace; font-size: 11px; font-weight: 500; letter-spacing: .05em }
.ha-src  { font-family: var(--sans), -apple-system, "Segoe UI", system-ui, sans-serif; font-size: 9.5px; font-weight: 600; letter-spacing: .07em }
.ha-val  { font-family: var(--display), var(--serif), Georgia, serif; font-size: 34px; font-weight: 600; letter-spacing: -.03em }
.ha-unit { font-size: 17px; letter-spacing: -.01em }
.ha-lab  { font-family: var(--sans), -apple-system, "Segoe UI", system-ui, sans-serif; font-size: 11px; font-weight: 500 }
.ha-q    { font-family: var(--serif), Georgia, serif; font-size: 10.5px; font-style: italic }

.ha-cap {
  display: flex; gap: 12px; align-items: baseline;
  max-width: 560px; margin: 22px auto 0;
  font-family: var(--sans), -apple-system, "Segoe UI", system-ui, sans-serif;
  font-size: 13px; line-height: 1.55; color: var(--on-field-soft);
}
.ha-cap b {
  flex: none; font-family: var(--mono), ui-monospace, Menlo, Consolas, monospace;
  font-weight: 500; font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--signal);
}

/* A slow drift: five viewBox units deep over twenty-odd seconds, which is enough
   for the slips to read as floating above the field and not enough to move while
   anybody is reading them. Nothing at all for reduced-motion users — the rule
   only exists inside no-preference, so there is nothing to switch off. */
@media (prefers-reduced-motion: no-preference) {
  .ha-float { animation: ha-drift 21s ease-in-out infinite }
  .ha-float-2 { animation-duration: 26s; animation-delay: -7s }
  .ha-float-3 { animation-duration: 31s; animation-delay: -14s }
}
@keyframes ha-drift {
  0%, 100% { transform: translateY(0) }
  50% { transform: translateY(-5px) }
}

/* Phone: the narrow cut, two slips in a 300-unit box. See LAYOUTS. The caption
   drops its hanging label onto its own line so the sentence keeps a full measure. */
@media (max-width: 559px) {
  .hero-art > svg.ha-wide { display: none }
  .hero-art > svg.ha-narrow { display: block }
  .hero-art { max-width: 430px }
  .ha-cap { flex-direction: column; gap: 6px; margin-top: 18px }
}
/* --------------------------------------------------------- header search -- */

.rgs {
  position: relative;
  font-family: var(--sans);
  flex: 1 1 190px;
  min-width: 44px;
  max-width: 300px;
}
.rgs-form { position: relative; margin: 0; display: block; }

/* The hidden attribute is how everything here is shown and hidden, and the
   UA sheet rule [hidden] { display: none } is an ordinary author-beatable one:
   .rgs-clear { display: flex } silently wins over it. That left the clear
   button laid out at 44x44 over the collapsed field on a phone, eating the tap
   that should have opened search, and left the "see all" strip rendering as a
   blank sticky bar under every short result list. Hiding is not optional
   styling, so it is stated once, here, and it wins. */
.rgs [hidden], .rgs-page [hidden] { display: none !important; }

.rgs-vh {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.rgs-ico {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  color: var(--muted); pointer-events: none;
}

.rgs-in {
  width: 100%; height: 44px; min-height: 44px;
  padding: 0 34px 0 35px; margin: 0;
  font-family: var(--sans); font-size: 15px; font-weight: 500; line-height: 1.2;
  color: var(--ink); background: var(--paper);
  border: 1px solid var(--rule-firm); border-radius: 999px;
  -webkit-appearance: none; appearance: none;
}
.rgs-in::placeholder { color: var(--muted); opacity: 1; }
.rgs-in::-webkit-search-cancel-button, .rgs-in::-webkit-search-decoration { -webkit-appearance: none; display: none; }
.rgs-in:hover { border-color: var(--accent); }
.rgs-in:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.rgs-clear {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; padding: 0; display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-radius: 999px; cursor: pointer; color: var(--muted);
}
.rgs-clear:hover { color: var(--ink); }
.rgs-clear:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* The submit button is visually hidden because Enter already submits and the
   field carries the magnifier — but it stays in the tab order, so a keyboard
   user was landing on a 3px invisible control with nothing to see. It surfaces
   over the right end of the field while it holds focus and clips away again
   after, so nothing moves. */
.rgs-go:focus-visible {
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  width: auto; height: 36px; margin: 0; padding: 0 14px;
  clip: auto; clip-path: none; overflow: visible; white-space: nowrap; z-index: 9;
  font-family: var(--sans); font-size: 13px; font-weight: 600;
  color: var(--accent-ink); background: var(--accent-bg);
  border: 1px solid var(--accent); border-radius: 999px; cursor: pointer;
  outline: 2px solid var(--accent); outline-offset: 1px;
}

/* -------------------------------------------------------------- the panel -- */

.rgs-panel {
  position: absolute; z-index: 6; top: calc(100% + 8px); right: 0;
  width: min(92vw, 400px);
  background: var(--surface);
  border: 1px solid var(--rule-firm); border-radius: 4px;
  box-shadow: 0 12px 34px color-mix(in srgb, var(--ink) 16%, transparent);
  max-height: min(70vh, 460px); overflow-y: auto; overscroll-behavior: contain;
}
.rgs-list { list-style: none; margin: 0; padding: 0; }
.rgs-list li { margin: 0; }

.rgs-hit {
  display: block; padding: 10px 15px 11px 12px;
  min-height: 44px; text-decoration: none; color: var(--ink);
  border-left: 3px solid transparent;
  border-bottom: 1px solid var(--rule);
}
.rgs-list li:last-child .rgs-hit { border-bottom: 0; }
.rgs-hit .t { display: block; font-size: 15px; font-weight: 600; line-height: 1.35; }
.rgs-hit .c {
  display: block; margin-top: 3px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted);
}
/* Two encodings for the active row, never colour alone: the rule on the left
   edge is what tells you where you are if the tint is not distinguishable. */
.rgs-hit:hover { background: var(--raised); }
.rgs-hit[aria-selected="true"] {
  background: var(--accent-bg); border-left-color: var(--accent);
}
.rgs-hit[aria-selected="true"] .t { color: var(--accent-ink); }
.rgs-hit mark { background: var(--data-bg); color: var(--ink); border-radius: 2px; padding: 0 1px; }

.rgs-empty { margin: 0; padding: 14px 15px; font-size: 14px; color: var(--muted); line-height: 1.5; }
.rgs-empty a { color: var(--accent); }

/* Sticky: with eight results the panel scrolls, and the way out to the full
   result set should not be something you have to scroll to find. */
.rgs-all {
  display: block; padding: 12px 15px; min-height: 44px;
  position: sticky; bottom: 0;
  border-top: 1px solid var(--rule); background: var(--raised);
  font-size: 13.5px; font-weight: 600; color: var(--accent); text-decoration: none;
}
.rgs-all:hover { background: var(--accent-bg); text-decoration: underline; }
.rgs-all:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ------------------------------------------------------- the compact box -- */
/* Two problems, one answer. Below 1080px the bar is one non-wrapping row and
   the nav already scrolls sideways inside it, so a 190px input would leave the
   nav about 60px wide. Between 1080 and 1200 the bar is wide enough not to
   scroll but not wide enough for everything: measured at 1120px, a 181px input
   pushed the seven nav links onto three rows and took the sticky header from
   60px to 94px. The wordmark, the nav and a 190px field need about 1150px
   before they fit, so the box stays a 44px target until then and expands over
   the nav on focus — with :focus-within, so it works before the script loads
   and keeps working if the script never loads. */
@media (max-width: 1199px) {
  .rgs { flex: 0 0 44px; max-width: 44px; min-width: 44px; height: 44px; margin-left: auto; }
  /* The form is the containing block for the input, the icon and the clear
     button. Once the input goes absolute on focus the form has nothing left in
     flow, so without this it collapses to zero height and every "top: 50%"
     inside it centres on the bar's top edge instead of on the bar. */
  .rgs-form { height: 100%; }
  .rgs-in {
    width: 44px; padding: 0 0 0 40px;
    background: transparent; border-color: transparent;
  }
  .rgs-in::placeholder { color: transparent; }
  .rgs-ico { left: 14px; }
  .rgs:focus-within .rgs-in, .rgs[data-open] .rgs-in {
    position: absolute; right: 0; top: 50%; transform: translateY(-50%); z-index: 7;
    width: min(78vw, 340px); padding: 0 40px 0 16px;
    background: var(--paper); border-color: var(--rule-firm);
  }
  .rgs:focus-within .rgs-in::placeholder, .rgs[data-open] .rgs-in::placeholder { color: var(--muted); }
  .rgs:focus-within .rgs-ico, .rgs[data-open] .rgs-ico { display: none; }
  .rgs-clear { z-index: 8; }
  .rgs-panel { width: min(92vw, 360px); }
}

/* The expanded field is min(78vw, 340px) anchored to the right edge, so it only
   reaches back as far as the wordmark on a phone — above about 560px there is
   clear space between them and hiding the wordmark would be gratuitous. Below
   it the wordmark steps out of the way while someone is typing rather than
   being half-covered by an opaque pill. Layout is untouched — visibility, not
   display — and where :has() is not supported the rule is simply dropped and
   the field overlaps, which is the pattern every mobile header uses anyway. */
@media (max-width: 560px) {
  .bar:has(.rgs:focus-within) .wordmark, .bar:has(.rgs[data-open]) .wordmark { visibility: hidden; }
}

/* ----------------------------------------------------------- /search/ page -- */

.rgs-page { max-width: var(--measure); }
.rgs-pform { margin: 0 0 22px; }
.rgs-pform label {
  display: block; font-family: var(--sans); font-size: 15px; font-weight: 500;
  color: var(--ink); margin: 0 0 8px;
}
.rgs-prow { display: flex; gap: 10px; flex-wrap: wrap; }
.rgs-pin {
  flex: 1 1 240px; min-width: 0; min-height: 48px;
  font-family: var(--sans); font-size: 16px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--rule-firm); border-radius: 3px;
  padding: 12px 14px; -webkit-appearance: none; appearance: none;
}
.rgs-pin::placeholder { color: var(--muted); opacity: 1; }
.rgs-pin:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.rgs-pgo {
  font-family: var(--sans); font-size: 15px; font-weight: 600;
  background: var(--accent); color: var(--surface);
  border: 1px solid var(--accent); border-radius: 3px;
  padding: 12px 22px; min-height: 48px; cursor: pointer;
}
.rgs-pgo:hover { background: var(--accent-ink); border-color: var(--accent-ink); }
.rgs-pgo:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.rgs-pcount {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted); margin: 0 0 6px; min-height: 1.2em;
}
.rgs-presults { margin: 0; }
.rgs-presults .c {
  display: block; margin-top: 5px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--accent);
}
.rgs-presults mark { background: var(--data-bg); color: var(--ink); border-radius: 2px; padding: 0 1px; }
.rgs-noscript, .rgs-pnone {
  font-family: var(--sans); font-size: 15px; color: var(--muted);
  line-height: 1.6; border-left: 3px solid var(--rule-firm); padding: 2px 0 2px 16px; margin: 8px 0 0;
}

@media (max-width: 620px) {
  .rgs-pgo { flex: 1 1 100%; }
}
/* --------------------------------------------------------- breadcrumbs --- */
.crumbs { font-family: var(--sans); font-size: 13px; margin: 0 0 14px; }
.crumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 6px; }
.crumbs li { margin: 0; display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.crumbs li + li::before { content: "/"; color: var(--rule-firm); }
/* 8px of vertical padding rather than 3: at 13px these are the first links on
   the page and a 19px-tall tap target on a phone is a coin toss. The li is
   flex, so the padding grows the hit box without moving the baseline. */
.crumbs a { color: var(--muted); text-decoration: none; padding: 8px 0; margin: -8px 0; }
.crumbs a:hover { color: var(--accent); text-decoration: underline; }
.crumbs [aria-current="page"] { color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 22ch; }
@media (min-width: 720px) { .crumbs [aria-current="page"] { max-width: 48ch; } }

/* ----------------------------------------------------- reading progress --- */
/* Sits above the sticky header (z-index 20) and takes the structural accent,
   never the data ochre, so it cannot be mistaken for a measurement. */
.rp { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 30; pointer-events: none; }
.rp-i { height: 100%; width: 100%; transform: scaleX(0); transform-origin: 0 50%; background: var(--accent); }

/* ---------------------------------------------------------- back to top --- */
.totop {
  position: fixed; z-index: 25;
  right: max(14px, env(safe-area-inset-right));
  bottom: max(16px, env(safe-area-inset-bottom));
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 44px; min-width: 44px; padding: 0 15px;
  font-family: var(--sans); font-size: 13.5px; font-weight: 600; line-height: 1;
  color: var(--accent); background: var(--surface);
  border: 1px solid var(--rule-firm); border-radius: 999px; cursor: pointer;
  box-shadow: 0 2px 10px color-mix(in srgb, var(--ink) 14%, transparent);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
.totop:hover { color: var(--accent-ink); border-color: var(--accent); }
/* visibility, not opacity alone: a button faded to zero is still tabbable. */
.totop[data-on="0"] { opacity: 0; visibility: hidden; transform: translateY(8px); }
@media (prefers-reduced-motion: reduce) { .totop { transition: none; } }

/* ------------------------------------------------------------- key facts -- */
.keyfacts {
  border: 1px solid var(--rule); border-top: 3px solid var(--data);
  background: var(--surface); border-radius: 3px;
  padding: 16px 18px 14px; margin: 0 0 30px;
}
.keyfacts h2 {
  border: 0; padding: 0; margin: 0 0 12px;
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--data);
}
.keyfacts ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 15px; }
@media (min-width: 560px) {
  .keyfacts ul { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 22px; }
}
.keyfacts li { margin: 0; min-width: 0; }
.kf-v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.45rem; font-weight: 500; line-height: 1.1;
  color: var(--ink); margin: 0 0 4px;
}
.kf-u { font-size: 0.56em; color: var(--muted); margin-left: 2px; }
.kf-l { font-family: var(--sans); font-size: 13.5px; line-height: 1.4; color: var(--ink-soft); margin: 0 0 5px; }
.kf-s { font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.08em; color: var(--muted); margin: 0; cursor: help; }
.kf-note { font-family: var(--sans); font-size: 12.5px; line-height: 1.5; color: var(--muted); margin: 15px 0 0; }

/* ------------------------------------------------------------ toc active -- */
/* Weight and a rule as well as colour — colour alone is not an encoding. */
.toc a.is-here, .toc-mobile a.is-here { color: var(--accent); font-weight: 600; }
.toc a.is-here { border-left-color: var(--accent); }

/* ------------------------------------------------------------- copy link -- */
/* There is no hover on a phone, so the anchors are permanently faint there
   rather than invisible, and padded out to something a thumb can hit.
   Written as a.anchor rather than .anchor purely to outrank the theme's own
   "h2 .anchor { opacity: 0 }" whichever order the build concatenates the two. */
h2 a.anchor, h3 a.anchor, h4 a.anchor { position: relative; padding: 6px; margin-left: 2px; }
@media (hover: none) {
  h2 a.anchor, h3 a.anchor, h4 a.anchor { opacity: 0.45; }
  /* A "#" set at 0.8em with 6px of padding is about a 26px target, and a thumb
     needs 44. The hit area is grown with an out-of-flow pseudo-element instead
     of real padding so the heading's line box does not change, and it is anchored
     to the anchor's left edge and grown rightwards into the empty end of the
     line rather than centred, which would put it over the last few words of the
     heading — sometimes an internal link the resolver put there. */
  h2 a.anchor::before, h3 a.anchor::before, h4 a.anchor::before {
    content: ""; position: absolute; left: 0; top: 50%;
    width: 44px; height: 44px; transform: translateY(-50%);
  }
}
.anchor[data-copied] { opacity: 1; color: var(--good); }
.anchor[data-copied]::after {
  content: "copied"; font-family: var(--sans); font-size: 11px;
  font-weight: 600; letter-spacing: 0.02em; margin-left: 5px;
}
/* The live region, and the spoken half of a key-facts source line: a title
   attribute is a mouse affordance and nothing else — it never appears on a
   phone, which is where this site is read, and screen readers vary on whether
   they announce it at all. The tile's provenance is therefore in the text as
   well, hidden from sight rather than from the accessibility tree. */
.ux-say, .kf-vh {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

@media print { .rp, .totop { display: none; } }
