/* ==========================================================================
   BB2G SOLUTIONS — shared brand system
   One front door, seven surfaces. Documentary / records-room art direction.
   ========================================================================== */

:root {
  /* --- surfaces (documentary dark) --- */
  --ink:        #0B0D0F;
  --ink-1:      #101316;
  --ink-2:      #161A1E;
  --ink-3:      #1E2429;
  --ink-4:      #2A3237;

  /* --- type --- */
  --bone:       #EDE8E0;
  --bone-2:     #C6C0B7;
  /* The two muted tiers were originally #948E85 and #635F59, which measured
     2.8-3.1:1 against the dark surfaces they sit on — under the 4.5:1 needed
     for the 10-12px labels that use them. Lifted until they pass. */
  --bone-3:     #A8A29A;
  --bone-4:     #8A8781;

  /* --- shared signal --- */
  --amber:      #D9A24B;

  /* --- per-surface accent (overridden per app) --- */
  --accent:     #D9A24B;
  --accent-dim: color-mix(in oklab, var(--accent) 55%, var(--ink));
  --accent-ink: #0B0D0F;
  /* Accent used as TEXT rather than as a fill. On near-black the accent itself
     is legible; on paper it is not, so the light theme darkens this one token
     and every accent-coloured label follows. */
  --accent-text: color-mix(in oklab, var(--accent) 76%, #EDE8E0);

  /* --- evidence status palette (identical on every surface) --- */
  --st-confirmed:  #4F9481;
  --st-reported:   #6683AD;
  --st-contested:  #C98A3C;
  --st-allegation: #CE6C60;  /* lifted from #B4544A: 3.8:1 as label text */
  --st-neutral:    #7C8288;

  /* --- election board labels --- */
  --lb-effective: #4F9481;
  --lb-enjoined:  #CE6C60;  /* same, for the enjoined pill */
  --lb-appealed:  #C98A3C;
  --lb-pending:   #6683AD;
  --lb-decided:   #A8A29A;

  /* --- lines --- */
  --line:      color-mix(in oklab, var(--bone) 12%, transparent);
  --line-soft: color-mix(in oklab, var(--bone) 7%, transparent);
  --line-hard: color-mix(in oklab, var(--bone) 22%, transparent);

  /* --- type families --- */
  --font-display: 'Zodiak', 'Iowan Old Style', Georgia, serif;
  --font-body: 'Satoshi', 'Inter', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;

  /* --- scale --- */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1.0625rem;
  --text-lg: 1.1875rem;
  --text-xl: clamp(1.4rem, 1.2rem + 0.9vw, 1.75rem);
  --text-2xl: clamp(1.9rem, 1.5rem + 1.9vw, 2.9rem);
  --text-3xl: clamp(2.5rem, 1.7rem + 3.6vw, 4.6rem);

  /* --- rhythm --- */
  --gut: clamp(1.25rem, 4vw, 2.5rem);
  --max: 1240px;
  --max-read: 68ch;

  --radius-sm: 3px;
  --radius: 5px;
  --radius-lg: 10px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

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

/* The [hidden] attribute only sets display:none at the UA level, so any element given
   display:flex/grid by a class stays visible when toggled hidden from JS. Every surface
   toggles panels, legends and filters this way, so enforce it globally. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone-2);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

::selection { background: var(--accent); color: var(--accent-ink); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--accent); color: var(--accent-ink);
  padding: 0.75rem 1.25rem; font: 600 var(--text-sm)/1 var(--font-body);
}
.skip:focus { left: 0.5rem; top: 0.5rem; }

/* ---------- typography ---------- */
h1, h2, h3, h4 { color: var(--bone); margin: 0; font-weight: 500; line-height: 1.12; }
h1 { font-family: var(--font-display); font-size: var(--text-3xl); letter-spacing: -0.02em; }
h2 { font-family: var(--font-display); font-size: var(--text-2xl); letter-spacing: -0.015em; }
h3 { font-family: var(--font-body); font-size: var(--text-xl); font-weight: 600; letter-spacing: -0.01em; line-height: 1.25; }
h4 { font-family: var(--font-body); font-size: var(--text-lg); font-weight: 600; line-height: 1.35; }
p { margin: 0 0 1.05em; }
a { color: var(--bone); text-decoration-color: var(--accent); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--accent-text); }
strong { color: var(--bone); font-weight: 600; }

.lede { font-size: var(--text-lg); color: var(--bone-2); max-width: var(--max-read); }
.read { max-width: var(--max-read); }

.kicker {
  font: 500 var(--text-xs)/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-text);
  display: block;
  margin-bottom: 0.9rem;
}
.kicker-dim { color: var(--bone-4); }

