/* ==========================================================================
   scorza4fairfax.com
   One stylesheet. No framework. Light is the reference design; dark mode
   swaps custom properties only.
   Every color pair in here is verified by contrast.py. Run it after any
   palette edit: python3 contrast.py
   ========================================================================== */

/* ---------------------------------------------------------------- fonts */
@font-face {
  font-family: "Fraunces";
  src: url("/assets/fonts/Fraunces-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Public Sans";
  src: url("/assets/fonts/PublicSans-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---------------------------------------------------------------- tokens */
:root {
  --bg: #FBF8F3;
  --surface: #FFFFFF;
  --text: #1F241F;
  --muted: #55604F;
  --primary: #1F4D3A;
  --primary-2: #2A6B50;
  --accent: #1D4E89;      /* deep civic blue */
  --accent-lt: #2E6BB0;   /* decorative only, never used for text */
  --rule: #E3DCCF;        /* decorative hairlines only */
  --border: #8A8578;      /* anything that is an actual UI boundary */
  --focus: #1D4E89;
  --on-primary: #FFFFFF;
  --on-accent: #FFFFFF;
  --tint: #F2EEE5;        /* quiet fill for boxes */

  /* Chart palette. Six colors, all dark enough to carry white text at 5.6:1
     or better, all sitting in the same earthy family as the brand so nothing
     clashes. Verified by contrast.py; do not add a seventh by eye. */
  --c1: #1F4D3A;   /* forest, same as primary */
  --c2: #1D4E89;   /* blue, same as accent */
  --c3: #6A3557;   /* plum */
  --c4: #7E6410;   /* ochre */
  --c5: #6B6255;   /* warm stone, the "everything else" neutral */
  --c6: #17555F;   /* deep teal, spare */
  --on-chart: #FFFFFF;
  /* Warm gold. Only ever used on a dark ground, where it clears 8:1. It would
     fail badly as text on cream, so it is not a general accent. */
  --warm: #F4C89A;
  /* Semantic, not brand. These two mean fire and water and nothing else. */
  --fire: #A82D19;
  --flood: #1D4E89;
  --asphalt: #3B403C;
  --asphalt-bad: #575D57;
  --pict-short: #DFA394;   /* the homes that do not exist yet */

  --serif: "Fraunces", Georgia, "Iowan Old Style", "Times New Roman", serif;
  --sans: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;

  --s1: 8px;  --s2: 16px; --s3: 24px; --s4: 32px;
  --s5: 48px; --s6: 64px; --s7: 96px;

  /* A width, not a character count. 880px at this size and line height is a
     long but comfortable line, and it is what the two-column issue pages
     already produce. Using it everywhere keeps the two layouts consistent. */
  --measure: 1000px;
  /* Fill the screen rather than sitting in a 1240px box with 200px of nothing
     on either side. Text stays at --measure; charts, tiles and timelines get
     the whole width, which makes them shorter as well as bigger. */
  --wide: min(94vw, 1520px);
  --radius: 4px;
}

/* Light is the design. Dark is available from the control in the header and
   is remembered, but the site no longer follows the operating system on its
   own: landing in the wrong one was worse than not offering it. */

:root[data-theme="dark"] {
  --bg: #15180F;
  --surface: #1E2219;
  --text: #F2EFE6;
  --muted: #B6BFAF;
  --primary: #8FD6AE;
  --primary-2: #B4E7C9;
  --accent: #8FBEE8;
  --accent-lt: #8FBEE8;
  --rule: #333A2E;
  --border: #6E7A66;
  --focus: #8FBEE8;
  --on-primary: #10140D;
  --on-accent: #10140D;
  --tint: #232819;
  --c1: #8FD6AE;
  --c2: #8FBEE8;
  --c3: #D9A3C6;
  --c4: #DDBE63;
  --c5: #C3B8A6;
  --c6: #84CBD8;
  --on-chart: #10140D;
  --fire: #F09080;
  --flood: #8FBEE8;
  --asphalt: #2B302C;
  --asphalt-bad: #454B46;
  --pict-short: #7E4A3E;
}

/* ---------------------------------------------------------------- reset */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

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

body {
  margin: 0;
  background: var(--bg);          /* explicit, never transparent */
  color: var(--text);
  font-family: var(--sans);
  /* rem, not px, so a reader who has raised their browser's default text size
     actually gets it. 1.125rem is 18px at the default. */
  font-size: 1.125rem;
  line-height: 1.65;
  overflow-x: hidden;             /* the page body never scrolls sideways */
}

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

h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 600;
  line-height: 1.14;
  color: var(--primary);
  margin: 0 0 var(--s2);
  text-wrap: balance;
  /* Fraunces carries an optical size axis. Large type wants the display cut
     (tighter, higher contrast); small type wants the text cut. */
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 40;
  font-optical-sizing: auto;
}
h1 { font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 120; }
h3, h4 { font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 20; }
h1 { font-size: clamp(2.1rem, 1.5rem + 3vw, 3.4rem); letter-spacing: -0.022em; }
h2 { font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.1rem); margin-top: var(--s5); letter-spacing: -0.012em; }
h3 { font-size: clamp(1.2rem, 1.1rem + 0.6vw, 1.45rem); margin-top: var(--s3); }
h4 { font-size: 1.1rem; margin-top: var(--s3); }

p, ul, ol { margin: 0 0 var(--s2); }
li { margin-bottom: var(--s1); }

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent);
  transition: text-decoration-color 120ms ease, color 120ms ease;
}
a:hover { color: var(--primary); text-decoration-color: currentColor; }

strong { font-weight: 600; }

/* ----------------------------------------------------------- focus, skip */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;   /* the gap shows --bg, so the ring never has to
                            contrast with the element fill underneath it */
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: var(--s2);
  top: -100px;
  z-index: 100;
  background: var(--primary);
  color: var(--on-primary);
  padding: 12px var(--s3);
  border-radius: var(--radius);
  font-weight: 600;
  text-decoration: none;
  transition: top 120ms ease;
}
.skip-link:focus { top: var(--s2); color: var(--on-primary); }

/* --------------------------------------------------------------- layout */
.wrap { width: 100%; max-width: var(--wide); margin: 0 auto; padding: 0 var(--s3); }

.prose > * { max-width: var(--measure); }
.prose > h1 { max-width: 20ch; }
.prose > .standfirst { max-width: 52ch; }

/* On a page with no rail, run a content grid: everything shares one text
   column with even gutters, and the wide blocks span the whole container.
   Centring individual elements instead left the h1 hard against the left edge
   while the paragraphs under it sat 150px inboard, which looked like a bug
   because it was one. */
@media (min-width: 1080px) {
  .wrap.prose {
    display: grid;
    grid-template-columns: 1fr min(var(--measure), 100%) 1fr;
  }
  .wrap.prose > * { grid-column: 2; }
  /* Grid does not collapse adjacent margins the way normal flow does, so a
     paragraph's 16px bottom and a heading's top margin now stack instead of
     overlapping. Trim the tops to get the old rhythm back. */
  .wrap.prose > h2 { margin-top: var(--s3); }
  .wrap.prose > h3 { margin-top: var(--s2); }
  .wrap.prose > .chart,
  .wrap.prose > .timeline,
  .wrap.prose > .tiles { margin-top: var(--s2); }
  .wrap.prose > .bio { grid-column: 2 / -1; }
  .wrap.prose > .hero-grid,
  .wrap.prose > .tiles,
  .wrap.prose > .chart,
  .wrap.prose > .form,
  .wrap.prose > .timeline,
  .wrap.prose > .stat,
  .wrap.prose > .box,
  .wrap.prose > .bio,
  .wrap.prose > .wrong,
  .wrap.prose > .pager,
  .wrap.prose > #donate,
  .wrap.prose > #endorsements { grid-column: 1 / -1; }
}
.prose > .tiles,
.prose > .hero-figure,
.prose > .stat,
.prose > .box,
.prose > .wrong,
.prose > .form,
.prose > #donate,
.prose > #endorsements,
.prose > .hero-actions { max-width: none; }

