/* PlainRecord — a monochrome newspaper page.

   Structure of this file
   ----------------------
   1  tokens            9  article, rail, panels
   2  fonts            10  evidence, tables, revisions
   3  base             11  charts
   4  motion           12  prose pages
   5  masthead, nav    13  footer
   6  ticker, notices  14  wider screens
   7  sections, home   15  print
   8  lists, meta

   Four positions are load-bearing and are argued where they are implemented,
   so that a later editor can disagree with the reasoning rather than guess at
   it: there is no accent hue (§1), the layout is additive from the phone up
   (§14), the black bars invert by token rather than by colour so the dark
   scheme keeps its emphasis (§1), and motion runs once on load rather than on
   scroll (§4).

   Nothing here needs JavaScript. The reader pages are served under a
   Content-Security-Policy with no `script-src` at all, and no
   `style-src 'unsafe-inline'` either — so every declaration on the site is in
   this one file, and chart geometry lives in SVG presentation attributes
   written server-side. */


/* ==========================================================================
   1. Tokens
   ========================================================================== */

:root {
  /* Paper and ink. `--ink` means *the ink colour*, not "black": on a dark
     page the ink is light. Everything that inverts — filled tags, notice
     chips, pill hovers — is expressed as `--ink` on `--ink-invert`, so the
     dark scheme inherits the inversion instead of re-specifying it. */
  --paper:        #f7f6f4;
  --paper-raised: #ffffff;
  --paper-sunk:   #f0efec;
  --ink:          #0b0b0b;
  --ink-body:     #3a3936;
  --ink-soft:     #565450;
  --ink-invert:   #ffffff;
  --rule:         #dcdad5;
  --rule-strong:  #0b0b0b;

  /* The large inverted surfaces — nav, ticker, footer — are a separate pair.
     On a light page they are the ink colour and that is the whole point of
     them. On a dark page they cannot simply follow `--ink`, because that
     would turn them white and blow out the two widest bands on the screen.
     They become a raised near-black with a visible hairline instead: still
     read as "a bar", by surface change rather than by brute contrast. This is
     the one place where the dark scheme is not a straight inversion, and it
     is the reason the black bars survive it. */
  --bar-bg:       #0b0b0b;
  --bar-ink:      #ffffff;
  --bar-ink-soft: #d6d4cf;
  --bar-rule:     #2a2a2a;

  /* Chart surfaces. The hatch and dot patterns that separate one series from
     another need a ground to sit on that is the page, not white. */
  --chart-ink:    #0b0b0b;
  --chart-ground: #f7f6f4;

  --measure:      46em;
  --container:    77.5rem;   /* 1240px at the default root size */
  --gutter:       1.25rem;

  /* Type. Every size below is relative, so a reader who has raised their
     system text size actually gets it — the previous build declared 86 sizes
     in px and none in rem, which quietly discarded that preference. The
     clamps are bounded at both ends so nothing collapses at 320px or runs
     away on a wide monitor. */
  --fs-label:  0.6875rem;                                   /* 11px furniture */
  --fs-meta:   0.75rem;                                     /* 12px meta      */
  --fs-small:  0.875rem;                                    /* 14px           */
  --fs-body:   clamp(1.0625rem, 1.02rem + 0.18vw, 1.125rem);
  --fs-prose:  clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
  --fs-lede:   clamp(1.0625rem, 1rem + 0.45vw, 1.25rem);
  --fs-h3:     clamp(1.1875rem, 1.1rem + 0.5vw, 1.4375rem);
  --fs-h2:     clamp(1.3125rem, 1.15rem + 0.9vw, 1.75rem);
  --fs-h1:     clamp(1.625rem, 1.3rem + 2.2vw, 3rem);
  --fs-lead:   clamp(2rem, 1.5rem + 3vw, 3.375rem);
  --fs-figure: clamp(2rem, 1.7rem + 1.6vw, 2.75rem);

  --display: "Prata", "Iowan Old Style", Palatino, Georgia, serif;
  --serif:   "Lora", Georgia, "Times New Roman", serif;
  --sans:    "Work Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
             Roboto, sans-serif;
  --mono:    ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Motion. One easing: a critically damped spring sampled into `linear()`.
     `linear()` normalises both axes, so a spring at a given damping has
     exactly one shape and only the duration varies — which is why there is
     one token here and not three. Damping is critical (bounce = 0), so the
     curve never overshoots: a record of votes and death tolls does not
     wobble into place. */
  --ease-settle: linear(0, 0.0534, 0.169, 0.3033, 0.4338, 0.5501, 0.6485,
                        0.729, 0.7933, 0.8437, 0.8827, 0.9125, 0.9351, 0.952,
                        0.9647, 0.9741, 0.9811, 0.9862, 1);
  --dur-swift: 0.2s;
  --dur-settle: 0.32s;
  --dur-draw: 0.55s;

  color-scheme: light;
}

/* The dark palette, defined once as its own set of names. It is remapped onto
   the live tokens by the two rules below rather than written into them here,
   because dark applies in two different situations — the reader's system asks
   for it, or the reader asks for it on this page — and a colour that lived
   inside one of those rules would have to be kept in step by hand with the
   other. Change a value here and both paths follow. */
:root {
  --d-paper:        #101010;
  --d-paper-raised: #171716;
  --d-paper-sunk:   #0a0a0a;
  --d-ink:          #ecebe8;
  --d-ink-body:     #c3c1bc;
  --d-ink-soft:     #9a9793;
  --d-ink-invert:   #0b0b0b;
  --d-rule:         #2f2e2c;
  --d-rule-strong:  #ecebe8;
  --d-bar-bg:       #1b1b1a;
  --d-bar-ink:      #ecebe8;
  --d-bar-ink-soft: #a5a29d;
  /* A hairline the bars can still show against the page behind them. */
  --d-bar-rule:     #353432;
  --d-chart-ink:    #ecebe8;
  --d-chart-ground: #101010;
}

/* Dark, because the operating system asked for it — unless the reader has
   overridden it to Light on this page. "Auto" and "no control rendered" both
   fall through to here, so the scheme still follows the system on any page
   that never draws the switch. */