.num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* ---------- layout ---------- */
.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gut); }
.wrap-wide { max-width: 1560px; }

section { position: relative; }
.band { padding-block: clamp(3.5rem, 7vw, 7rem); border-top: 1px solid var(--line-soft); }
.band-tight { padding-block: clamp(2.25rem, 4vw, 3.5rem); }
.band-tall { padding-block: clamp(5rem, 10vw, 10rem); }
.band-alt { background: var(--ink-1); }

.grid { display: grid; gap: clamp(1.25rem, 2.5vw, 2.25rem); }
.g2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.g3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }

.split {
  display: grid;
  gap: clamp(1.5rem, 4vw, 4rem);
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  align-items: start;
}
@media (max-width: 820px) { .split { grid-template-columns: 1fr; } }

.sec-head { margin-bottom: clamp(1.75rem, 3.5vw, 3rem); }
.sec-head p { max-width: var(--max-read); }

/* ---------- top bar / front door ---------- */
.topbar {
  position: sticky; top: 0; z-index: 90;
  background: color-mix(in oklab, var(--ink) 88%, transparent);
  backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--line-soft);
}
.topbar-in {
  display: flex; align-items: center; gap: 1rem;
  min-height: 60px;
  width: 100%; max-width: 1560px; margin-inline: auto;
  padding-inline: var(--gut);
}
.brand { display: flex; align-items: center; gap: 0.7rem; text-decoration: none; color: var(--bone); flex-shrink: 0; }
.brand:hover { color: var(--bone); }
.brand svg { width: 26px; height: 26px; color: var(--accent-text); flex-shrink: 0; }
.brand-txt { display: flex; flex-direction: column; line-height: 1; }
.brand-txt b { font: 600 0.8rem/1 var(--font-body); letter-spacing: 0.16em; text-transform: uppercase; }
.brand-txt span { font: 400 0.6rem/1 var(--font-mono); letter-spacing: 0.13em; color: var(--bone-4); margin-top: 3px; text-transform: uppercase; }

.doorwrap { position: relative; margin-left: auto; }
.door {
  display: flex; align-items: center; gap: 0.6rem;
  min-height: 40px; padding: 0 0.9rem;
  background: var(--ink-2); color: var(--bone);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: 500 var(--text-sm)/1 var(--font-body);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.door:hover { border-color: var(--line-hard); background: var(--ink-3); }
.door .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
.door .car { color: var(--bone-4); font-size: 0.7rem; }
.door-now { color: var(--bone-4); }
@media (max-width: 620px) { .door-now { display: none; } }
/* Keep the current surface name on one line. Without this, a longer name such as
   "The Front Door" breaks onto three lines on a 375px screen and the header grows
   to three times its height. Both the brand block and the button label truncate
   with an ellipsis rather than wrapping or pushing the header past the viewport. */
.door { white-space: nowrap; }
.doorwrap { flex-shrink: 0; }  /* size to the button; never let it overflow its wrapper */
/* .brand is declared flex-shrink: 0 above, which is what pushed the button off-screen.
   It has to be the element that yields space, so it is re-enabled here. */
.brand { flex-shrink: 1; min-width: 0; }
.brand-txt { min-width: 0; }
.brand-txt b, .brand-txt span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 620px) {
  /* A 375px header cannot hold the wordmark, the tagline, and the surface name.
     There is not enough room to shrink the wordmark without ellipsizing it, so the
     text drops and the logo mark carries the link home. The surface name — the thing
     that tells you where you are — stays complete. */
  .brand-txt { display: none; }
  .brand svg { width: 30px; height: 30px; }
  .door-name { display: inline-block; max-width: 62vw; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
}

.doormenu {
  position: absolute; right: 0; top: calc(100% + 8px);
  width: min(92vw, 400px);
  background: var(--ink-1);
  border: 1px solid var(--line-hard);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 60px -12px rgba(0,0,0,0.75);
  padding: 0.45rem;
  display: none;
  max-height: min(72vh, 560px); overflow-y: auto;
}
.doormenu[data-open='true'] { display: block; }
.doormenu-lab {
  font: 500 var(--text-xs)/1 var(--font-mono); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--bone-4); padding: 0.7rem 0.75rem 0.5rem;
}
.doorlink {
  display: grid; grid-template-columns: 9px 1fr; gap: 0.75rem; align-items: start;
  padding: 0.6rem 0.75rem; border-radius: var(--radius);
  text-decoration: none; color: var(--bone);
  transition: background 0.15s var(--ease);
}
.doorlink:hover { background: var(--ink-3); color: var(--bone); }
.doorlink[aria-current='page'] { background: var(--ink-3); }
.doorlink i { width: 9px; height: 9px; border-radius: 50%; margin-top: 7px; }
.doorlink b { display: block; font: 600 var(--text-sm)/1.3 var(--font-body); }
.doorlink span { display: block; font: 400 var(--text-xs)/1.45 var(--font-body); color: var(--bone-3); margin-top: 2px; }
.doorlink code { display: block; font: 400 0.65rem/1.4 var(--font-mono); color: var(--bone-4); margin-top: 4px; }