main { padding: var(--s4) 0 var(--s6); }

/* --------------------------------------------------------------- header */
.site-header {
  border-bottom: 1px solid var(--rule);
  background: var(--bg);
  position: relative;
}
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  min-height: 76px;
  flex-wrap: wrap;
}
.brand {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: var(--primary);
  padding: 10px 0;
}
.brand-name {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.4rem;
  line-height: 1.1;
}
.brand-office {
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.nav ul { display: flex; gap: var(--s3); list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.nav li { margin: 0; }
.nav a {
  display: inline-block;
  padding: 12px 2px;
  min-height: 44px;
  text-decoration: none;
  font-weight: 600;
  font-size: 0.98rem;
  color: var(--text);
  border-bottom: 3px solid transparent;
}
.nav a:hover { color: var(--primary-2); border-bottom-color: var(--rule); }
.nav a[aria-current="page"] { color: var(--primary); border-bottom-color: var(--accent); }

.nav-toggle {
  display: none;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  min-width: 44px;
  padding: 8px 14px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font: 600 1rem/1 var(--sans);
  cursor: pointer;
}
.nav-toggle-bars { display: inline-block; width: 18px; }
.nav-toggle-bars span { display: block; height: 2px; background: currentColor; margin: 4px 0; }

@media (max-width: 900px) {
  .nav-toggle { display: inline-flex; }
  .nav {
    display: none;
    flex-basis: 100%;
    border-top: 1px solid var(--rule);
    padding-bottom: var(--s2);
  }
  .nav.is-open { display: block; order: 5; }
  .nav ul { flex-direction: column; gap: 0; }
  .nav li + li { border-top: 1px solid var(--rule); }
  .nav a { display: block; padding: 14px 0; border-bottom: none; }
  .nav a[aria-current="page"] { border-left: 4px solid var(--accent); padding-left: 12px; }
}

@media (min-width: 901px) {
  .nav { order: 2; margin-left: auto; }
  .header-controls { order: 4; margin-left: var(--s3); }
}

/* ------------------------------------------------------------ standfirst */
.standfirst {
  font-family: var(--serif);
  font-size: clamp(1.25rem, 1.1rem + 0.8vw, 1.6rem);
  line-height: 1.35;
  color: var(--text);
  margin-bottom: var(--s4);
}

/* ----------------------------------------------------------- home hero */
.page-index .hero-text .standfirst {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(2rem, 1.4rem + 2.6vw, 3rem);
  line-height: 1.1;
  color: var(--accent);
  margin: 0 0 var(--s3);
  max-width: 18ch;
}
.hero-meta {
  color: var(--muted);
  font-size: 1rem;
  max-width: 52ch;
  border-left: 3px solid var(--rule);
  padding-left: var(--s2);
  margin-bottom: var(--s3);
}
.hero-meta p { margin: 0; }
.hero-actions { margin-bottom: var(--s2); }
.hero-actions p {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: center;
  margin: 0;
}
.hero-actions a {
  display: inline-block;
  min-height: 44px;
  padding: 12px var(--s3);
  border-radius: var(--radius);
  font-weight: 600;
  text-decoration: none;
  border: 2px solid var(--primary);
}
.hero-actions a:first-child { background: var(--primary); color: var(--on-primary); }
.hero-actions a:first-child:hover { background: var(--primary-2); border-color: var(--primary-2); }
.hero-actions a:last-child { color: var(--primary); }
.hero-actions a:last-child:hover { background: var(--tint); }

/* ------------------------------------------------------------- the stat */
.stat {
  border-left: 6px solid var(--accent);
  background: var(--tint);
  padding: var(--s3) var(--s4);
  margin: var(--s3) 0 var(--s4);
  border-radius: 0 var(--radius) var(--radius) 0;
}
@media (min-width: 820px) {
  .stat {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: var(--s5);
    align-items: center;
  }
  .stat-value {
  font-variant-numeric: tabular-nums; grid-row: 1 / span 2; margin: 0; }
  .stat-label { align-self: end; }
  .stat-source { align-self: start; }
}
.stat-value {
  font-variant-numeric: tabular-nums;
  font-family: var(--serif);
  font-size: clamp(2.2rem, 1.6rem + 3.4vw, 3.6rem);
  font-weight: 600;
  line-height: 1;
  color: var(--accent);
  margin: 0 0 var(--s2);
  overflow-wrap: break-word;
}
.stat-label { font-size: 1.1rem; margin: 0 0 var(--s1); max-width: 62ch; }
.stat-source {
  font-size: 0.85rem;
  color: var(--muted);
  margin: 0;
  letter-spacing: 0.02em;
}

/* ---------------------------------------------------------------- boxes */
.note {
  font-size: 0.9rem;
  color: var(--muted);
  border-left: 3px solid var(--rule);
  padding-left: var(--s2);
  margin: calc(var(--s3) * -0.5) 0 var(--s4);
  max-width: 60ch;
}
.note p { margin: 0 0 var(--s1); }
.note p:last-child { margin-bottom: 0; }

.consent-block { margin: 0 0 var(--s3); }

.box {
  border: 2px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: var(--s3) var(--s4);
  margin: var(--s4) 0;
}
@media (min-width: 900px) {
  .box { columns: 2; column-gap: var(--s5); }
  .box > h3 { column-span: all; }
  .box > p { break-inside: avoid; }
}
.box > h3 { margin-top: 0; }
.box > :last-child { margin-bottom: 0; }

.commitments { padding-left: 1.3em; }
.commitments li { padding-left: 0.2em; }

/* ---------------------------------------------------------------- tiles */
.tiles {
  list-style: none;
  margin: var(--s3) 0 var(--s4);
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s3);
}
@media (min-width: 640px) { .tiles { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .tiles { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1400px) { .tiles { gap: var(--s4); } }

.tile {
  position: relative;
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 4px solid var(--primary);
  border-radius: var(--radius);
  padding: var(--s3);
  display: flex;
  flex-direction: column;
}
.tile { transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease; }
.tile:hover {
  border-top-color: var(--accent);
  transform: translateY(-3px);
  box-shadow: 0 10px 24px rgba(0, 0, 0, .09);
}
@media (prefers-reduced-motion: reduce) { .tile { transition: none; } .tile:hover { transform: none; } }
.tile:focus-within { outline: 3px solid var(--focus); outline-offset: 2px; }
.tile-icon { width: 30px; height: 30px; color: var(--accent); margin-bottom: var(--s1); }
.tile-index {
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 4px;
}
.tile-title { font-size: 1.25rem; margin: 0 0 var(--s1); }
.tile-title a { text-decoration: none; }
.tile-title a:hover { text-decoration: underline; }
/* the whole card is clickable, but the real link lives on the heading so
   keyboard and screen reader users get one proper link, not a div */
.stretched::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
}
.tile-stake { font-size: 0.95rem; margin: 0 0 var(--s2); }
.tile-number {
  font-variant-numeric: tabular-nums;
  font-family: var(--serif);
  font-size: 1.9rem;
  font-weight: 600;
  line-height: 1.05;
  color: var(--accent);
  margin: auto 0 4px;
  padding-top: var(--s2);
  overflow-wrap: break-word;
}
.tile-label { font-size: 0.9rem; margin: 0 0 var(--s1); }
.tile-source { font-size: 0.78rem; color: var(--muted); margin: 0; }

/* -------------------------------------------------------------- figures */
.hero-figure {
  margin: var(--s4) 0 var(--s5);
  max-width: none;
}
.hero-figure img {
  width: 100%;
  border-radius: var(--radius);
  border: 1px solid var(--rule);
}
.portrait { margin: 0 0 var(--s3); max-width: 320px; }
.portrait img { width: 100%; border-radius: var(--radius); border: 1px solid var(--rule); }

/* Portrait beside the bio rather than above it. A flex row, so it works the
   same whether the page is running the content grid or not. */
.bio { display: block; }
@media (min-width: 860px) {
  .bio { display: flex; align-items: flex-start; gap: var(--s5); }
  .bio-text { flex: 1 1 auto; min-width: 0; max-width: var(--measure); }
  /* top aligned with the first line of the heading beside it */
  .bio .portrait { flex: 0 0 280px; margin: 0; order: 2; }
  .bio-text > h1 { margin-top: 0; }
}
.bio-text > :last-child { margin-bottom: 0; }

/* ---------------------------------------------------------- wrong block */
.wrong {
  margin: var(--s4) 0 0;
  border-top: 3px solid var(--accent);
  padding-top: var(--s3);
}
.wrong h2 { margin-top: 0; }
.wrong p { max-width: var(--measure); }
@media (min-width: 900px) {
  .wrong {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(320px, 26rem);
    column-gap: var(--s5);
    align-items: start;
  }
  .wrong > h2 { grid-column: 1; grid-row: 1; margin-bottom: 6px; }
  .wrong > p { grid-column: 1; grid-row: 2; margin: 0; }
  .wrong > .mailto-block { grid-column: 2; grid-row: 1 / span 2; margin: 0; max-width: none; }
}
.updated, .footer-vote, .footer-a11y { max-width: 78ch; }

/* ---------------------------------------------------------------- forms */
.form {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s4);
  margin: var(--s3) 0 var(--s4);
  max-width: 640px;
}
.field { margin-bottom: var(--s3); border: 0; padding: 0; }
fieldset.field { margin-bottom: var(--s3); }
.field > label, .field > legend {
  display: block;
  font-weight: 600;
  margin-bottom: 6px;
  padding: 0;
}
.req { color: var(--accent); margin-left: 4px; }
.field input[type="text"],
.field input[type="email"],
.field input[type="tel"],
.field select,
.field textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  font: 400 1rem/1.5 var(--sans);
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.field textarea { min-height: 120px; resize: vertical; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--primary); }
.help { font-size: 0.85rem; color: var(--muted); margin: 6px 0 0; }