@media (prefers-color-scheme: dark) {
  :root:not(:has(#ap-light:checked)) {
    --paper: var(--d-paper);
    --paper-raised: var(--d-paper-raised);
    --paper-sunk: var(--d-paper-sunk);
    --ink: var(--d-ink);
    --ink-body: var(--d-ink-body);
    --ink-soft: var(--d-ink-soft);
    --ink-invert: var(--d-ink-invert);
    --rule: var(--d-rule);
    --rule-strong: var(--d-rule-strong);
    --bar-bg: var(--d-bar-bg);
    --bar-ink: var(--d-bar-ink);
    --bar-ink-soft: var(--d-bar-ink-soft);
    --bar-rule: var(--d-bar-rule);
    --chart-ink: var(--d-chart-ink);
    --chart-ground: var(--d-chart-ground);
    color-scheme: dark;
  }
}

/* Dark, because the reader asked for it here, whatever the system says. */
:root:has(#ap-dark:checked) {
  --paper: var(--d-paper);
  --paper-raised: var(--d-paper-raised);
  --paper-sunk: var(--d-paper-sunk);
  --ink: var(--d-ink);
  --ink-body: var(--d-ink-body);
  --ink-soft: var(--d-ink-soft);
  --ink-invert: var(--d-ink-invert);
  --rule: var(--d-rule);
  --rule-strong: var(--d-rule-strong);
  --bar-bg: var(--d-bar-bg);
  --bar-ink: var(--d-bar-ink);
  --bar-ink-soft: var(--d-bar-ink-soft);
  --bar-rule: var(--d-bar-rule);
  --chart-ink: var(--d-chart-ink);
  --chart-ground: var(--d-chart-ground);
  color-scheme: dark;
}


/* ==========================================================================
   2. Fonts
   Latin and latin-ext subsets only, served from this origin. Reading a page
   contacts nobody else. Lora and Work Sans are variable, so one file covers
   the whole 400–600 range. See web/static/fonts/OFL.txt.
   ========================================================================== */

@font-face {
  font-family: "Prata";
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/prata-latin.b4419348ab41.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: "Lora";
  font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("../fonts/lora-latin.662c56ecd8de.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: "Lora";
  font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("../fonts/lora-latin-ext.d551ed729291.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: "Lora";
  font-style: italic; font-weight: 400; font-display: swap;
  src: url("../fonts/lora-italic-latin.1b001151dec8.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: "Lora";
  font-style: italic; font-weight: 400; font-display: swap;
  src: url("../fonts/lora-italic-latin-ext.976f138e48c2.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: "Work Sans";
  font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("../fonts/work-sans-latin.4890688e6436.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: "Work Sans";
  font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("../fonts/work-sans-latin-ext.1f8c41030121.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;
}


/* ==========================================================================
   3. Base
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  /* No fixed root size: the reader's own base size is the base size. */
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: var(--fs-body);
  line-height: 1.7;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  /* iOS: keep the tap flash monochrome rather than the system blue wash. */
  -webkit-tap-highlight-color: rgba(11, 11, 11, 0.08);
}

.wrap {
  max-width: var(--container);
  margin-inline: auto;
  /* Safe areas on a notched phone in landscape, which is a real reading
     posture and currently loses text behind the sensor housing. */
  padding-inline: max(var(--gutter), env(safe-area-inset-left))
                  max(var(--gutter), env(safe-area-inset-right));
}

a {
  color: var(--ink);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
}
a:hover { color: var(--ink-soft); }

:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}

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

h1, h2, h3, .lead__title, .article__title, .brief-item__title {
  /* Headlines here run to 300 characters. Balancing the short ones and
     pretty-wrapping the long ones stops a single orphaned word ending a
     Parliament title. */
  text-wrap: balance;
}
p, li, dd, figcaption { text-wrap: pretty; }

/* Visually hidden, still announced and still focusable. Used for the search
   field's label text and the appearance group's legend, both of which are
   named by an icon or by their own options on screen. */
.u-sr {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; inset-inline-start: -9999px; inset-block-start: 0;
  background: var(--paper-raised); color: var(--ink);
  border: 1px solid var(--ink);
  font-family: var(--sans); font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase;
  padding: .7rem 1.1rem; z-index: 10; text-decoration: none;
}
.skip:focus { inset-inline-start: 0; }

/* Shared furniture: the uppercase sans label used for kickers, meta lines,
   section titles, table headers and pagination.

   Noted for the day a second language arrives: uppercase is wrong in Turkish
   and German, meaningless in CJK, Arabic and Devanagari, and letter-spacing
   breaks Arabic cursive joining outright. The label system will need a form
   that still reads as a label when it is neither Latin nor uppercase — a rule
   above, a weight change, or a size step. Everything that would have to
   change is gathered in this one selector on purpose. */
.kicker, .meta, .section__title, .section__more, .pager,
table.data th, details > summary {
  font-family: var(--sans);
  text-transform: uppercase;
}


/* ==========================================================================
   4. Motion

   Entrance only, once, on load. Deliberately *not* scroll-driven: CSS
   scroll-timelines are well supported now and were the obvious modern choice
   here, but `animation-timeline: view()` re-runs its animation every time an
   element re-enters the viewport, so a reader scrolling back up a brief would
   watch the evidence animate again. The standing rule is that nothing repeats
   while a reader is reading, and a chart that redraws itself on the way back
   up is exactly the manufactured drama this publication has no use for.

   Scroll-driven animation is used once, further down, for something that is
   genuinely a function rather than an effect: showing that a scrollable
   container has more to the right.

   Zero layout shift: every animated element occupies its final space from the
   first frame, so only opacity and a small translate are touched. And the
   page must be identically informative with no frames at all — the whole
   block is gated behind `prefers-reduced-motion: no-preference`.
   ========================================================================== */

@keyframes pr-rise {
  from { opacity: 0; transform: translateY(0.5rem); }
  to   { opacity: 1; transform: none; }
}
@keyframes pr-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes pr-ticker {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
/* A bar establishing its length against its axis — permitted, because it
   reveals the structure of the drawing rather than implying movement in the
   data. Scaled from the axis end, never from the middle. */
@keyframes pr-grow-x {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
@keyframes pr-grow-y {
  from { transform: scaleY(0); }
  to   { transform: scaleY(1); }
}

@media (prefers-reduced-motion: no-preference) {
  .lead__title,
  .page-head__title,
  .article__title { animation: pr-rise var(--dur-settle) var(--ease-settle) both; }

  .lead__summary,
  .article__standfirst { animation: pr-rise var(--dur-settle) var(--ease-settle) 60ms both; }

  .figure { animation: pr-fade var(--dur-settle) var(--ease-settle) both; }

  /* Charts draw once, after the headline has settled, so the page does not
     move in two places at the same time. */
  /* `transform-box: fill-box` is load-bearing, not tidiness. An SVG element's
     transform-origin resolves against the whole view-box by default, so
     `bottom` would mean the bottom of the drawing rather than the foot of this
     bar — and the bar would slide in from the axis instead of growing from it.
     With fill-box each rect scales from its own edge, which is the only
     version of this animation that reveals structure rather than inventing
     movement. */
  .chart__bar { animation: pr-grow-y var(--dur-draw) var(--ease-settle) 120ms both;
                transform-box: fill-box; transform-origin: bottom; }
  .chart__bar--cat { animation-name: pr-grow-x; transform-origin: left; }
  .chart__seg { animation: pr-grow-x var(--dur-draw) var(--ease-settle) 120ms both;
                transform-box: fill-box; transform-origin: left; }
  .chart__mark { animation: pr-fade var(--dur-settle) var(--ease-settle) 380ms both; }

  .ticker__items { animation: pr-ticker 46s linear infinite; }

  .appearance__thumb { transition: transform var(--dur-settle) var(--ease-settle); }
  .search-mini__input { transition: inline-size var(--dur-settle) var(--ease-settle),
                                    border-color var(--dur-swift) var(--ease-settle); }
}


/* ==========================================================================
   5. Masthead and nav
   ========================================================================== */

/* The masthead is a wordmark and three controls, and nothing else. It used to
   carry the tagline and the identity note as well, stacked, which cost roughly
   half the fold on a phone before a reader reached a headline. Both still
   appear in the footer of every page, so what went is the repetition rather
   than the claim. */
.masthead {
  background: var(--paper-raised);
  border-block-end: 1px solid var(--rule);
}
.masthead__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  padding-block: 0.625rem;
}
.masthead__title {
  margin: 0;
  font-family: var(--display); font-weight: 400;
  font-size: clamp(1.0625rem, 0.95rem + 0.55vw, 1.375rem);
  line-height: 1;
  letter-spacing: .2em; text-transform: uppercase;
}
.masthead__title a { color: var(--ink); text-decoration: none; }

.masthead__tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  margin-inline-start: auto;
}
/* RSS and Corrections are quiet text, not bordered pills. At this size a pill
   reads as a call to action, and neither of these is one — they are the two
   places a reader goes to check up on the site rather than to read it. */
.masthead__link {
  display: inline-flex; align-items: center;
  min-height: 2rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-swift) var(--ease-settle);
}
.masthead__link:hover, .masthead__link:focus-visible { color: var(--ink); }

/* Nav. A wrapped list, not a hidden scroller.

   The previous build turned this into a horizontally scrolling strip with the
   scrollbar deliberately hidden and no affordance that anything lay
   off-screen, so on a phone four of the seven sections simply did not exist
   as far as the reader could tell. Wrapping costs a second row at 320px and
   hides nothing, which is the correct trade for a menu. No hamburger: opening
   one needs script, and there is none. */
.nav {
  background: var(--bar-bg);
  color: var(--bar-ink);
}
.nav ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; align-items: center; flex-wrap: wrap;
  column-gap: 1.375rem;
}
.nav a {
  display: flex; align-items: center;
  min-height: 2.75rem;          /* 44px touch target */
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--bar-ink);
  text-decoration: none;
  opacity: .72;
  transition: opacity var(--dur-swift) var(--ease-settle);
}
.nav a:hover, .nav a:focus-visible { opacity: 1; }
.nav a[aria-current="page"] {
  opacity: 1;
  box-shadow: inset 0 -2px 0 0 var(--bar-ink);
}


/* ==========================================================================
   6. Ticker and notices
   ========================================================================== */

/* The ticker is decorative, `aria-hidden`, and repeats /corrections/ in full.
   On a 390px screen it costs a band of the most valuable space on the site
   for information that is already published, in full, one tap away. So it is
   withheld below 48rem and restored above, where the space is cheap. Nothing
   is lost on the phone: the corrections page is the accessible route to the
   same sentences and always has been. */
.ticker { display: none; }

.ticker__inner {
  max-width: var(--container);
  margin-inline: auto;
  display: flex;
  align-items: stretch;
}
.ticker__label {
  margin: 0;
  padding: 0.5rem 1.375rem 0.5rem var(--gutter);
  font-family: var(--serif); font-style: italic;
  font-size: var(--fs-small);
  border-inline-end: 1px solid var(--bar-rule);
  white-space: nowrap;
  display: flex; align-items: center;
}
.ticker__viewport {
  flex: 1 1 auto;
  overflow: hidden;
  display: flex; align-items: center;
}
.ticker__items {
  display: flex; gap: 3.5rem;
  white-space: nowrap;
  padding-inline-start: 1.5rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .10em; text-transform: uppercase;
}

/* A bordered block with a filled label chip. Every state the server can be in
   — demonstration data, private deployment, paused publication, withdrawn,
   historical import, corrected — uses this one treatment, and the chip always
   carries the words rather than relying on a colour to mean something. */
.notice {
  display: flex; flex-wrap: wrap; gap: 0.75rem 1.125rem; align-items: flex-start;
  border: 1px solid var(--ink);
  padding: 0.875rem 1.125rem;
  margin: 0 0 2rem;
}
.notice > .notice__tag {
  flex: 0 0 auto;
  max-width: 21em;
  margin: 0;
  background: var(--ink); color: var(--ink-invert);
  font-family: var(--sans); font-size: var(--fs-label); font-weight: 500;
  line-height: 1.5; letter-spacing: .12em; text-transform: uppercase;
  padding: 0.25rem 0.5rem;
}
.notice__body { margin: 0; flex: 1 1 18em; }
.notice .notice__body p { margin: 0 0 0.625rem; font-size: var(--fs-small); line-height: 1.65; color: var(--ink-body); }
.notice .notice__body p:last-child { margin-block-end: 0; }

/* The quieter note: a coverage caveat, a stale section, an empty one. */
.notice--quiet {
  display: block;
  border: 0;
  border-inline-start: 2px solid var(--ink);
  padding: 0.125rem 0 0.125rem 1.125rem;
  margin: 0 0 1.375rem;
  max-width: 52em;
  font-size: var(--fs-small); line-height: 1.7; color: var(--ink-body);
}
.notice--quiet > p { margin: 0 0 0.625rem; font-size: var(--fs-small); line-height: 1.7; color: var(--ink-body); }
.notice--quiet > p:last-child { margin-block-end: 0; }
.notice--quiet .source-name {
  font-family: var(--sans); font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink);
}


/* ==========================================================================
   7. Page shell, sections, home
   ========================================================================== */

main > .wrap { padding-block-end: 3.5rem; }
.page { padding-block-start: 1.75rem; }
.page > :last-child { margin-block-end: 0; }

.section { margin-block-end: 2.5rem; }
.section:last-child { margin-block-end: 0; }
.section__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  border-block-end: 1px solid var(--ink);
  padding-block-end: 0.625rem;
  margin-block-end: 1.5rem;
}
.section__title {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink);
}
.section__more {
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-soft);
}
.section__more a { color: inherit; text-decoration: none; }
.section__more a:hover { color: var(--ink); }