/* ---------- full-bleed motion hero ---------- */
.hero { position: relative; min-height: min(88vh, 800px); display: flex; align-items: flex-end; overflow: hidden; isolation: isolate; }
.hero-short { min-height: min(62vh, 560px); }
.hero-bg { position: absolute; inset: 0; z-index: -2; }
.hero-bg video, .hero-bg img { width: 100%; height: 100%; object-fit: cover; }
.hero-veil {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(to top, var(--ink) 2%, color-mix(in oklab, var(--ink) 78%, transparent) 34%, color-mix(in oklab, var(--ink) 30%, transparent) 72%, color-mix(in oklab, var(--ink) 55%, transparent) 100%),
    linear-gradient(to right, color-mix(in oklab, var(--ink) 68%, transparent), transparent 62%);
}
.hero-in { width: 100%; max-width: var(--max); margin-inline: auto; padding: var(--gut) var(--gut) clamp(2.5rem, 6vw, 5rem); }
.hero h1 { max-width: 20ch; }
.hero .lede { margin-top: 1.5rem; }
.hero-meta {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; margin-top: 2rem;
  font: 400 var(--text-xs)/1.4 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--bone-3);
}
.hero-meta span { display: flex; align-items: center; gap: 0.5rem; }
.hero-meta span::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }

.rule { height: 3px; width: 56px; background: var(--accent); margin-bottom: 1.75rem; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.55rem;
  min-height: 46px; padding: 0 1.4rem;
  border-radius: var(--radius); border: 1px solid transparent;
  font: 600 var(--text-sm)/1 var(--font-body); letter-spacing: 0.01em;
  text-decoration: none; cursor: pointer;
  transition: transform 0.15s var(--ease), background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn-p { background: var(--accent); color: var(--accent-ink); }
.btn-p:hover { background: color-mix(in oklab, var(--accent) 82%, var(--bone)); color: var(--accent-ink); }
.btn-s { background: transparent; color: var(--bone); border-color: var(--line-hard); }
.btn-s:hover { background: var(--ink-2); color: var(--bone); border-color: var(--bone-4); }
.btnrow { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 2rem; }

/* ---------- cards ---------- */
.card {
  background: var(--ink-1);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
  padding: clamp(1.25rem, 2.2vw, 1.85rem);
}
.card-raised { background: var(--ink-2); }
.card h3, .card h4 { margin-bottom: 0.6rem; }
.card p:last-child { margin-bottom: 0; }

.tile {
  position: relative; display: block;
  background: var(--ink-1); border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg); overflow: hidden;
  text-decoration: none; color: inherit;
  transition: border-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.tile:hover { border-color: color-mix(in oklab, var(--tile-accent, var(--accent)) 50%, transparent); transform: translateY(-3px); color: inherit; }
.tile-media { position: relative; aspect-ratio: 16 / 9; overflow: hidden; background: var(--ink-3); }
/* The hero stills are deliberately dark cinematic frames (mean luminance 15-55).
   At thumbnail size they read as solid black, so lift them here rather than
   brightening the source art, which still needs to sit behind hero text. */
.tile-media img, .tile-media video {
  width: 100%; height: 100%; object-fit: cover;
  filter: brightness(1.85) saturate(1.12) contrast(0.95);
  transition: transform 0.7s var(--ease), filter 0.4s var(--ease);
}
.tile:hover .tile-media img { transform: scale(1.035); filter: brightness(2.05) saturate(1.2) contrast(0.95); }
/* Only a shallow bottom blend into the card body — the tile text sits below the
   media, not over it, so a full-height scrim buys nothing and costs the image. */
.tile-media::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to top, color-mix(in oklab, var(--ink-1) 88%, transparent), transparent 42%);
}
.tile-body { padding: clamp(1.1rem, 2vw, 1.6rem); }
.tile-body h3 { margin-bottom: 0.45rem; }
.tile-body p { color: var(--bone-3); font-size: var(--text-sm); margin-bottom: 0.9rem; }
.tile-sub { font: 400 var(--text-xs)/1 var(--font-mono); color: var(--bone-4); letter-spacing: 0.04em; word-break: break-all; }
.tile-tag {
  position: absolute; left: 1rem; top: 1rem; z-index: 2;
  font: 500 0.62rem/1 var(--font-mono); letter-spacing: 0.16em; text-transform: uppercase;
  padding: 0.42rem 0.6rem; border-radius: var(--radius-sm);
  background: color-mix(in oklab, var(--ink) 82%, transparent);
  border: 1px solid color-mix(in oklab, var(--tile-accent, var(--accent)) 45%, transparent);
  color: color-mix(in oklab, var(--tile-accent, var(--accent)) 66%, #EDE8E0);
  backdrop-filter: blur(6px);
}

/* ---------- status pills (shared evidence grammar) ---------- */
.pill {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font: 500 0.66rem/1 var(--font-mono); letter-spacing: 0.13em; text-transform: uppercase;
  padding: 0.4rem 0.6rem; border-radius: var(--radius-sm);
  border: 1px solid currentColor;
  white-space: nowrap;
}
.pill::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.pill-confirmed  { color: var(--st-confirmed); }
.pill-reported   { color: var(--st-reported); }
.pill-contested  { color: var(--st-contested); }
.pill-allegation { color: var(--st-allegation); }
.pill-neutral    { color: var(--st-neutral); }
.pill-effective  { color: var(--lb-effective); }
.pill-enjoined   { color: var(--lb-enjoined); }
.pill-appealed   { color: var(--lb-appealed); }
.pill-pending    { color: var(--lb-pending); }
.pill-decided    { color: var(--lb-decided); }
.pill-plain { border-color: var(--line); color: var(--bone-3); }
.pill-plain::before { display: none; }

/* ---------- legend ---------- */
.legend { display: flex; flex-wrap: wrap; gap: 0.6rem 1rem; align-items: center; }
.legend-item { display: flex; align-items: baseline; gap: 0.5rem; font-size: var(--text-sm); color: var(--bone-3); }

/* ---------- stat blocks ---------- */
.stats { display: grid; gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); border-radius: var(--radius-lg); overflow: hidden; grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); }
.stat { background: var(--ink-1); padding: clamp(1.1rem, 2vw, 1.6rem); }
.stat-v { font: 500 clamp(1.85rem, 1.2rem + 2.2vw, 2.9rem)/1 var(--font-mono); color: var(--bone); font-variant-numeric: tabular-nums; letter-spacing: -0.03em; display: block; }
.stat-v em { font-style: normal; font-size: 0.5em; color: var(--bone-3); margin-left: 0.2em; }
.stat-l { display: block; margin-top: 0.6rem; font-size: var(--text-sm); color: var(--bone-3); line-height: 1.4; }
.stat-src { display: block; margin-top: 0.7rem; font: 400 0.66rem/1.3 var(--font-mono); }
.stat-src a { color: var(--bone-4); }
.stat-src a:hover { color: var(--accent-text); }
.stat-accent .stat-v { color: var(--accent-text); }