.check { display: flex; align-items: center; gap: 10px; margin: 0 0 6px; }
.check input[type="checkbox"] { width: 24px; height: 24px; min-width: 24px; accent-color: var(--primary); margin: 0; }
.check label { font-weight: 400; }

.form-error {
  color: var(--accent);
  font-weight: 600;
  border-left: 4px solid var(--accent);
  padding-left: var(--s2);
  margin: 0 0 var(--s3);
}
.field.has-error input,
.field.has-error select,
.field.has-error textarea { border-color: var(--accent); border-width: 2px; }

/* the honeypot. Hidden from sight, still labelled, still reachable by the
   bots that ignore CSS. Not display:none on the input itself. */
.hp {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* -------------------------------------------------------------- buttons */
.button {
  display: inline-block;
  min-height: 44px;
  padding: 12px var(--s3);
  background: var(--primary);
  color: var(--on-primary);
  border: 2px solid var(--primary);
  border-radius: var(--radius);
  font: 600 1rem/1.25 var(--sans);
  text-decoration: none;
  cursor: pointer;
}
.button:hover { background: var(--primary-2); border-color: var(--primary-2); color: var(--on-primary); }

.fineprint { font-size: 0.85rem; color: var(--muted); }

/* --------------------------------------------------------------- footer */
.site-footer {
  border-top: 1px solid var(--rule);
  background: var(--tint);
  padding: var(--s5) 0 var(--s4);
  margin-top: var(--s6);
  font-size: 0.92rem;
}
.footer-lockup { font-family: var(--serif); font-size: 1.15rem; color: var(--primary); }
.footer-nav ul { display: flex; flex-wrap: wrap; gap: var(--s3); list-style: none; margin: 0 0 var(--s3); padding: 0; }
.footer-nav li { margin: 0; }
.footer-nav a { min-height: 24px; display: inline-block; padding: 4px 0; }
.footer-vote, .footer-a11y { color: var(--muted); max-width: 62ch; }
.disclosure {
  color: var(--muted);
  font-size: 0.85rem;
  border-top: 1px solid var(--rule);
  padding-top: var(--s3);
  margin: var(--s3) 0 0;
}

/* --------------------------------------------------------------- motion */
@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(12px); }
  .reveal.is-in { opacity: 1; transform: none; transition: opacity 200ms ease, transform 200ms ease; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* ------------------------------------------------------- wide overflow */
table, pre { display: block; max-width: 100%; overflow-x: auto; }

/* ---------------------------------------------------------------- print */
@media print {
  .site-header, .nav, .form, .skip-link { display: none; }
  body { background: #fff; color: #000; font-size: 12pt; }
  a::after { content: " (" attr(href) ")"; font-size: 10pt; }
}

/* ==========================================================================
   Components added in the second pass: theme toggle, contents, timeline,
   charts, pull quotes, pager, date stamp, two-column hero.
   ========================================================================== */

/* ------------------------------------------------------- header controls */
.header-controls { display: flex; align-items: center; gap: var(--s1); }
/* On desktop the brand sits left and the nav plus the theme button sit right,
   in that order. Below the menu breakpoint the nav drops to its own row. */
@media (min-width: 901px) {
  .nav { order: 2; margin-left: auto; }
  .header-controls { order: 4; margin-left: var(--s3); }
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  cursor: pointer;
}
.theme-toggle:hover { background: var(--tint); color: var(--primary); }
.theme-toggle svg { width: 20px; height: 20px; }

/* Show the icon for the theme you would switch TO. */
.icon-sun { display: none; }
.icon-moon { display: block; }
:root[data-theme="dark"] .icon-sun { display: block; }
:root[data-theme="dark"] .icon-moon { display: none; }
:root[data-theme="light"] .icon-sun { display: none; }
:root[data-theme="light"] .icon-moon { display: block; }

/* ----------------------------------------------------------- hero, home */


/* -------------------------------------------------------- on this page */
/* On this page, as a disclosure in the header rather than a rail down the
   side. Closed it is one button; open it drops over the page. */
.toc { position: relative; }
.toc > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--text);
  white-space: nowrap;
}
.toc > summary::-webkit-details-marker { display: none; }
.toc > summary::after {
  content: "";
  width: 8px;
  height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
}
.toc[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.toc > summary:hover { background: var(--tint); color: var(--primary); }
.toc > nav {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 60;
  min-width: 260px;
  max-width: 340px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 26px rgba(0, 0, 0, .14);
  padding: var(--s2) var(--s3);
}
.toc > nav ol { margin: 0; padding-left: 1.2em; font-size: 0.94rem; }
.toc > nav li { margin-bottom: 6px; }
.toc > nav li:last-child { margin-bottom: 0; }
@media (max-width: 900px) {
  /* its own row under the brand, so three controls never fight for a 320px
     header and push the page sideways */
  .toc { order: 4; flex-basis: 100%; border-top: 1px solid var(--rule); padding-top: var(--s1); }
  .toc > summary { width: 100%; justify-content: space-between; }
  .toc > nav { position: static; box-shadow: none; margin-top: 6px; max-width: none; border: 0; padding: 0 0 var(--s2); }
}
@media (min-width: 901px) {
  .toc { order: 3; margin-left: var(--s3); }
}
.toc-h {
  font-family: var(--sans);
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--s2);
}
.toc ol { margin: 0; padding-left: 1.3em; }
.toc li { margin-bottom: 6px; }
.toc a { font-weight: 600; text-decoration-color: var(--rule); }

h2[id], h3[id] { scroll-margin-top: var(--s3); }

/* -------------------------------------------------------------- timeline */
.prose > .timeline { max-width: none; }
.timeline {
  list-style: none;
  margin: var(--s2) 0 var(--s3);
  padding: 0 0 0 var(--s4);
  border-left: 2px solid var(--rule);
}
.tl-item {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
  margin-bottom: var(--s2);
  padding-left: var(--s1);
}
.tl-item::before {
  content: "";
  position: absolute;
  left: calc(var(--s4) * -1 - 7px);
  top: 9px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--bg);
}
.tl-item.is-past::before { background: var(--rule); }
.tl-item.is-past .tl-date {
  font-variant-numeric: tabular-nums; color: var(--muted); }