.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  border-block-end: 1px solid var(--ink);
  padding-block-end: 1rem;
  margin-block-end: 1.75rem;
}
.page-head__title {
  margin: 0;
  font-family: var(--display); font-weight: 400;
  font-size: var(--fs-h1); line-height: 1.1;
}

/* Lead story */
.lead {
  display: grid;
  gap: 1.75rem;
  align-items: start;
  padding-block-end: 2rem;
  border-block-end: 1px solid var(--rule);
}
.lead__kicker {
  margin: 0 0 0.875rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-soft);
}
.lead__title {
  margin: 0 0 1rem;
  font-family: var(--display); font-weight: 400;
  font-size: var(--fs-lead);
  line-height: 1.06; letter-spacing: -0.01em;
}
.lead__title a { text-decoration: none; }
.lead__summary {
  margin: 0 0 1.25rem;
  font-size: var(--fs-lede); line-height: 1.6;
  color: var(--ink-body);
  max-width: 36em;
}

.band {
  display: grid;
  gap: 2.5rem;
  padding-block: 2rem;
  border-block-end: 1px solid var(--rule);
}
.band__aside .section { margin-block-end: 2rem; }

.explainer {
  border: 1px solid var(--ink);
  padding: 1.25rem;
}
.explainer h2 {
  margin: 0 0 0.75rem;
  font-family: var(--display); font-weight: 400;
  font-size: var(--fs-h3); line-height: 1.25;
}
.explainer p { margin: 0 0 0.875rem; font-size: var(--fs-small); line-height: 1.7; color: var(--ink-body); }
.explainer p:last-child { margin-block-end: 0; }