/* ---------- tables ---------- */
.tablewrap { overflow-x: auto; border: 1px solid var(--line-soft); border-radius: var(--radius-lg); background: var(--ink-1); }
table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); min-width: 640px; }
thead th {
  text-align: left; padding: 0.85rem 1rem; background: var(--ink-2);
  font: 500 var(--text-xs)/1.2 var(--font-mono); letter-spacing: 0.11em; text-transform: uppercase; color: var(--bone-3);
  border-bottom: 1px solid var(--line); white-space: nowrap; position: sticky; top: 0;
}
tbody td { padding: 0.85rem 1rem; border-bottom: 1px solid var(--line-soft); vertical-align: top; color: var(--bone-2); }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: color-mix(in oklab, var(--bone) 3%, transparent); }
td .src { display: block; margin-top: 0.35rem; font: 400 0.66rem/1.3 var(--font-mono); }
td .src a { color: var(--bone-4); }
td .src a:hover { color: var(--accent-text); }
td b { color: var(--bone); }

/* ---------- steps / protocol ---------- */
.steps { counter-reset: s; display: grid; gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); border-radius: var(--radius-lg); overflow: hidden; }
.step { counter-increment: s; background: var(--ink-1); padding: clamp(1.2rem, 2.2vw, 1.9rem); display: grid; grid-template-columns: auto 1fr; gap: 1.1rem; align-items: start; }
.step::before {
  content: counter(s, decimal-leading-zero);
  font: 500 var(--text-sm)/1 var(--font-mono); color: var(--accent-text);
  border: 1px solid color-mix(in oklab, var(--accent) 40%, transparent);
  border-radius: 50%; width: 34px; height: 34px; display: grid; place-items: center; flex-shrink: 0;
}
.step h4 { margin-bottom: 0.4rem; }
.step p:last-child { margin-bottom: 0; }
.step p { font-size: var(--text-sm); color: var(--bone-3); }