.tl-date {
  font-variant-numeric: tabular-nums;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.15rem;
  color: var(--accent);
  line-height: 1.3;
}
.tl-label { display: block; }
.tl-note { display: block; font-size: 0.85rem; color: var(--muted); }
@media (min-width: 700px) {
  .tl-item { grid-template-columns: 190px minmax(0, 1fr); gap: var(--s3); align-items: baseline; }
}

/* ------------------------------------------------------------ pull quote */
.pullquote {
  margin: var(--s4) 0;
  padding: 0 0 0 var(--s4);
  border-left: 4px solid var(--accent);
}
.pullquote p {
  font-family: var(--serif);
  font-size: clamp(1.35rem, 1.1rem + 1.1vw, 1.8rem);
  line-height: 1.3;
  color: var(--primary);
  margin: 0;
  max-width: 30ch;
  text-wrap: balance;
}

/* ----------------------------------------------------------------- pager */
.prose > .pager { max-width: none; }
.pager {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s2);
  margin: var(--s5) 0 var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule);
}
.pager a {
  display: block;
  padding: var(--s3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  text-decoration: none;
  background: var(--surface);
}
.pager a:hover { border-color: var(--primary); background: var(--tint); }
.pager-dir {
  display: block;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 2px;
}
.pager-name { display: block; font-family: var(--serif); font-weight: 600; font-size: 1.1rem; color: var(--primary); }
.pager-next { text-align: right; }
@media (min-width: 640px) { .pager { grid-template-columns: 1fr 1fr; } }

/* ------------------------------------------------------------ date stamp */
.updated {
  font-size: 0.85rem;
  color: var(--muted);
  border-top: 1px solid var(--rule);
  padding-top: var(--s2);
  margin-top: var(--s5);
  max-width: 62ch;
}

/* ==========================================================================
   Charts. HTML and CSS, not SVG, so the type stays real type at any width and
   the colors follow the theme. Every chart states its numbers in the
   figcaption, which is the part that has to survive with images off.
   ========================================================================== */

.prose > .chart { max-width: none; }
.chart {
  margin: var(--s3) 0;
  padding: var(--s3);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.chart figcaption {
  font-size: 1rem;
  color: var(--muted);
  margin-top: var(--s2);
  padding-top: var(--s2);
  border-top: 1px solid var(--rule);
  max-width: 78ch;
}
.chart figcaption strong { color: var(--text); font-weight: 600; }
.chart-note { font-size: 0.85rem; color: var(--muted); margin: var(--s2) 0 0; }

/* Fill helpers. Scoped, so a color class never paints anything else. */
.bar-fill.c1, .stack-seg.c1, .col-bar.c1, .swatch.c1, .gauge-fill.c1 { background: var(--c1); color: var(--on-chart); }
.bar-fill.c2, .stack-seg.c2, .col-bar.c2, .swatch.c2, .gauge-fill.c2 { background: var(--c2); color: var(--on-chart); }
.bar-fill.c3, .stack-seg.c3, .col-bar.c3, .swatch.c3, .gauge-fill.c3 { background: var(--c3); color: var(--on-chart); }
.bar-fill.c4, .stack-seg.c4, .col-bar.c4, .swatch.c4, .gauge-fill.c4 { background: var(--c4); color: var(--on-chart); }
.bar-fill.c5, .stack-seg.c5, .col-bar.c5, .swatch.c5, .gauge-fill.c5 { background: var(--c5); color: var(--on-chart); }
.bar-fill.c6, .stack-seg.c6, .col-bar.c6, .swatch.c6, .gauge-fill.c6 { background: var(--c6); color: var(--on-chart); }

/* ------------------------------------------------------------- bar charts */
.bars { display: grid; gap: var(--s3); }
.bar-row { display: grid; gap: 6px; }
.bar-label { margin: 0; font-weight: 600; font-size: 1.02rem; line-height: 1.3; }
.bar-when { display: block; font-weight: 400; font-size: 0.85rem; color: var(--muted); }
.bar-track {
  height: 38px;
  background: var(--tint);
  border-radius: 4px;
  overflow: hidden;
}
.bar-fill { height: 100%; width: var(--w, 0%); border-radius: 4px; }
.bar-value {
  font-variant-numeric: tabular-nums;
  margin: 0;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.25rem;
  color: var(--text);
  line-height: 1.2;
}
@media (min-width: 720px) {
  .bar-row { grid-template-columns: 15rem minmax(0, 1fr) auto; align-items: center; gap: var(--s3); }
  .bar-value {
  font-variant-numeric: tabular-nums; text-align: right; min-width: 9ch; }
}

/* ----------------------------------------------------------- stacked bar */
.stack {
  display: flex;
  height: 56px;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: var(--s3);
}
.stack-seg {
  width: var(--w, 0%);
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  overflow: hidden;
}
.stack-pct { font-weight: 700; font-size: 1rem; white-space: nowrap; padding: 0 4px; }
@media (max-width: 560px) { .stack-pct { display: none; } }
.stack-legend { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.stack-legend li { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 1rem; }
.swatch { width: 18px; height: 18px; border-radius: 3px; flex: none; }
@media (min-width: 720px) {
  .stack-legend { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
}

/* -------------------------------------------------------- column compare */
.columns {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: clamp(var(--s4), 8vw, var(--s7));
  height: 300px;
  padding-top: var(--s5);
}
.col { flex: 1 1 0; max-width: 220px; height: 100%; display: flex; flex-direction: column; }
.col-slot { flex: 1 1 auto; display: flex; align-items: flex-end; min-height: 0; }
.col-bar { position: relative; width: 100%; height: var(--h, 0%); border-radius: 4px 4px 0 0; }
.col-value {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-bottom: 8px;
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(1.5rem, 1.1rem + 1.7vw, 2.3rem);
  line-height: 1;
  white-space: nowrap;
  color: var(--text);
}
.col-label { margin: 10px 0 0; text-align: center; font-size: 0.95rem; color: var(--muted); }

/* ---------------------------------------------------------------- gauge */
.gauge { padding: var(--s2) 0 0; }
.gauge-track { position: relative; height: 48px; background: var(--tint); border-radius: 6px; }
.gauge-fill { position: relative; height: 100%; width: var(--w, 0%); border-radius: 6px; }
.gauge-value {
  position: absolute;
  left: 100%;
  top: 50%;
  transform: translateY(-50%);
  margin-left: 12px;
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(1.4rem, 1.1rem + 1vw, 2rem);
  color: var(--text);
  white-space: nowrap;
}
.gauge-mark { position: absolute; top: -10px; bottom: -10px; width: 0; border-left: 3px dashed var(--primary); }
.gauge-mark-label {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 4px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--primary);
  white-space: nowrap;
}
.gauge-scale {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  margin: var(--s4) 0 0;
  font-size: 0.9rem;
  color: var(--muted);
}
.gauge-scale span:last-child { text-align: right; }

/* --------------------------------------------------- charts that animate */
/* .reveal is only ever added by site.js, and site.js only adds it when the
   reader has not asked for reduced motion. So with JavaScript off, or with
   reduced motion on, every chart is simply drawn at full size. */
@media (prefers-reduced-motion: no-preference) {
  .chart.reveal .bar-fill,
  .chart.reveal .gauge-fill,
  .chart.reveal .stack-seg { width: 0; }
  .chart.reveal .col-bar { height: 0; }
  .chart.reveal .gauge-mark,
  .chart.reveal .gauge-value,
  .chart.reveal .col-value,
  .chart.reveal .stack-pct { opacity: 0; }

  .chart.reveal.is-in .bar-fill,
  .chart.reveal.is-in .gauge-fill,
  .chart.reveal.is-in .stack-seg {
    width: var(--w, 0%);
    transition: width 850ms cubic-bezier(0.16, 0.84, 0.44, 1);
    transition-delay: calc(var(--i, 0) * 110ms);
  }
  .chart.reveal.is-in .col-bar {
    height: var(--h, 0%);
    transition: height 850ms cubic-bezier(0.16, 0.84, 0.44, 1);
    transition-delay: calc(var(--i, 0) * 130ms);
  }
  .chart.reveal.is-in .gauge-mark,
  .chart.reveal.is-in .gauge-value,
  .chart.reveal.is-in .col-value,
  .chart.reveal.is-in .stack-pct {
    opacity: 1;
    transition: opacity 450ms ease 600ms;
  }
}

/* --------------------------------------------------------- slim forms */
.form-slim { max-width: 520px; }

/* ------------------------------------------------------------ draft only */
/* Only rendered by `python3 build.py --draft`. Never on the real site. */
.draft-banner {
  background: var(--accent);
  color: var(--on-accent);
  padding: 10px 0;
  font-size: 0.9rem;
}
.draft-banner p { margin: 0; max-width: 90ch; }
.draft-banner strong { font-weight: 600; }

/* Visible to screen readers and search engines, not to the eye. Used to give
   short link text ("Read more") the context it loses out of position. */
.visually-hidden {
  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;
  border: 0;
}

/* ==========================================================================
   Chart types added in the third pass: icon arrays, dial, donut, drop,
   month blocks, diverging bars. Plus a bolder tile badge.
   ========================================================================== */

/* --------------------------------------------------------- the tile badge */
.tile-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--tint);
  color: var(--primary);
  margin-bottom: var(--s2);
  flex: none;
}
.tile-badge svg { width: 30px; height: 30px; display: block; }
.tile:hover .tile-badge { background: var(--accent); color: var(--on-accent); }

/* ------------------------------------------------------------ icon arrays */
:root {
  --glyph-house: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M224,120v96a8,8,0,0,1-8,8H160a8,8,0,0,1-8-8V164a4,4,0,0,0-4-4H108a4,4,0,0,0-4,4v52a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V120a16,16,0,0,1,4.69-11.31l80-80a16,16,0,0,1,22.62,0l80,80A16,16,0,0,1,224,120Z'/%3E%3C/svg%3E");
}
.pictogram {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14px, 1fr));
  gap: 4px;
  margin: 0 0 var(--s2);
}
.glyph-house { --glyph: var(--glyph-house); }
.pictogram i {
  aspect-ratio: 1;
  background: var(--pict-short);
  -webkit-mask: var(--glyph) center / contain no-repeat;
  mask: var(--glyph) center / contain no-repeat;
}
.pictogram i.on { background: var(--c1); transform: scale(1.3); }
.pict-key {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  font-size: 0.98rem;
}
.pict-key li { display: flex; align-items: center; gap: 9px; margin: 0; }
.pict-swatch {
  width: 20px;
  height: 20px;
  flex: none;
  background: var(--pict-short);
  -webkit-mask: var(--glyph-house) center / contain no-repeat;
  mask: var(--glyph-house) center / contain no-repeat;
}
.pict-swatch.on.c1 { background: var(--c1); }
.pict-swatch.on.c2 { background: var(--c2); }