/* The figure grid. Each cell draws its own hairline ring into the 1px gap it
   shares with its neighbour, so the rules read as one ruled table and a short
   last row leaves paper rather than a grey slab. */
.figures {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
}
.figure {
  background: var(--paper);
  box-shadow: 0 0 0 1px var(--rule);
  padding: 1.25rem 1.125rem;
  container-type: inline-size;
}
.figure__kicker {
  margin: 0 0 0.75rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft);
}
/* The Figure: typographic first, chart second. */
.figure__value {
  margin: 0 0 0.625rem;
  font-family: var(--display);
  font-size: var(--fs-figure); line-height: 1;
  font-variant-numeric: lining-nums tabular-nums;
}
.figure__title {
  margin: 0 0 0.75rem;
  font-family: var(--serif); font-weight: 500;
  font-size: var(--fs-small); line-height: 1.5;
}
.figure__title a { text-decoration: none; }
.figure .meta { font-size: var(--fs-label); letter-spacing: .1em; }

.strips { display: grid; grid-template-columns: 1fr; gap: 0 3rem; }
.strips .section { border-block-start: 1px solid var(--rule); padding-block-start: 1.25rem; }


/* ==========================================================================
   8. Brief lists, meta, tags, pills
   ========================================================================== */

.briefs { list-style: none; margin: 0; padding: 0; }
.brief-item {
  padding-block-end: 1.5rem;
  border-block-end: 1px solid var(--rule);
  margin-block-end: 1.5rem;
}
.brief-item:last-child { border-block-end: 0; padding-block-end: 0; margin-block-end: 0; }
.brief-item__title {
  margin: 0 0 0.625rem;
  font-family: var(--display); font-weight: 400;
  font-size: var(--fs-h3); line-height: 1.25;
}
.brief-item__title a { color: var(--ink); text-decoration: none; }
.brief-item__title a:hover { color: var(--ink-soft); }
.brief-item__summary {
  margin: 0 0 0.75rem;
  font-size: var(--fs-small); line-height: 1.7;
  color: var(--ink-body);
}
.brief-item__when {
  margin: 0 0 0.5rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
}
.briefs--feature .brief-item:first-child .brief-item__title { font-size: var(--fs-h2); line-height: 1.2; }
.briefs--compact .brief-item__title { font-size: var(--fs-h3); }

.meta {
  margin: 0;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.5rem 0.75rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-soft);
}
.meta__assembled { font-style: normal; }
/* A meta line that is a sentence rather than a label: same quiet voice, but
   uppercase tracking is for labels and makes running words hard to read. */
.meta--note {
  display: block;
  font-size: var(--fs-meta);
  letter-spacing: .01em;
  text-transform: none;
  line-height: 1.6;
}

.tag {
  display: inline-block;
  font-family: var(--sans);
  font-size: var(--fs-label); line-height: 1.4;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 999px;
  padding: 0.1875rem 0.5rem;
}
/* Withdrawn, our error, stale: the same words, filled rather than outlined.
   Form carries the distinction, so it survives greyscale and dark alike. */
.tag--solid { background: var(--ink); color: var(--ink-invert); }

.pill {
  display: inline-flex; align-items: center;
  min-height: 2.75rem;          /* 44px touch target */
  font-family: var(--sans);
  font-size: var(--fs-label); line-height: 1.2;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 999px;
  padding-inline: 1.125rem;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--dur-swift) var(--ease-settle),
              color var(--dur-swift) var(--ease-settle),
              border-color var(--dur-swift) var(--ease-settle);
}
.pill:hover { background: var(--ink); color: var(--ink-invert); }
.pill--quiet { border-color: var(--rule); color: var(--ink-soft); }
.pill--quiet:hover { background: none; border-color: var(--ink); color: var(--ink); }
.pill--small { min-height: 2.25rem; padding-inline: 0.875rem; }


/* ---------- appearance switch ----------

   Three radios, one `:has()` selector, no script. The thumb slides under the
   chosen option, and the palette above swaps off the same checked state.

   "Auto" is the default and means the operating system decides — which is what
   the site did before this control existed, and what it still does on any page
   where the reader never touches it. Light and Dark override that for the
   current page only. Nothing is stored, because storing it would need either a
   cookie or a line of script, and this site promises the absence of both on
   every page it serves. So the control is honest about what it is: a per-page
   override rather than a saved setting. */

.appearance {
  border: 0; margin: 0; padding: 0; min-width: 0;
  display: flex; align-items: center;
}
.appearance__group {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  border: 1px solid var(--rule);
  border-radius: 999px;
  isolation: isolate;
}
/* Taken out of flow so the three labels occupy the three grid columns. Hidden
   from sight, but not from the keyboard or a screen reader. */
.appearance__input {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.appearance__option {
  grid-row: 1;
  display: flex; align-items: center; justify-content: center;
  /* Compact for a pointer; a full 44px touch target is restored below for
     anything with a coarse pointer. Sizing every control for fingers on a
     desktop is what made this header bulky in the first place. */
  min-height: 1.875rem;
  padding-inline: 0.5rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-soft);
  cursor: pointer;
  white-space: nowrap;
  z-index: 1;
  /* Tight tracking here on purpose. At the header's default .1em this control
     is about 185px wide, which is just past what will sit beside the search
     and the two links on a 390px phone — so it took a third row for the sake
     of thirty pixels. */
  letter-spacing: .04em;
}
.appearance__thumb {
  position: absolute;
  inset-block: 2px;
  inset-inline-start: 2px;
  inline-size: calc((100% - 4px) / 2);
  background: var(--ink);
  border-radius: 999px;
  z-index: 0;
}
/* Before the reader has chosen anything, the switch shows the scheme the
   operating system is giving them — sitting on Light by default, and moved to
   Dark by the same media query that darkens the page. This is the only way the
   control can start out telling the truth: `checked` is server-written and the
   server cannot see `prefers-color-scheme`.

   For the right-to-left work later: these are physical translations and will
   need mirroring, because the thumb tracks grid columns rather than logical
   order. */
.appearance__group:not(:has(.appearance__input:checked)) .appearance__thumb {
  transform: translateX(0);
}
.appearance__group:not(:has(.appearance__input:checked)) .appearance__option[for="ap-light"] {
  color: var(--ink-invert);
}
@media (prefers-color-scheme: dark) {
  .appearance__group:not(:has(.appearance__input:checked)) .appearance__thumb {
    transform: translateX(100%);
  }
  .appearance__group:not(:has(.appearance__input:checked)) .appearance__option[for="ap-light"] {
    color: var(--ink-soft);
  }
  .appearance__group:not(:has(.appearance__input:checked)) .appearance__option[for="ap-dark"] {
    color: var(--ink-invert);
  }
}