/* ---------- explainer video block ---------- */
.explainer { background: var(--ink-1); border: 1px solid var(--line-soft); border-radius: var(--radius-lg); overflow: hidden; }
.explainer video { width: 100%; aspect-ratio: 16 / 9; background: #000; object-fit: cover; }
.explainer-body { padding: clamp(1.1rem, 2vw, 1.6rem); border-top: 1px solid var(--line-soft); }
.explainer-body h4 { margin-bottom: 0.4rem; }
.explainer-body p { font-size: var(--text-sm); color: var(--bone-3); margin-bottom: 0; }

/* Two explainers in one Watch band, where a surface ships an accessible film and
   a detailed one. The accessible film always comes first in the DOM: a reader who
   stops after the first video should still have been given the useful one. */
.explainer-stack { display: grid; gap: clamp(1rem, 2vw, 1.5rem); align-content: start; }

/* ---------- plain-language callout ---------- */
.plain {
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(1.25rem, 2.2vw, 1.9rem);
}
.plain .kicker { color: var(--bone-4); }
.plain p { color: var(--bone-2); margin-bottom: 0; }
.plain p + p { margin-top: 0.8rem; }

/* ---------- footer ---------- */
.foot { border-top: 1px solid var(--line); background: var(--ink-1); padding-block: clamp(2.5rem, 5vw, 4rem); margin-top: clamp(3rem, 6vw, 6rem); }
.foot-grid { display: grid; gap: clamp(1.75rem, 4vw, 3.5rem); grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.4fr); }
@media (max-width: 780px) { .foot-grid { grid-template-columns: 1fr; } }
.foot h4 { font: 500 var(--text-xs)/1 var(--font-mono); letter-spacing: 0.16em; text-transform: uppercase; color: var(--bone-4); margin-bottom: 1.1rem; }
.foot p { font-size: var(--text-sm); color: var(--bone-3); }
.footlinks { display: grid; gap: 0.55rem 1.5rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr)); list-style: none; margin: 0; padding: 0; }
.footlinks a { display: flex; align-items: center; gap: 0.55rem; font-size: var(--text-sm); text-decoration: none; color: var(--bone-2); }
.footlinks a:hover { color: var(--accent-text); }
.footlinks i { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.foot-base { margin-top: clamp(2rem, 4vw, 3rem); padding-top: 1.5rem; border-top: 1px solid var(--line-soft); display: flex; flex-wrap: wrap; gap: 0.75rem 2rem; font: 400 var(--text-xs)/1.5 var(--font-mono); color: var(--bone-4); letter-spacing: 0.04em; }
.foot-base a { color: var(--bone-3); }

/* ---------- misc utility ---------- */
.mono-sm { font: 400 var(--text-xs)/1.5 var(--font-mono); color: var(--bone-4); letter-spacing: 0.06em; }
.muted { color: var(--bone-3); }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.mt0 { margin-top: 0; }
.mb0 { margin-bottom: 0; }
.stack > * + * { margin-top: 1rem; }
.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.srclist { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.65rem; }
.srclist li { font-size: var(--text-sm); padding-left: 1.1rem; position: relative; color: var(--bone-3); }
.srclist li::before { content: ''; position: absolute; left: 0; top: 0.62em; width: 5px; height: 5px; border-radius: 50%; background: var(--bone-4); }

/* reveal on scroll */
.rv { opacity: 0; transform: translateY(18px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.rv.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .rv { opacity: 1; transform: none; } }

/* ==========================================================================
   LIGHT / DARK THEME
   The suite was built dark. Read on a bright screen, the documentary stills
   and the tileless atlas map both collapsed toward black, so light is now the
   default reading surface and dark is a deliberate choice. Every colour in
   this stylesheet already comes from a token, so the flip below is complete:
   only the surface ramp and the type ramp change hands.
   ========================================================================== */

html[data-theme='light'] {
  /* --- surfaces: warm paper, not clinical white --- */
  --ink:        #FBFAF6;
  --ink-1:      #FFFFFF;
  --ink-2:      #F5F2EC;
  --ink-3:      #EAE6DE;
  --ink-4:      #D9D4C9;

  /* --- type: the ramp inverts, darkest first --- */
  --bone:       #14181B;
  --bone-2:     #2C3237;
  --bone-3:     #4E555B;
  --bone-4:     #5C6369;

  /* Rules are mixed from --bone, so they invert on their own, but the
     dark-theme weights read as heavy pencil on paper. Re-pin them lighter. */
  --line:      color-mix(in oklab, var(--bone) 13%, transparent);
  --line-soft: color-mix(in oklab, var(--bone) 8%, transparent);
  --line-hard: color-mix(in oklab, var(--bone) 24%, transparent);

  /* Status and label colours were chosen to glow on near-black. On paper they
     need darkening to hold 4.5:1 against white. Same hues, same meanings. */
  --st-confirmed:  #2F6B59;
  --st-reported:   #3E5C85;
  --st-contested:  #8A5A16;
  --st-allegation: #8E332B;
  --st-neutral:    #545A60;

  --lb-effective: #2F6B59;
  --lb-enjoined:  #8E332B;
  --lb-appealed:  #8A5A16;
  --lb-pending:   #3E5C85;
  --lb-decided:   #4E555B;

  /* Accent labels, darkened until they hold 4.5:1 on paper. */
  --accent-text: color-mix(in oklab, var(--accent) 52%, #0B0D0F);
}

/* The hero keeps its dark cinematic band in BOTH themes. The stills are dark
   footage; a pale veil over them would wash the picture out and leave nothing
   to look at. So the dark palette stays scoped to the hero and the page below
   it turns to paper. */
html[data-theme='light'] .hero {
  --ink:        #0B0D0F;
  --ink-1:      #101316;
  --ink-2:      #161A1E;
  --ink-3:      #1E2429;
  --ink-4:      #2A3237;
  --bone:       #EDE8E0;
  --bone-2:     #C6C0B7;
  --bone-3:     #A8A29A;
  --bone-4:     #8A8781;
  --line:      color-mix(in oklab, #EDE8E0 12%, transparent);
  --line-soft: color-mix(in oklab, #EDE8E0 7%, transparent);
  --line-hard: color-mix(in oklab, #EDE8E0 22%, transparent);
  /* The hero stays cinematic in both themes, so anything tuned for paper has to
     be handed back its dark-surface value here — otherwise the kicker and the
     status dots vanish into the photograph. */
  --accent-text: color-mix(in oklab, var(--accent) 76%, #EDE8E0);
  --st-confirmed:  #4F9481;
  --st-reported:   #6683AD;
  --st-contested:  #C98A3C;
  --st-allegation: #CE6C60;
  --st-neutral:    #9AA0A6;
}

/* The original veil ran to 78% opacity by a third of the way up the frame,
   which is why the picture read as black. Hold the bottom strong enough to
   carry the headline, then get out of the image's way. */
.hero-veil {
  background:
    linear-gradient(to top,
      var(--ink) 0%,
      color-mix(in oklab, var(--ink) 86%, transparent) 16%,
      color-mix(in oklab, var(--ink) 52%, transparent) 40%,
      color-mix(in oklab, var(--ink) 14%, transparent) 72%,
      color-mix(in oklab, var(--ink) 34%, transparent) 100%),
    linear-gradient(to right, color-mix(in oklab, var(--ink) 58%, transparent), transparent 58%);
}

/* Lift the footage itself rather than re-grading the source files, which still
   have to work as poster frames and as tile thumbnails. */
/* Each surface's footage was graded to a different depth (source mean luminance
   runs from 15 to 54), so a single multiplier leaves the darkest ones black and
   blows out the lightest. Per-surface lift, set on :root in each page. */
.hero-bg video, .hero-bg img {
  filter: brightness(var(--hero-lift, 1.34)) saturate(1.06) contrast(0.97);
}

/* ---------- theme switch ---------- */
.themebtn {
  appearance: none; cursor: pointer; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
  min-height: 38px; min-width: 38px; padding: 0 0.7rem;
  background: var(--ink-2); color: var(--bone-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: 500 var(--text-xs)/1 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.themebtn:hover { background: var(--ink-3); color: var(--bone); border-color: var(--line-hard); }
.themebtn svg { width: 15px; height: 15px; flex-shrink: 0; }
.themebtn .themelab { display: inline; }
/* Below the switcher breakpoint the label goes and the icon carries it. */
@media (max-width: 620px) {
  .themebtn { padding: 0 0.5rem; }
  .themebtn .themelab { display: none; }
}
/* Only one icon shows at a time: the one for the theme you'd switch TO. */
html[data-theme='light'] .themebtn .ico-dark { display: block; }
html[data-theme='light'] .themebtn .ico-light { display: none; }
html[data-theme='dark'] .themebtn .ico-dark { display: none; }
html[data-theme='dark'] .themebtn .ico-light { display: block; }

/* Leaflet's own chrome and the attribution strip follow the tokens too. */
html[data-theme='light'] .leaflet-control-attribution { background: color-mix(in oklab, var(--ink-1) 86%, transparent); color: var(--bone-3); }
html[data-theme='light'] .leaflet-control-attribution a { color: var(--bone-2); }

/* The switch adds ~44px to the bar. Give the surface name less room on phones
   so the header still holds one line and nothing scrolls sideways. */
@media (max-width: 620px) {
  .door-name { max-width: 44vw; }
}

/* Leaflet ships its own colours for the disabled zoom button (#bbb on #f4f4f4,
   a 1.75:1 pair). Bring it onto the tokens in both themes. */
.leaflet-control-zoom a.leaflet-disabled {
  background: var(--ink-3) !important;
  color: var(--bone-4) !important;
  border-color: var(--line) !important;
}

/* Region codes and tile tags take their colour from data (a region's or a
   surface's own accent) via an inline style, so no token can reach them. The
   vivid values were picked to glow on near-black and sit at 3.1-3.9:1 on paper.
   Darkening them here keeps each item's identity colour while clearing 4.5:1,
   and it costs nothing in the dark theme. */
html[data-theme='light'] .rcode { color: color-mix(in oklab, var(--rc) 48%, #0B0D0F); }
html[data-theme='light'] .tile-tag { color: color-mix(in oklab, var(--tile-accent, var(--accent)) 48%, #0B0D0F); }