/* ------------------------------------------------------------------ dial */
.dial { max-width: 460px; margin: 0 auto; }
.dial-svg { display: block; width: 100%; height: auto; overflow: visible; }
/* The base state has to carry the real fill. Putting the dash values only in
   the animation rule left the arc drawing all the way round whenever motion
   was reduced or JavaScript was off. */
.dial-arc {
  stroke-dasharray: var(--len);
  stroke-dashoffset: var(--dash);
}
.dial-arc.c1 { color: var(--c1); }
.dial-arc.c2 { color: var(--c2); }
.dial-value {
  font-family: var(--serif);
  font-weight: 700;
  font-size: 58px;
  fill: var(--text);
}
.dial-unit { font-size: 15px; fill: var(--muted); font-family: var(--sans); }
.dial-mark { font-size: 15px; font-weight: 700; fill: var(--primary); font-family: var(--sans); }

/* ----------------------------------------------------------------- donut */
.donut-layout { display: grid; gap: var(--s3); align-items: center; }
@media (min-width: 820px) {
  .donut-layout { grid-template-columns: 260px minmax(0, 1fr); gap: var(--s5); }
  .donut-side .stack-legend { grid-template-columns: 1fr; gap: var(--s2); }
  .donut-callout { margin-top: var(--s3); }
}
.donut-wrap {
  position: relative;
  width: min(260px, 78vw);
  margin: 0 auto;
}
.donut { display: block; width: 100%; height: auto; transform: rotate(-90deg); overflow: visible; }
.donut-seg { stroke-width: 30; }
/* the slice worth staring at is thicker and outlined, so it reads as the
   leftover rather than as just another wedge */
.donut-seg.pop { stroke-width: 42; }
.donut-seg.c1 { color: var(--c1); }
.donut-seg.c2 { color: var(--c2); }
.donut-seg.c3 { color: var(--c3); }
.donut-seg.c4 { color: var(--c4); }
.donut-seg.c5 { color: var(--c5); }
.donut-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin: 0;
  text-align: center;
  pointer-events: none;
}
.donut-big {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(2rem, 1.4rem + 2.4vw, 2.9rem);
  line-height: 1;
  color: var(--text);
}
.donut-small { font-size: 0.9rem; color: var(--muted); max-width: 11ch; line-height: 1.25; margin-top: 4px; }

/* ------------------------------------------------------------------ drop */
.drop { position: relative; padding-top: var(--s5); }
.drop-svg { display: block; width: 100%; height: 130px; }
.drop-area { fill: var(--c2); opacity: 0.16; }
.drop-line { stroke: var(--c2); stroke-width: 3; fill: none; vector-effect: non-scaling-stroke; }
.drop-ends {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  pointer-events: none;
}
.drop-end { margin: 0; display: flex; flex-direction: column; }
.drop-end-b { text-align: right; align-items: flex-end; justify-content: flex-end; padding-top: var(--s6); }
.drop-value {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(1.8rem, 1.2rem + 2.6vw, 2.8rem);
  line-height: 1;
  color: var(--c2);
}
.drop-label { font-size: 0.9rem; color: var(--muted); margin-top: 4px; }