/* Once either is pressed it is an explicit override and outranks the above. */
.appearance__group:has(#ap-light:checked) .appearance__thumb { transform: translateX(0); }
.appearance__group:has(#ap-dark:checked)  .appearance__thumb { transform: translateX(100%); }

#ap-light:checked ~ .appearance__option[for="ap-light"],
#ap-dark:checked  ~ .appearance__option[for="ap-dark"] {
  color: var(--ink-invert);
}
.appearance__input:focus-visible + .appearance__option {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  border-radius: 999px;
}

/* Touch. The tap targets go back to 44px wherever the pointer is a finger,
   which is the condition the rule actually cares about — not screen width. */
@media (pointer: coarse) {
  .appearance__option { min-height: 2.75rem; padding-inline: 0.5rem; }
  .search-mini__input { min-block-size: 2.75rem; inline-size: 2.75rem; }
  .search-mini__go { min-block-size: 2.75rem; }
  .masthead__link { min-height: 2.75rem; }
}


/* ==========================================================================
   9. Article, rail, panels
   ========================================================================== */

.article__kicker {
  margin: 0 0 0.875rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-soft);
}
.article__title {
  margin: 0 0 1.125rem;
  font-family: var(--display); font-weight: 400;
  font-size: var(--fs-h1);
  line-height: 1.08;
  max-width: 18em;
}
.article__columns { display: grid; gap: 2rem; align-items: start; }
.article__standfirst {
  margin: 0 0 1.5rem;
  font-size: var(--fs-lede); line-height: 1.55;
  font-style: italic;
  color: var(--ink-body);
}
.article__body p { margin: 0 0 1.125rem; font-size: var(--fs-prose); line-height: 1.75; }
.article__body p:last-child { margin-block-end: 2rem; }

/* The provenance rail. Not a byline: a brief has no author, so this carries
   where the page came from instead. On a phone it is a bordered block above
   the panels; on a wide screen it becomes a sticky column beside them. */
.rail {
  border: 1px solid var(--rule);
  padding: 1.25rem;
  margin-block-end: 2rem;
}
.rail__label {
  margin: 0 0 0.25rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft);
}
.rail__value { margin: 0 0 1.125rem; font-size: var(--fs-small); line-height: 1.6; }
.rail__value.mono { font-family: var(--mono); font-size: var(--fs-meta); overflow-wrap: anywhere; }

.panel {
  border-block-start: 1px solid var(--ink);
  padding-block-start: 1.25rem;
  margin: 0 0 2rem;
}
.panel:last-child { margin-block-end: 0; }
.panel--measure { max-width: var(--measure); }
.panel h2 {
  margin: 0 0 1rem;
  font-family: var(--sans);
  font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase;
}
.panel__note { margin: -0.5rem 0 1rem; font-size: var(--fs-small); line-height: 1.6; color: var(--ink-soft); }
.panel p { font-size: var(--fs-small); line-height: 1.75; color: var(--ink-body); }
.panel > p { margin: 0 0 1rem; }
.panel > p:last-child { margin-block-end: 0; }
.panel__foot code { font-family: inherit; font-size: inherit; }
.panel__foot {
  margin: 1.125rem 0 0;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-soft);
}

/* The limits block. Promoted from a paragraph at the foot to a designed,
   recurring element with as much visual authority as the figure itself —
   what a record does not establish is the claim this publication is actually
   making, and it should not look like a disclaimer. */
.panel--limits {
  border: 1px solid var(--ink);
  border-block-start-width: 3px;
  padding: 1.25rem;
}
.panel--limits h2 { font-size: var(--fs-label); }
.panel--limits > p { color: var(--ink); }
.panel--limits > p:first-of-type { font-size: var(--fs-small); }


/* ==========================================================================
   10. Evidence, tables, revisions
   ========================================================================== */

.kv { margin: 0 0 1.25rem; }
.kv:last-child { margin-block-end: 0; }
.kv div {
  display: flex; flex-direction: column; gap: 0.25rem;
  padding-block: 0.625rem;
  border-block-end: 1px solid var(--rule);
}
.kv dt {
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
}
.kv dd { margin: 0; font-size: var(--fs-small); overflow-wrap: anywhere; }
.kv dd.mono, .kv dd .mono { font-family: var(--mono); font-size: var(--fs-meta); }
.kv dd .meta { display: inline; font-size: var(--fs-label); }

details > summary {
  cursor: pointer;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink);
  min-height: 2.75rem;
  display: flex; align-items: center;
}
details[open] > summary { margin-block-end: 1rem; }

table.data { border-collapse: collapse; width: 100%; font-size: var(--fs-small); }
table.data th, table.data td { text-align: start; padding: 0.5625rem 0.75rem; vertical-align: top; }
table.data th:first-child, table.data td:first-child { padding-inline-start: 0; }
table.data th:last-child, table.data td:last-child { padding-inline-end: 0; }
table.data th {
  font-family: var(--sans);
  font-size: var(--fs-label); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-soft);
  border-block-end: 1px solid var(--ink);
}
table.data td { border-block-end: 1px solid var(--rule); }
table.data td.origin { color: var(--ink-soft); }
table.data td.mono { font-family: var(--mono); font-size: var(--fs-meta); }

table.status { font-size: var(--fs-small); }
table.status td { padding-block: 0.875rem; }
table.status .when { color: var(--ink-body); }

/* The evidence table, re-formed as cards on a small screen.

   This is the site's central promise, and sideways scrolling through it was
   the least usable element on the device most people read it on. Below 48rem
   each row becomes a card carrying one value — what it is, as published,
   where it came from — with the column headers reattached to each cell from
   `data-label`, so nothing depends on a header row that has scrolled away. */