/* ---------------------------------------------------------- month blocks */
.blocks { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: var(--s2); }
.blocks i {
  flex: 1 1 44px;
  min-width: 44px;
  height: 58px;
  border-radius: 3px;
  background: var(--tint);
  border: 2px solid var(--border);
  /* the month name sits inside the block, so a row of them reads as a
     calendar rather than as a row of anonymous rectangles */
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 5px;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  font-style: normal;
}
.blocks i::after { content: attr(data-m); }
.blocks i.on { background: var(--c2); border-color: var(--c2); color: #FFFFFF; }

/* -------------------------------------------------------- diverging bars */
.div-track { display: flex; }
.bar-row-div .bar-fill { border-radius: 4px 0 0 4px; }
.div-rest {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  border-radius: 0 4px 4px 0;
}
.div-rest.c5 { background: var(--c5); color: var(--on-chart); }
.div-track .bar-fill { display: flex; align-items: center; }
.div-in { font-weight: 700; font-size: 0.95rem; white-space: nowrap; padding: 0 12px; }
@media (max-width: 560px) { .div-in { font-size: 0.8rem; padding: 0 6px; } }

/* --------------------------------------------------- animating the above */
@media (prefers-reduced-motion: no-preference) {
  .chart.reveal .pictogram i,
  .chart.reveal .blocks i { opacity: 0; }
  .chart.reveal.is-in .pictogram i,
  .chart.reveal.is-in .blocks i {
    opacity: 1;
    transition: opacity 500ms ease;
  }
  /* the filled glyphs land last, so the shortfall is what you watch appear */
  .chart.reveal.is-in .pictogram i.on { transition-delay: 350ms; }

  .chart.reveal .dial-arc { stroke-dashoffset: var(--len); }
  .chart.reveal.is-in .dial-arc {
    stroke-dashoffset: var(--dash);
    transition: stroke-dashoffset 1100ms cubic-bezier(0.16, 0.84, 0.44, 1);
  }
  .chart.reveal .dial-value,
  .chart.reveal .dial-mark,
  .chart.reveal .donut-center,
  .chart.reveal .drop-ends { opacity: 0; }
  .chart.reveal.is-in .dial-value,
  .chart.reveal.is-in .dial-mark,
  .chart.reveal.is-in .donut-center,
  .chart.reveal.is-in .drop-ends {
    opacity: 1;
    transition: opacity 500ms ease 550ms;
  }

  .chart.reveal .donut { transform: rotate(-90deg) scale(0.82); opacity: 0; }
  .chart.reveal.is-in .donut {
    transform: rotate(-90deg) scale(1);
    opacity: 1;
    transition: transform 700ms cubic-bezier(0.16, 0.84, 0.44, 1), opacity 500ms ease;
  }

  .chart.reveal .drop-svg { clip-path: inset(0 100% 0 0); }
  .chart.reveal.is-in .drop-svg {
    clip-path: inset(0 0 0 0);
    transition: clip-path 900ms cubic-bezier(0.16, 0.84, 0.44, 1);
  }

  .chart.reveal .div-rest { opacity: 0; }
  .chart.reveal.is-in .div-rest { opacity: 1; transition: opacity 400ms ease 500ms; }
}

/* ------------------------------------------------- stacked icon compare */
:root {
  --glyph-coin: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm12,152h-4v8a8,8,0,0,1-16,0v-8H104a8,8,0,0,1,0-16h36a12,12,0,0,0,0-24H116a28,28,0,0,1,0-56h4V72a8,8,0,0,1,16,0v8h16a8,8,0,0,1,0,16H116a12,12,0,0,0,0,24h24a28,28,0,0,1,0,56Z'/%3E%3C/svg%3E");
}
.pict-rows { display: grid; gap: var(--s4); margin-bottom: var(--s3); }
.pict-row-head { margin: 0 0 8px; display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; }
.pict-row-value {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(1.7rem, 1.2rem + 2.2vw, 2.6rem);
  line-height: 1;
  color: var(--text);
}
.pict-row-label { font-size: 1rem; color: var(--muted); }
.pict-line { display: flex; flex-wrap: wrap; gap: 5px; }
.pict-line i {
  width: 26px;
  height: 26px;
  flex: none;
  -webkit-mask: var(--glyph) center / contain no-repeat;
  mask: var(--glyph) center / contain no-repeat;
}
.glyph-coin { --glyph: var(--glyph-coin); }
.pict-line i.on-a { background: var(--c5); }
.pict-line i.on-b { background: var(--c2); }

@media (prefers-reduced-motion: no-preference) {
  .chart.reveal .pict-line i { opacity: 0; }
  .chart.reveal.is-in .pict-line i { opacity: 1; transition: opacity 450ms ease; }
  .chart.reveal.is-in .pict-line i.on-b { transition-delay: 400ms; }
}

/* ------------------------------------------------------------ tile header */
.tile-top { display: flex; align-items: center; gap: 14px; margin-bottom: var(--s2); }
.tile-key {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(1.5rem, 1.2rem + 1.1vw, 1.95rem);
  line-height: 1;
  letter-spacing: -0.015em;
  color: var(--primary);
  margin: 0;
  text-wrap: balance;
}
.kw-fire { color: var(--fire); }
.kw-flood { color: var(--flood); }
.tile-note {
  font-size: 0.82rem;
  color: var(--muted);
  margin: 0 0 6px;
  line-height: 1.35;
}
.tile-title { font-size: 1.12rem; }
.tile-badge { margin-bottom: 0; }

/* ------------------------------------------------------------- road chart */
.road { padding: 46px 0 0; }
.road-strip {
  position: relative;
  display: flex;
  height: 88px;
  border-radius: 6px;
  overflow: visible;
}
.road-good {
  width: var(--w, 50%);
  background:
    /* the center line */
    repeating-linear-gradient(to right,
      #F3F1EA 0 26px, transparent 26px 52px) center / 100% 6px no-repeat,
    var(--asphalt);
  border-radius: 6px 0 0 6px;
}
.road-bad {
  flex: 1;
  background:
    radial-gradient(circle at 12% 34%, rgba(0,0,0,.55) 0 9px, transparent 10px),
    radial-gradient(circle at 27% 70%, rgba(0,0,0,.5) 0 6px, transparent 7px),
    radial-gradient(circle at 44% 28%, rgba(0,0,0,.5) 0 11px, transparent 12px),
    radial-gradient(circle at 61% 62%, rgba(0,0,0,.45) 0 7px, transparent 8px),
    radial-gradient(circle at 78% 38%, rgba(0,0,0,.55) 0 10px, transparent 11px),
    radial-gradient(circle at 91% 72%, rgba(0,0,0,.45) 0 6px, transparent 7px),
    repeating-linear-gradient(74deg, rgba(0,0,0,.28) 0 2px, transparent 2px 15px),
    var(--asphalt-bad);
  border-radius: 0 6px 6px 0;
}
.road-target {
  position: absolute;
  top: -8px;
  bottom: -8px;
  width: 0;
  border-left: 3px dashed var(--c1);
}
.road-target span {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-bottom: 4px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--c1);
  white-space: nowrap;
}
.road-car {
  position: absolute;
  bottom: 52px;
  transform: translateX(-58%);
  width: 62px;
  color: var(--c2);
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.28));
}
.road-car svg { width: 100%; height: auto; display: block; }
.road-scale {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s2);
  margin: var(--s2) 0 0;
  font-size: 0.9rem;
  color: var(--muted);
}
.road-here {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(1.1rem, 0.9rem + 0.8vw, 1.5rem);
  color: var(--c2);
}
@media (prefers-reduced-motion: no-preference) {
  .chart.reveal .road-good { width: 0; }
  .chart.reveal.is-in .road-good {
    width: var(--w, 50%);
    transition: width 1000ms cubic-bezier(0.16, 0.84, 0.44, 1);
  }
  .chart.reveal .road-car { opacity: 0; }
  .chart.reveal.is-in .road-car {
    opacity: 1;
    transition: opacity 400ms ease 700ms;
  }
}

/* ------------------------------------------------- plain-language glossary */
.glossary {
  margin: var(--s2) 0 0;
  padding-top: var(--s2);
  border-top: 1px solid var(--rule);
  display: grid;
  gap: var(--s2);
}
@media (min-width: 860px) {
  .glossary { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--s2) var(--s4); }
}
.gl-item { min-width: 0; }
.glossary dt {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--primary);
  margin-bottom: 2px;
}
.glossary dd {
  margin: 0;
  font-size: 0.92rem;
  color: var(--muted);
  line-height: 1.5;
}

/* ------------------------------------------------------- legends with icons */
.legend-icon {
  width: 30px;
  height: 30px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: transparent;
}
.legend-icon svg { width: 26px; height: 26px; }
.legend-icon.c1 { color: var(--c1); }
.legend-icon.c2 { color: var(--c2); }
.legend-icon.c3 { color: var(--c3); }
.legend-icon.c4 { color: var(--c4); }
.legend-icon.c5 { color: var(--c5); }

/* ------------------------------------------- callout on the leftover slice */
.donut-callout {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: var(--s3) 0 0;
  padding: var(--s2) var(--s3);
  background: var(--tint);
  border-left: 4px solid var(--c5);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 0.95rem;
  color: var(--muted);
}
.donut-callout strong { color: var(--text); }
.callout-arrow { flex: none; width: 22px; height: 22px; color: var(--c5); margin-top: 1px; }
.callout-arrow svg { width: 100%; height: 100%; display: block; }

/* the explanation under a bar label needs to read as an explanation */
.bar-when { font-style: normal; }

/* ==========================================================================
   The dock. Fixed to the bottom of the viewport on desktop: who she is and
   the main links on the left, previous and next issue on the right. Hidden
   below the breakpoint, where a phone has no room to give up.
   ========================================================================== */
.dock { display: none; }

@media (min-width: 1080px) {
  .dock {
    display: block;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    background: var(--surface);
    border-top: 1px solid var(--border);
    box-shadow: 0 -2px 14px rgba(0, 0, 0, .07);
  }
  .dock-inner {
    max-width: var(--wide);
    margin: 0 auto;
    padding: 10px var(--s3);
    display: flex;
    align-items: center;
    gap: var(--s4);
  }
  .dock-id {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    flex: none;
    padding: 4px 0;
  }
  .dock-name-main {
    font-family: var(--serif);
    font-weight: 600;
    font-size: 1.05rem;
    line-height: 1.1;
    color: var(--primary);
  }
  .dock-office { font-size: 0.76rem; color: var(--muted); letter-spacing: 0.02em; }

  .dock-nav ul {
    display: flex;
    gap: var(--s3);
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .dock-nav li { margin: 0; }
  .dock-nav a {
    font-size: 0.88rem;
    font-weight: 600;
    text-decoration: none;
    color: var(--text);
    padding: 8px 2px;
    display: inline-block;
    min-height: 24px;
    border-bottom: 2px solid transparent;
  }
  .dock-nav a:hover { color: var(--primary); border-bottom-color: var(--rule); }
  .dock-nav a[aria-current="page"] { color: var(--primary); border-bottom-color: var(--accent); }

  .dock-steps { margin-left: auto; display: flex; gap: var(--s2); flex: none; }
  .dock-step {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    padding: 6px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    max-width: 200px;
  }
  .dock-step:hover { border-color: var(--primary); background: var(--tint); }
  .dock-next { text-align: right; }
  .dock-dir {
    font-size: 0.66rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .dock-name {
    font-family: var(--serif);
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* keep the dock off the last of the content, and off a focused element */
  body { padding-bottom: 78px; }
  .site-footer { margin-bottom: 0; }
  h2[id], h3[id] { scroll-margin-top: var(--s3); scroll-margin-bottom: 96px; }
  :focus-visible { scroll-margin-bottom: 96px; }

  /* the dock already carries previous and next, so the in-page pager is
     redundant here. It stays for narrow screens, where the dock is hidden. */
  .pager { display: none; }

  /* the header follows you down, so the name and the nav are always there */
  .site-header {
    position: sticky;
    top: 0;
    z-index: 45;
    background: var(--bg);
  }
}

/* ------------------------------------------------------------ mailto block */
.mailto-block {
  background: var(--tint);
  border-left: 4px solid var(--primary);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: var(--s3) var(--s4);
  margin: var(--s3) 0;
  max-width: 720px;
}
.mailto-block > p { margin: 0 0 var(--s2); }
.mailto-cta { margin: 0 0 var(--s2); }
.mailto-note { font-size: 0.92rem; color: var(--muted); }
.mailto-plain { font-size: 0.88rem; color: var(--muted); margin: 0; }
.wrong .mailto-block { margin-top: var(--s2); }


/* ============================================================ fact bands */
/* One fact, very large, full width. Three in a row make an argument before
   anyone argues. These are the parts people screenshot. */
.prose > .factband,
.wrap.prose > .factband { grid-column: 1 / -1; max-width: none; }
.factband {
  margin: var(--s3) 0;
  padding: var(--s4) var(--s5);
  border-radius: var(--radius);
  border-left: 6px solid var(--c1);
  background: var(--tint);
}
.factband.fb-b { border-left-color: var(--c2); }
.factband.fb-c { border-left-color: var(--c3); }
.fb-value {
  font-variant-numeric: tabular-nums;
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(2.6rem, 1.6rem + 5vw, 5rem);
  line-height: 0.95;
  letter-spacing: -0.02em;
  margin: 0 0 8px;
  color: var(--c1);
  overflow-wrap: break-word;
}
.factband.fb-b .fb-value {
  font-variant-numeric: tabular-nums; color: var(--c2); }
.factband.fb-c .fb-value {
  font-variant-numeric: tabular-nums; color: var(--c3); }
.fb-label {
  font-size: clamp(1.05rem, 0.95rem + 0.5vw, 1.3rem);
  margin: 0 0 6px;
  max-width: 54ch;
  color: var(--text);
}
.fb-source { font-size: 0.85rem; color: var(--muted); margin: 0; letter-spacing: 0.02em; }

@media (prefers-reduced-motion: no-preference) {
  .factband.reveal .fb-value {
  font-variant-numeric: tabular-nums; opacity: 0; transform: translateY(14px); }
  .factband.reveal.is-in .fb-value {
  font-variant-numeric: tabular-nums;
    opacity: 1;
    transform: none;
    transition: opacity 500ms ease, transform 600ms cubic-bezier(0.16, 0.84, 0.44, 1);
  }
}

/* =========================================================== mini tiles */
.minitiles ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.minitiles a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius);
  text-decoration: none;
  background: var(--surface);
}
.minitiles a:hover { border-left-color: var(--accent); background: var(--tint); }
.mt-badge {
  width: 30px; height: 30px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--primary);
}
.mt-badge svg { width: 24px; height: 24px; }
.mt-body { display: flex; flex-direction: column; min-width: 0; }
.mt-key {
  font-family: var(--serif); font-weight: 600; font-size: 1rem;
  line-height: 1.15; color: var(--primary);
}
.mt-num { font-size: 0.82rem; color: var(--muted); }
.mt-more a { border-left-color: var(--c3); }
.mt-more .mt-badge { color: var(--c3); }
.mt-more .mt-key { color: var(--c3); }
@media (min-width: 700px) {
  .minitiles ul { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
}

/* ------------------------------------------ icons beside headings and facts */
h2.has-icon, h3.has-icon { display: flex; align-items: center; gap: 12px; }
.h-icon {
  flex: none;
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: var(--tint);
  color: var(--accent);
}
.h-icon svg { width: 22px; height: 22px; }

.factband { display: flex; align-items: flex-start; gap: var(--s4); }
.fb-icon {
  flex: none;
  width: 56px;
  height: 56px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: var(--surface);
  color: var(--c1);
  margin-top: 6px;
}
.factband.fb-b .fb-icon { color: var(--c2); }
.factband.fb-c .fb-icon { color: var(--c3); }
.fb-icon svg { width: 34px; height: 34px; }
.fb-body { min-width: 0; }
@media (max-width: 620px) {
  .factband { gap: var(--s3); }
  .fb-icon { width: 42px; height: 42px; }
  .fb-icon svg { width: 26px; height: 26px; }
}

/* ============================================================= photographs */
.prose > .photo,
.wrap.prose > .photo { grid-column: 1 / -1; max-width: none; }
.photo { margin: var(--s3) 0; }
.photo img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius);
  object-fit: cover;
  background: var(--tint);
}
.photo figcaption {
  font-size: 0.92rem;
  color: var(--muted);
  margin-top: 10px;
  max-width: 72ch;
  line-height: 1.5;
}

/* the hero photo on the home page sits in the second column of the hero grid */
.hero-grid .photo { margin: 0; }