@media (max-width: 47.999rem) {
  table.data--evidence,
  table.data--evidence thead,
  table.data--evidence tbody,
  table.data--evidence tr,
  table.data--evidence td { display: block; width: 100%; }

  table.data--evidence thead {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  table.data--evidence tr {
    border: 1px solid var(--rule);
    padding: 0.875rem 1rem;
    margin-block-end: 0.75rem;
  }
  table.data--evidence td {
    border-block-end: 0;
    padding: 0.375rem 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.125rem;
  }
  table.data--evidence td::before {
    content: attr(data-label);
    font-family: var(--sans);
    font-size: var(--fs-label);
    letter-spacing: .12em; text-transform: uppercase;
    color: var(--ink-soft);
  }
  /* The value this row is about, given the weight it deserves. */
  table.data--evidence td[data-label="As published"] {
    font-family: var(--display);
    font-size: var(--fs-h3);
    line-height: 1.2;
  }
}

/* A container that really must scroll sideways says so, rather than hiding it.
   The mask is driven by a scroll-timeline on the container itself: pure CSS,
   no script, and — unlike a decorative reveal — this is a function. The fade
   on each edge is present exactly when there is content past it. */
.table-scroll {
  overflow-x: auto;
  margin-block-start: 1rem;
  scrollbar-width: thin;
}
@supports (animation-timeline: scroll(self inline)) {
  @media (prefers-reduced-motion: no-preference) {
    .table-scroll {
      animation: pr-scroll-hint linear both;
      animation-timeline: scroll(self inline);
    }
    @keyframes pr-scroll-hint {
      from { mask-image: linear-gradient(to right, #000 0 88%, transparent 100%); }
      to   { mask-image: linear-gradient(to right, transparent 0, #000 12% 100%); }
    }
  }
}

.revisions { list-style: none; margin: 0; padding: 0; }
/* Our own errors and upstream revisions must stay distinguishable by form,
   not only by the label text: a solid rule for a change the source made, a
   doubled rule for one we made. */
.revision {
  border-inline-start: 2px solid var(--ink);
  padding-inline-start: 1.125rem;
  margin: 0 0 1.75rem;
}
.revision:last-child { margin-block-end: 0; }
.revision:has(.tag--solid) {
  border-inline-start-style: double;
  border-inline-start-width: 6px;
}
.revision__head {
  margin: 0 0 0.5rem;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.75rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
}
.revision__note { margin: 0 0 0.875rem; font-size: var(--fs-small); line-height: 1.7; }
.revision__note:last-child { margin-block-end: 0; }
.revision__previous {
  border: 1px solid var(--rule);
  padding: 1rem;
  margin: 0.75rem 0 0;
  color: var(--ink-body);
  background: var(--paper-sunk);
}
.revision__previous p { margin: 0 0 0.625rem; font-size: var(--fs-small); line-height: 1.6; }
.revision__previous p:last-child { margin-block-end: 0; }
.revision__previous-headline { font-family: var(--display); font-size: var(--fs-h3); line-height: 1.3; }

code { font-family: var(--mono); font-size: var(--fs-meta); overflow-wrap: anywhere; }


/* ==========================================================================
   11. Charts

   Geometry is written into presentation attributes by a Django template
   server-side; only colour, weight and motion are set here. That split is
   what lets one drawing serve both colour schemes: `currentColor` follows
   `--chart-ink`, so nothing has to be re-measured for the dark page.

   No hue anywhere. Series separate by fill pattern, stroke weight and
   outline, which survives greyscale, every form of colour blindness, and a
   printer. Colour may not encode a category or an outcome.
   ========================================================================== */

.chart {
  margin: 0 0 1.75rem;
  padding: 1.125rem;
  border: 1px solid var(--rule);
  background: var(--paper-raised);
}
.chart__svg {
  display: block;
  width: 100%; height: auto;
  max-width: 34rem;       /* never scale the drawn type below its designed size */
  margin-inline: auto;
  color: var(--chart-ink);
  overflow: visible;
}
.chart__svg--short { max-width: 30rem; }

.chart__axis   { stroke: var(--chart-ink); fill: none; }
.chart__grid   { stroke: var(--ink-soft); fill: none; opacity: .5; }
.chart__frame  { stroke: var(--chart-ink); fill: none; }
/* The key swatch repeats the fill it names, so it must let the `fill`
   presentation attribute through. A CSS `fill` here — even `none` — would
   override it, because presentation attributes carry no specificity at all. */
.chart__swatch { stroke: var(--chart-ink); }
.chart__mark   { stroke: var(--chart-ink); fill: none; stroke-linecap: square; }
.chart__hypo   { fill: var(--chart-ink); }
.chart__hatch  { stroke: var(--chart-ink); }
.chart__dot    { fill: var(--chart-ink); }
.chart__patternbg { fill: var(--chart-ground); }

.chart__bar        { fill: var(--chart-ink); }
.chart__bar--prev  { fill: var(--chart-ground); stroke: var(--chart-ink); stroke-width: 1; }
.chart__bar--curr  { fill: var(--chart-ink); }

.chart__label, .chart__tick, .chart__value, .chart__pp {
  font-family: var(--sans);
  fill: var(--chart-ink);
  /* Knock the type out of anything it crosses. A depth label sits close to a
     gridline by definition — the whole point is that it marks a position — so
     the text carries a halo in the page colour and stays legible where it
     lands on a rule. Drawn under the fill, so the letterforms are untouched. */
  paint-order: stroke fill;
  stroke: var(--chart-ground);
  stroke-width: 4px;
  stroke-linejoin: round;
}
/* 14px at the designed width is the floor for anything a reader has to read
   off the drawing. Nothing here goes below it. */
.chart__tick  { font-size: 14px; fill: var(--ink-soft); }
.chart__label { font-size: 14px; }
.chart__value { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
.chart__value--big { font-size: 20px; }
.chart__pp    { font-size: 14px; font-weight: 600; }

.chart__cap {
  margin: 1rem 0 0;
  font-size: var(--fs-small);
  line-height: 1.65;
  color: var(--ink-body);
  max-width: 44em;
}
.chart__cap b { color: var(--ink); font-weight: 600; }

/* The percentage-point explainer. The summary states the rule outright, so a
   reader who never opens it has still been told the thing that matters. */
.pp { border: 1px solid var(--ink); padding: 0 1.125rem; margin: 0 0 1.75rem; }
.pp__summary {
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  padding-block: 0.75rem;
}
.pp__body { padding-block-end: 1.125rem; }
.pp__lede { margin: 0 0 1rem; font-size: var(--fs-small); line-height: 1.7; color: var(--ink-body); }
.pp__svg { display: block; width: 100%; height: auto; max-width: 30rem; margin: 0 auto 1rem; color: var(--chart-ink); }
.pp__pair { margin: 0 0 1rem; }
.pp__pair div { padding-block: 0.625rem; border-block-end: 1px solid var(--rule); }
.pp__pair dt {
  font-family: var(--sans); font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft);
  margin-block-end: 0.25rem;
}
.pp__pair dd { margin: 0; font-size: var(--fs-small); line-height: 1.6; }
.pp__foot { margin: 0; font-size: var(--fs-meta); line-height: 1.7; color: var(--ink-soft); }

/* The provenance marker: ties a value in the prose to its row in the evidence
   table without altering one word of the published sentence, which comes from
   an immutable versioned template and cannot be re-punctuated to suit a
   design. So the marker sits *around* the value, never inside the wording. */
.pmark {
  font-variant-numeric: tabular-nums;
  box-shadow: inset 0 -0.35em 0 0 var(--paper-sunk);
  text-decoration: none;
  color: inherit;
  border-block-end: 1px solid var(--ink-soft);
}
.pmark:hover, .pmark:focus-visible { box-shadow: inset 0 -0.35em 0 0 var(--rule); color: inherit; }

/* Following a marker lands on the row it names, and the row says so. Without
   this the reader arrives somewhere in a table of five near-identical rows
   with no indication which one answered their question. */
table.data--evidence tr { scroll-margin-block-start: 1.5rem; }
table.data--evidence tr:target { outline: 2px solid var(--ink); outline-offset: 3px; }
table.data--evidence tr:target td:first-child { font-weight: 600; }


/* ==========================================================================
   12. Prose pages, sources, corrections, pager, search
   ========================================================================== */

.prose { max-width: var(--measure); }
.prose--wide { max-width: 52em; }
.prose--table { max-width: 60em; }
.prose--full { max-width: none; }
.prose h1 {
  margin: 0 0 1.25rem;
  font-family: var(--display); font-weight: 400;
  font-size: var(--fs-h1); line-height: 1.08;
}
.prose > p:first-of-type, .prose .prose__lede { font-size: var(--fs-lede); line-height: 1.7; color: var(--ink-body); }
.prose h2 {
  margin: 2.25rem 0 0.75rem;
  font-family: var(--sans);
  font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase;
  border-block-end: 1px solid var(--ink);
  padding-block-end: 0.625rem;
}
.prose h3 { margin: 1.75rem 0 0.5rem; font-family: var(--display); font-weight: 400; font-size: var(--fs-h3); line-height: 1.3; }
.prose p { margin: 0 0 1.125rem; font-size: var(--fs-prose); line-height: 1.75; }
.prose ul, .prose ol { padding-inline-start: 1.3rem; }
.prose li { margin-block-end: .4rem; font-size: var(--fs-prose); line-height: 1.75; }
.prose blockquote {
  margin: 2rem 0;
  padding-inline-start: 1.5rem;
  border-inline-start: 2px solid var(--ink);
  font-family: var(--display);
  font-size: var(--fs-h3); line-height: 1.45;
  color: var(--ink);
}
.prose .meta { margin-block-end: 1.125rem; }
.prose p.status__note { margin: 1.75rem 0 0; font-size: var(--fs-small); line-height: 1.7; color: var(--ink-body); max-width: 44em; }
.prose + .table-scroll { margin-block-start: 1.375rem; }

ol.steps { list-style: none; margin: 0 0 1.125rem; padding: 0; }
ol.steps li {
  display: grid;
  grid-template-columns: 2.125rem minmax(0, 1fr);
  gap: 0.75rem;
  padding-block: 0.875rem;
  margin: 0;
  border-block-end: 1px solid var(--rule);
  font-size: var(--fs-small); line-height: 1.7;
}
.steps .steps__n { font-family: var(--display); font-size: var(--fs-h3); line-height: 1.2; color: var(--ink-soft); }
.steps strong, ol.steps strong { font-weight: 600; }

ul.rows { list-style: none; margin: 0 0 1.125rem; padding: 0; }
ul.rows li { padding-block: 0.875rem; margin: 0; border-block-end: 1px solid var(--rule); font-size: var(--fs-small); line-height: 1.7; }

ul.rows.section-index li, ul.rows.archive-months li {
  display: flex; justify-content: space-between; gap: 0.875rem;
  align-items: baseline;
  min-height: 2.75rem;
}
.section-index__count, .archive-months__count {
  font-family: var(--sans); font-size: var(--fs-label);
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-soft); text-align: end; flex: 0 0 auto;
}

.source-entry {
  display: grid;
  gap: 1.25rem;
  align-items: start;
  padding-block: 1.75rem;
  border-block-start: 1px solid var(--ink);
  margin: 0;
}
.source-entry__name { margin: 0 0 0.625rem; font-family: var(--display); font-weight: 400; font-size: var(--fs-h2); line-height: 1.2; }
.source-entry__counts {
  margin: 0 0 0.375rem;
  font-family: var(--sans); font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
}
.source-entry__note { margin: 0 0 1rem; font-size: var(--fs-small); line-height: 1.75; color: var(--ink-body); }
.source-entry__terms { margin: 0; font-size: var(--fs-meta); line-height: 1.75; color: var(--ink-soft); }
.source-entry .kv { margin-block-start: 1rem; }

ul.revision-list { list-style: none; margin: 0; padding: 0; }
ul.revision-list li {
  display: grid; gap: 0.5rem;
  align-items: start;
  padding-block: 1.375rem;
  border-block-end: 1px solid var(--rule);
}
ul.revision-list .revision-list__when {
  margin: 0;
  font-family: var(--sans); font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
}
h3.revision-list__title { margin: 0 0 0.5rem; font-family: var(--display); font-weight: 400; font-size: var(--fs-h3); line-height: 1.3; }
.revision-list__title a { text-decoration: none; }
ul.revision-list .revision-list__note { margin: 0; font-size: var(--fs-small); line-height: 1.7; color: var(--ink-body); }

/* The empty state is deliberately large and plain: nothing met the selection
   rules, and nothing is substituted to fill the space. */
p.empty-state { margin: 0 0 2.5rem; font-family: var(--display); font-size: var(--fs-h2); line-height: 1.35; color: var(--ink-soft); }

.pager {
  display: flex; gap: 1rem;
  align-items: center; justify-content: space-between;
  padding-block-start: 1.25rem;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
}
.pager a { display: inline-flex; align-items: center; min-height: 2.75rem; color: var(--ink); text-decoration: none; }
.pager a:hover { text-decoration: underline; }

/* Search that opens when you press it, with no script to open it.

   The input is always a real, focusable, announced control — it just starts
   narrow enough to show only the magnifier, and `:focus` widens it. It also
   stays open while it holds a query, so arriving at /search/ with a term does
   not present a shut field next to a page of results for it.

   The icon is painted over the field's own inline-start padding and takes no
   pointer events, so a press anywhere on the control lands on the input. It
   is inline SVG using `currentColor` rather than a background image, because a
   `data:` URI would bake one ink colour in and stop following the scheme. */
.search-mini {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.25rem;
}
.search-mini__icon {
  position: absolute;
  inset-inline-start: 0.5rem;
  color: var(--ink-soft);
  pointer-events: none;
  transition: color var(--dur-swift) var(--ease-settle);
}
.search-mini:focus-within .search-mini__icon { color: var(--ink); }

.search-mini__input {
  font-family: var(--sans); font-size: var(--fs-small);
  inline-size: 2.25rem;
  min-inline-size: 0;
  min-block-size: 2rem;
  padding-inline: 1.9rem 0;
  color: var(--ink);
  background: none;
  border: 1px solid transparent;
  border-radius: 999px;
  -webkit-appearance: none; appearance: none;
  cursor: pointer;
}
.search-mini__input:focus { outline: 0; cursor: text; }
.search-mini__input::-webkit-search-cancel-button { -webkit-appearance: none; }
/* The placeholder would otherwise peek out of the shut field. */
.search-mini__input::placeholder { color: transparent; }
.search-mini__input:focus::placeholder { color: var(--ink-soft); }

.search-mini__input:focus,
.search-mini__input:not(:placeholder-shown) {
  inline-size: min(11rem, 42vw);
  padding-inline-end: 0.625rem;
  border-color: var(--rule);
  background: var(--paper);
}

/* The submit button only exists once the field is open. Shut, it would be a
   button that searches for nothing. Enter submits either way. */
.search-mini__go {
  font-family: var(--sans); font-size: var(--fs-label);
  text-transform: uppercase; letter-spacing: .08em;
  inline-size: 0; padding: 0; border: 0;
  overflow: hidden; opacity: 0;
  min-block-size: 2rem; cursor: pointer;
  color: var(--ink-invert); background: var(--ink);
  border-radius: 999px;
  white-space: nowrap;
}
.search-mini:focus-within .search-mini__go,
.search-mini:has(.search-mini__input:not(:placeholder-shown)) .search-mini__go {
  inline-size: auto; padding-inline: 0.75rem; opacity: 1;
}


/* The full search form on /search/. Submits a GET to this origin, which the
   reader-page CSP permits through `form-action 'self'` — the single directive
   in that header that is not 'none'. */
.search {
  display: flex; flex-wrap: wrap; gap: 0.875rem; align-items: flex-end;
  padding-block: 1.375rem; margin: 0 0 0.625rem;
  border-block-start: 1px solid var(--ink); border-block-end: 1px solid var(--rule);
}
.search__row { display: flex; flex-direction: column; gap: 0.375rem; flex: 1 1 14rem; }
.search__label { font-family: var(--sans); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: .08em; color: var(--ink-soft); }
.search__input, .search__select {
  font-family: var(--serif); font-size: var(--fs-small);
  padding: 0.625rem 0.75rem; min-height: 2.75rem; width: 100%;
  color: var(--ink); background: var(--paper-raised);
  border: 1px solid var(--ink); border-radius: 0;
}
.search__select { font-family: var(--sans); }
.search__go {
  font-family: var(--sans); font-size: var(--fs-meta);
  text-transform: uppercase; letter-spacing: .08em;
  padding-inline: 1.25rem; min-height: 2.75rem; cursor: pointer;
  color: var(--ink-invert); background: var(--ink);
  border: 1px solid var(--ink); border-radius: 0;
}
.prose p.search__count { font-size: var(--fs-small); color: var(--ink-body); }

/* The box a picture would occupy if one were ever attached. The service
   publishes no imagery, so nothing renders it today. */
.photo-slot {
  aspect-ratio: 4 / 3; width: 100%;
  border: 1px solid var(--rule);
  background: repeating-linear-gradient(135deg, var(--paper-sunk) 0 10px, var(--rule) 10px 20px);
  filter: grayscale(1);
  display: flex; align-items: flex-end; padding: 1rem;
}
.photo-slot img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(1); }
.photo-slot figcaption, .photo-slot__caption {
  font-family: var(--mono); font-size: var(--fs-meta);
  color: var(--ink-soft); background: var(--paper); padding: 0.375rem 0.625rem;
}


/* ==========================================================================
   13. Footer
   ========================================================================== */

.footer { background: var(--bar-bg); color: var(--bar-ink); border-block-start: 1px solid var(--bar-rule); }
.footer__row {
  max-width: var(--container);
  margin-inline: auto;
  padding: 2.5rem var(--gutter) max(2.5rem, env(safe-area-inset-bottom));
  display: grid; gap: 2rem;
}
.footer__wordmark { margin: 0 0 1rem; font-family: var(--display); font-size: var(--fs-h3); line-height: 1; letter-spacing: .2em; text-transform: uppercase; }
.footer__where { margin: 0; font-family: var(--serif); font-style: italic; font-size: var(--fs-small); color: var(--bar-ink-soft); }
.footer ul {
  list-style: none;
  display: flex; flex-wrap: wrap;
  gap: 0 1.5rem;
  margin: 0 0 1.25rem; padding: 0;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase;
}
.footer li { flex: 0 0 auto; }
.footer a {
  display: inline-flex; align-items: center; min-height: 2.75rem;
  color: var(--bar-ink); text-decoration: none;
  opacity: .8;
  transition: opacity var(--dur-swift) var(--ease-settle);
}
.footer a:hover, .footer a:focus-visible { opacity: 1; }
.footer p { margin: 0 0 0.75rem; font-size: var(--fs-small); line-height: 1.7; color: var(--bar-ink-soft); max-width: 46em; }
.footer p:last-child { margin-block-end: 0; }


/* ==========================================================================
   14. Wider screens

   Every rule below is a `min-width` addition. The previous build expressed
   every breakpoint as a `max-width`, which made the layout subtractive: the
   phone got whatever survived the desktop design rather than what mattered
   most. Read from here down as "what a larger screen earns", not "what a
   small one loses".
   ========================================================================== */

@media (min-width: 30rem) {
  :root { --gutter: 1.5rem; }
  .figures { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
}

@media (min-width: 48rem) {
  :root { --gutter: 2rem; }

  .masthead__row { padding-block: 0.75rem; gap: 0.5rem 1.5rem; }
  .masthead__tools { gap: 0.5rem 1.25rem; }

  /* Space is cheap here, so the ticker returns. */
  .ticker {
    display: block;
    background: var(--bar-bg);
    color: var(--bar-ink);
    border-block-start: 1px solid var(--bar-rule);
    overflow: hidden;
  }

  .briefs--rail .brief-item {
    display: grid;
    grid-template-columns: 9rem minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
  }
  .briefs--rail .brief-item__when { margin-block-end: 0; }

  ul.revision-list li { grid-template-columns: 10.5rem minmax(0, 1fr); gap: 1.75rem; }

  .kv div { flex-direction: row; gap: 1.25rem; }
  .kv dt { flex: 0 0 10.5rem; padding-block-start: 0.1875rem; }
  .kv dd { flex: 1 1 auto; }

  .source-entry { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 2.5rem; }
  .footer__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); gap: 3.5rem; }
  .strips { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .chart { padding: 1.5rem; }
}

@media (min-width: 64rem) {
  .lead { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 3rem; }
  .lead:not(:has(.photo-slot)) { grid-template-columns: minmax(0, 1fr); }
  .band { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 3rem; padding-block: 2.5rem; }
  .strips { gap: 0 3rem; }
}

@media (min-width: 69rem) {
  .article__columns { grid-template-columns: minmax(0, 1fr) 16rem; gap: 3.5rem; }
  /* The rail becomes a column beside the article and loses its box: the
     white space and the top rule do the work the border was doing. */
  .rail {
    border: 0;
    border-block-start: 1px solid var(--ink);
    padding: 1.125rem 0 0;
    margin-block-end: 0;
    position: sticky; top: 1.25rem;
  }
}

/* A reader at 200% text scaling on a phone is at roughly this width in ems.
   Nothing may overflow horizontally, so the two-up chart columns collapse. */
@media (max-width: 24rem) {
  .chart { padding: 0.875rem; }
  .pill { padding-inline: 0.875rem; }
}


/* ==========================================================================
   15. Print

   A brief is evidence, and evidence gets printed — including from a phone.
   The furniture goes, the provenance stays, and link targets are written out
   so a printed page remains checkable.
   ========================================================================== */

@media print {
  :root {
    --paper: #fff; --paper-raised: #fff; --paper-sunk: #fff;
    --ink: #000; --ink-body: #000; --ink-soft: #333;
    --rule: #bbb; --chart-ink: #000; --chart-ground: #fff;
    --bar-bg: #fff; --bar-ink: #000; --bar-ink-soft: #333;
  }
  .nav, .ticker, .footer ul, .skip, .masthead__links, .pager, .appearance { display: none; }
  body { background: #fff; font-size: 11pt; }
  .masthead, .footer { background: none; color: #000; }
  .footer p, .footer__where { color: #000; }
  .rail { position: static; border: 1px solid #bbb; padding: 1rem; }
  .article__columns { display: block; }
  .chart { break-inside: avoid; border: 1px solid #bbb; }
  .chart__svg { max-width: 12cm; }
  /* Open every disclosure: the evidence must be on the paper, not behind a
     control that paper does not have. */
  details > summary { display: none; }
  details > div, details > .revision__previous { display: block !important; }
  .panel, .revision, figure, table { break-inside: avoid; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; color: #333; word-break: break-all; }
}