/* ---------------------------------------------------------------- gallery */
.prose > .gallery,
.wrap.prose > .gallery { grid-column: 1 / -1; max-width: none; }
.gallery {
  list-style: none;
  margin: var(--s3) 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s3);
}
@media (min-width: 620px) { .gallery { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .gallery { grid-template-columns: repeat(3, 1fr); } }
.gallery li { margin: 0; min-width: 0; }
.gallery .photo { margin: 0; height: 100%; display: flex; flex-direction: column; }
/* photo() writes the real aspect ratio as an inline style so the browser can
   reserve space before the image arrives. In a gallery the cells have to
   match each other instead, and beating an inline style needs this. */
.gallery .photo img { aspect-ratio: 4 / 3 !important; }
.gallery figcaption { font-size: 0.88rem; margin-top: 8px; }

@media (prefers-reduced-motion: no-preference) {
  .photo.reveal img { opacity: 0; transform: scale(1.02); }
  .photo.reveal.is-in img {
    opacity: 1;
    transform: none;
    transition: opacity 600ms ease, transform 800ms cubic-bezier(0.16, 0.84, 0.44, 1);
  }
}

/* ================================================================= banner */
/* Mount Tam behind the words. Everyone here has seen the mountain, so it
   works as ground rather than as subject. The scrim is a solid gradient, not
   a hope: text contrast cannot depend on which part of a photograph happens
   to sit behind it. */
.wrap.prose > .banner,
.prose > .banner {
  grid-column: 1 / -1;
  max-width: none;
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: calc(var(--s4) * -1);
  margin-bottom: var(--s5);
  overflow: hidden;
  isolation: isolate;
  background: #101512;
}
.banner-media { position: absolute; inset: 0; z-index: 0; }
.banner-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Weighted left. The words sit in the dark half, the mountain shows through
   the right. Measured, not guessed: see the note on .scene::after. */
.banner::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    /* Shade the text column and let the mountain be a mountain. Pulled back
       from the earlier version, which dimmed the whole frame to protect text
       that only occupies the left third. */
    linear-gradient(100deg, rgba(10, 16, 12, .93) 0%, rgba(10, 16, 12, .88) 34%,
                    rgba(10, 16, 12, .42) 54%, rgba(10, 16, 12, .06) 72%,
                    rgba(10, 16, 12, 0) 88%),
    linear-gradient(to bottom, rgba(10, 16, 12, .22) 0%, rgba(10, 16, 12, 0) 40%,
                    rgba(10, 16, 12, .16) 100%);
}
.banner-inner {
  position: relative;
  z-index: 2;
  max-width: var(--wide);
  margin: 0 auto;
  padding: var(--s7) var(--s3) var(--s6);
  display: grid;
  gap: var(--s5);
  align-items: center;
}
.banner-text > * { max-width: 40ch; }
.banner-text h1 {
  color: #FFFFFF;
  margin-top: 0;
  font-size: clamp(2.1rem, 1.25rem + 3.3vw, 3.7rem);
  line-height: 1.04;
  letter-spacing: -0.026em;
  max-width: 19ch;
  text-shadow: 0 2px 24px rgba(0, 0, 0, .35);
}
.banner-text .standfirst {
  color: var(--warm);
  font-weight: 600;
  font-size: clamp(1.55rem, 1.15rem + 1.9vw, 2.35rem);
  line-height: 1.05;
  margin: 6px 0 var(--s3);
  max-width: 18ch;
  text-shadow: 0 2px 20px rgba(0, 0, 0, .4);
}
.banner-text .hero-meta {
  color: #E7EDE6;
  border-left-color: rgba(255, 255, 255, .38);
  max-width: 46ch;
}
.banner-text .hero-meta strong { color: #FFFFFF; }
.banner-text .hero-actions a:first-child {
  background: #FFFFFF;
  color: #16211C;
  border-color: #FFFFFF;
}
.banner-text .hero-actions a:first-child:hover { background: var(--warm); border-color: var(--warm); }
.banner-text .hero-actions a:last-child { color: #FFFFFF; border-color: rgba(255, 255, 255, .6); }
.banner-text .hero-actions a:last-child:hover { background: rgba(255, 255, 255, .14); }

.banner-portrait .photo { margin: 0; }
.banner-portrait .photo img {
  border-radius: var(--radius);
  box-shadow: 0 18px 44px rgba(0, 0, 0, .45);
  border: 3px solid rgba(255, 255, 255, .9);
}
.banner-portrait .photo figcaption { color: #D8E0D6; }

@media (min-width: 900px) {
  .banner { min-height: 60vh; }
  .banner-inner { grid-template-columns: minmax(0, 35rem); align-content: center; }
}
@media (max-width: 899px) {
  .banner::after {
    background: linear-gradient(to bottom, rgba(10, 16, 12, .72) 0%,
                rgba(10, 16, 12, .88) 55%, rgba(10, 16, 12, .93) 100%);
  }
  .banner-inner { padding: var(--s6) var(--s3) var(--s5); }
}

/* ================================================================== scenes */
/* A photograph used as ground rather than as an object. Full width, dimmed,
   with a line of copy over it. The scrim is a solid gradient so contrast
   never depends on which part of the picture sits behind the words. */
.wrap.prose > .scene,
.prose > .scene {
  grid-column: 1 / -1;
  max-width: none;
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-block: var(--s5);
  overflow: hidden;
  isolation: isolate;
  background: #0C140F;
  min-height: 300px;
  display: flex;
  align-items: flex-end;
}
.scene-media { position: absolute; inset: 0; z-index: 0; }
.scene-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.scene::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Shade where the words are, not across the whole photograph. The old
     version was a full width wash that blacked out the bottom half and left
     the top at 34 percent, which cost the picture and gained nothing: the
     text only ever sits in the lower left. Measured, not guessed. */
  background:
    radial-gradient(125% 95% at 6% 100%,
      rgba(10, 16, 12, .94) 0%, rgba(10, 16, 12, .88) 24%,
      rgba(10, 16, 12, .58) 44%, rgba(10, 16, 12, .22) 64%,
      rgba(10, 16, 12, 0) 82%),
    linear-gradient(to top, rgba(10, 16, 12, .40) 0%,
      rgba(10, 16, 12, .10) 20%, rgba(10, 16, 12, 0) 36%);
}
.scene-body {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--wide);
  margin: 0 auto;
  padding: var(--s3) var(--s3) var(--s4);
}
.scene-head {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(1.5rem, 1.1rem + 1.9vw, 2.4rem);
  line-height: 1.1;
  color: #FFFFFF;
  margin: 0;
  max-width: 22ch;
  text-wrap: balance;
  letter-spacing: -0.015em;
}
.scene-sub {
  color: var(--warm);
  font-size: 1rem;
  margin: 10px 0 0;
  max-width: 54ch;
}
/* This has to match the specificity of `.prose > .scene` above or it loses
   silently, which it did: every band sat at the 300px base. */
@media (min-width: 900px) {
  .wrap.prose > .scene,
  .prose > .scene { min-height: 420px; }
}

/* A strip of a photograph is not the photograph. When the subject is the
   height of a building, or sits at the bottom of the frame, the band has to
   change shape or move rather than take the middle and hope. */
/* the subject sits low in the frame, so the band both moves down and needs
   more height than the default strip to show more than a patch of ground */
.scene-bottom .scene-media img { object-position: 50% 100%; }
.wrap.prose > .scene-bottom,
.prose > .scene-bottom { min-height: 380px; }
@media (min-width: 900px) {
  .wrap.prose > .scene-bottom,
  .prose > .scene-bottom { min-height: 440px; }
}
.scene-top .scene-media img { object-position: 50% 0%; }
/* matches the specificity of the .prose > .scene rule above, which sets the
   base min-height and would otherwise win */
.wrap.prose > .scene-tall,
.prose > .scene-tall { min-height: 66vh; }
@media (min-width: 900px) {
  .wrap.prose > .scene-tall,
  .prose > .scene-tall { min-height: 640px; }
}

/* ------------------------------------------------- headings that carry color */
.prose h2:not(.toc-h):not(.tile-title)::before,
.wrap.prose h2:not(.toc-h):not(.tile-title)::before {
  content: "";
  display: block;
  width: 44px;
  height: 4px;
  border-radius: 2px;
  background: var(--accent);
  margin-bottom: 14px;
}
h2.has-icon::before { display: none !important; }
.wrong h2::before { display: none !important; }
.box h3, .glossary dt { color: var(--primary); }


/* ------------------------------------------------ the endorsements statement */
/* Declining to publish a list is a position, so it gets treated as one rather
   than tucked away at the foot of the page. */
.endorse-note {
  margin-top: var(--s5);
  padding: var(--s4);
  border: 1px solid var(--border);
  border-left: 4px solid var(--c2);
  border-radius: 6px;
  background: var(--tint);
}
.endorse-note h2 { margin-top: 0; }
.endorse-note p:last-child { margin-bottom: 0; }
