/* Forecast Seed — the design system.
 *
 * This file is Forecast dBZ's `site.css` (itself weather.city's highway-signage
 * system, shared byte for byte across the network) with Forecast Seed's own marks
 * appended at the end. Do not restyle the shared tokens here — a network fix
 * belongs upstream and re-copied, the same way the siblings stay in step.
 *
 * The original header follows, for the reasoning; read "dBZ" as "the network".
 *
 * ---------------------------------------------------------------------------
 * Forecast dBZ — the design system, shared by the documents and the explorer.
 *
 * This is weather.city's highway-signage system, shared unchanged with Forecast
 * Eagle so the three sites read as one network: MUTCD guide-sign green #04663d,
 * motorist-services blue #0a5ca8, warm paper ground #e6e2da, and Overpass — the
 * open, metric-compatible cut of FHWA Highway Gothic, which is the actual
 * Interstate signage face.
 *
 * Forecast Eagle's own note within that system is the Interstate route shield.
 * Forecast dBZ's is **the reflectivity scale itself** — the green-yellow-red
 * ramp every American has been reading off a television since childhood. It is
 * already a piece of signage: a legend, meant to be read at a glance, with hard
 * class edges and no ambiguity about which end is worse. So the site's mark is
 * its own colour bar, and the highway motif and the radar identity end up being
 * one thing rather than two competing ones.
 *
 * The document is light paper throughout. Radar sits in a dark inset panel, the
 * same way weather.city frames its national outlook figures and for the same
 * reason: reflectivity needs a dark ground, the surrounding page does not.
 *
 * WHY THIS FILE IS THE ONE FILE.
 * There were three partial copies of the tokens below on this site: site.css for
 * the documents, explorer.css for the two viewers, and a third set inlined in
 * mrms.html. They had already begun to disagree — explorer.css was three Eagle
 * releases stale, and site.css never had the buttons at all. So this is now the
 * whole system, and it is Forecast Eagle's `forecasteagle.css` byte for byte
 * apart from the four blocks at the end, which are the marks and the prose
 * treatments only this site has. The explorer *chrome* — the primary strip, the
 * drawer, the stage — is `explorer.css`, exactly as it is on Eagle, so the two
 * sites mean the same thing by the same filename.
 *
 * `forecastdbz.css` is a separate thing again: the full-bleed phone viewer that
 * predates the explorer. It is not part of this system.
 */

:root {
  --paper: #e6e2da;
  --card: #ffffff;
  --ink: #161616;
  --ink2: #4a463e;
  --sign: #04663d;
  --sign-dk: #013d26;
  --sign-tx: #ffffff;
  --sign-sub: #bdebcf;
  --blue: #0a5ca8;
  --navy: #103e7e;
  --blue-sub: #cfe2f6;
  --line: #c9c5bc;
  --line2: #e4e1d9;
  --mut: #8a867c;
  --shield-red: #c0331a;
  --amber: #f2ac14;

  /* Ink that goes ON an accent surface. Three tokens rather than a literal #fff,
     because in the dark theme every accent becomes luminous and wants near-black
     ink instead — see the dark block below. */
  --sign-tx: #ffffff;
  --blue-tx: #ffffff;
  --red-tx: #ffffff;
  --blue-dk: #08488a;
  --blue-hi: #0b6bc4;

  /* Surfaces below the card: input fields, quiet chips, code. */
  --card2: #efece5;
  --field: #ffffff;
  --footer-bg: #ddd8ce;

  /* The utility bar is its own small system: dark on a light page, and on a dark
     page it is the page. */
  --util-bg: #161616;
  --util-tx: #e9e7e0;
  --util-mut: #cfccc4;

  /* Panel lift. On paper this is a drop shadow; in the dark theme a drop shadow
     is invisible against near-black and the job is done by a hairline and a faint
     inner highlight instead. */
  --shadow: 0 6px 22px rgba(0, 0, 0, .08);
  --shadow-lg: 0 10px 30px rgba(0, 0, 0, .16);
  --shadow-util: 0 1px 8px rgba(0, 0, 0, .22);
  /* The white keyline inside a guide sign — real signs have one, and it is what
     makes the green read as a sign rather than a coloured box. */
  --sign-keyline: rgba(255, 255, 255, .9);
  --sign-keyline2: rgba(255, 255, 255, .35);

  /* Dark inset used for model/satellite imagery panels */
  --figure: #0a0e14;
  --figure-line: #223142;

  /* The map inset's own small palette. These readouts sit ON the radar, so they
     stay deliberately neutral in BOTH themes: an accent here would compete with
     the reflectivity ramp, and the one thing a radar viewer must never do is put
     a colour next to the field that could be mistaken for part of it. */
  --fig-panel: rgba(10, 14, 20, .84);
  --fig-line: #223142;
  --fig-tx: #e9e7e0;
  --fig-hi: #ffffff;
  --fig-sub: #9fb0c2;
  --fig-hover: rgba(255, 255, 255, .16);
  --ctrl-scale: rgba(255, 255, 255, .82);
  --error-tx: #8a1f2c;

  /* HUD-only effects. Inert on paper — a glow on a white page is a smudge. */
  --glow: none;
  --glow-soft: none;
  --hud-tick: transparent;
  --scrim: transparent;

  --font: 'Overpass', Helvetica, Arial, sans-serif;
  --mono-font: 'Overpass Mono', ui-monospace, monospace;
  --maxw: 1080px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }

.mono { font-family: var(--mono-font); font-variant-numeric: tabular-nums; }
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 18px; }
.wrap-wide { max-width: 1560px; margin: 0 auto; padding: 0 18px; }

/* ── thin utility bar ─────────────────────────────────── */
.util {
  background: var(--util-bg); color: var(--util-mut); border-bottom: 3px solid var(--sign);
  position: sticky; top: 0; z-index: 100; box-shadow: var(--shadow-util);
}
.util .bar {
  max-width: 1560px; margin: 0 auto; padding: 0 18px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 34px; flex-wrap: wrap;
}
.util .mono { font-size: 11px; letter-spacing: .06em; }
.util .lnks { display: flex; gap: 16px; flex-wrap: wrap; }
.util a { color: var(--util-tx); font-weight: 700; font-size: 11px; letter-spacing: .06em; }
.util a:hover { color: var(--sign-sub); text-decoration: none; }
.util a[aria-current="page"] { color: var(--sign-sub); }

/* ── guide sign panel ─────────────────────────────────── */
.sign {
  background: var(--sign); border-radius: 10px; color: var(--sign-tx);
  padding: 26px 24px 24px; position: relative;
  box-shadow: inset 0 0 0 4px var(--sign), inset 0 0 0 6px var(--sign-keyline),
              var(--shadow-lg);
}
.sign a { color: var(--sign-tx); }
.signhead { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.signhead img { width: 62px; height: 62px; flex: none; display: block; }
.word {
  font-weight: 900; font-size: clamp(28px, 5.4vw, 50px); line-height: .92;
  letter-spacing: -.02em; margin: 0;
}
.word .yl { color: var(--sign-sub); }
.tag {
  margin: 8px 0 0; font-weight: 700; font-size: clamp(13px, 2.2vw, 16px);
  color: var(--sign-sub); letter-spacing: .01em;
}

/* Route shield marker, as used on real guide signs */
.shield {
  border: 2.5px solid var(--sign-tx); border-radius: 6px; padding: 5px 10px 6px;
  text-align: center; line-height: 1; flex: none; display: inline-block;
}
.shield .a { font-size: 8px; font-weight: 700; letter-spacing: .16em; color: var(--sign-sub); }
.shield .b { font-size: 20px; font-weight: 900; letter-spacing: .04em; display: block; }
.shield .c { font-size: 8px; font-weight: 700; letter-spacing: .12em; color: var(--sign-sub); }

/* Exit-style chips */
.exits { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; align-items: center; }
.exits .lbl { font-size: 11px; font-weight: 700; letter-spacing: .14em; color: var(--sign-sub); }
.mm {
  background: rgba(255, 255, 255, .1); border: 1.5px solid rgba(255, 255, 255, .55);
  border-radius: 5px; padding: 6px 12px; font-family: inherit; font-weight: 700;
  font-size: 12px; letter-spacing: .03em; cursor: pointer; color: var(--sign-tx);
}
.mm:hover { background: var(--sign-tx); color: var(--sign); text-decoration: none; }

/* ── section rule header ──────────────────────────────── */
section { padding: 26px 0 4px; }
.rule { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.rule .ln {
  height: 3px; flex: 1;
  background: repeating-linear-gradient(90deg, var(--sign) 0 18px, transparent 18px 34px);
}
.rule h2 {
  margin: 0; color: var(--sign); font-size: 15px; font-weight: 900;
  text-transform: uppercase; letter-spacing: .12em; white-space: nowrap;
}
.rule .sub { color: var(--mut); font-size: 11px; font-weight: 700; letter-spacing: .06em; }

/* ── cards ────────────────────────────────────────────── */
.card-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 0; overflow: hidden; display: block; color: inherit;
  box-shadow: var(--shadow); transition: transform .14s, box-shadow .14s;
}
a.card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); text-decoration: none; }
.card .chead {
  background: var(--sign); color: var(--sign-tx); padding: 9px 14px;
  box-shadow: inset 0 0 0 1.5px var(--sign-keyline2);
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
}
.card .chead.blue { background: var(--blue); }
.card .chead .k { font-size: 10px; font-weight: 700; letter-spacing: .1em; color: var(--sign-sub); }
.card .chead.blue .k { color: var(--blue-sub); }
.card .cbody { padding: 14px; }
.card h3 { margin: 0 0 5px; font-size: 17px; font-weight: 900; letter-spacing: -.01em; }
.card p { margin: 0; color: var(--ink2); font-size: 13.5px; font-weight: 600; line-height: 1.5; }

.panel {
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 16px; box-shadow: var(--shadow);
}

/* ── controls ─────────────────────────────────────────── */
.btn {
  cursor: pointer; border: 1px solid var(--line); background: var(--field); color: var(--ink2);
  border-radius: 3px; font-family: var(--font); font-weight: 700; font-size: 11.5px;
  letter-spacing: .02em; padding: 7px 12px; line-height: 1.3;
}
.btn:hover { border-color: var(--sign); color: var(--ink); }
.btn.on, .btn[aria-pressed="true"] { background: var(--blue); color: var(--blue-tx); border-color: var(--blue-dk); }
.btn:disabled { opacity: .5; cursor: default; }
.btn-go { background: var(--blue); color: var(--blue-tx); border-color: var(--blue-dk); font-weight: 900; letter-spacing: .06em; }
.btn-go:hover { background: var(--blue-hi); color: var(--blue-tx); }

select, input[type="text"], input[type="search"] {
  background: var(--field); border: 1px solid var(--line); color: var(--ink);
  border-radius: 3px; padding: 6px 9px; font-family: var(--font);
  font-weight: 700; font-size: 12px;
}
select:focus, input:focus, .btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

label { font-size: 9.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--mut); }

/* ── timeline ─────────────────────────────────────────────
   Transport, scrubber and a UTC tick strip, in one card under the map. Shared by
   every model viewer (see assets/maptimeline.js), because a forecast loop is a
   forecast loop whether the frames are RRFS quarter-hours or NDFD forecast days.

   The range is index-based, so every frame gets equal width and the thumb always
   lands on one, and ticks are drawn on frames rather than at arbitrary clock times.
   Labels therefore thin out across a run exactly where its cadence coarsens. */
.timeline {
  display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap;
  margin-top: 12px; background: var(--card); border: 1px solid var(--line);
  border-radius: 8px; padding: 10px 14px 9px; box-shadow: var(--shadow);
}
.tl-side { display: flex; flex-direction: column; gap: 5px; }
.tl-lab { font-size: 9px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--mut); }
.tl-transport { display: flex; align-items: center; gap: 5px; }
.tl-track { flex: 1 1 340px; min-width: 240px; display: flex; flex-direction: column; }
.tl-track input[type="range"] { width: 100%; margin: 0; accent-color: var(--sign); }
/* Inset by half a thumb so the first and last ticks sit under the thumb's travel,
   not under the ends of the groove the thumb never reaches. */
.tl-ticks { position: relative; height: 23px; margin: 3px 9px 0; pointer-events: none; }
.tl-ticks .tk { position: absolute; top: 0; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; }
.tl-ticks .tk.at-start { transform: translateX(-2px); align-items: flex-start; }
.tl-ticks .tk.at-end { transform: translateX(calc(-100% + 2px)); align-items: flex-end; }
.tl-ticks .tk i { width: 1px; height: 5px; background: var(--line); display: block; }
.tl-ticks .tk span { font: 700 8.5px var(--mono-font); color: var(--mut);
  white-space: nowrap; line-height: 1; margin-top: 3px; letter-spacing: .02em; }
/* The tick that opens each forecast day carries the date and the signage green;
   the hours within that day are hairlines. */
.tl-ticks .tk.day i { height: 9px; width: 2px; background: var(--sign); }
.tl-ticks .tk.day span { color: var(--ink2); font-weight: 800; }
/* Buffer fill. Sits between the scrubber and the tick strip, so the thing that says
   "the loop is ready" is directly under the thing you drag. It fades out once full
   rather than staying as chrome nobody needs. */
.tl-buffer { height: 2px; margin: 2px 9px 0; border-radius: 2px; background: var(--line2);
  overflow: hidden; transition: opacity .4s ease .3s; }
.tl-buffer::before { content: ""; display: block; height: 100%; width: var(--pct, 0%);
  background: var(--sign); transition: width .15s linear; }
.tl-buffer.is-full { opacity: 0; }
.tl-ends { display: flex; justify-content: space-between; gap: 10px;
  font: 700 9.5px var(--mono-font); color: var(--mut); letter-spacing: .02em; }
.tl-count { font: 900 13px var(--mono-font); color: var(--ink); }
.tl-hint { margin-top: 7px; font-size: 11px; font-weight: 700; color: var(--mut); }

/* Segmented control — the speed menu, and anything else that is one choice of a few */
.seg { display: flex; }
.seg button { font: 700 11px var(--mono-font); background: var(--card); color: var(--ink2);
  border: 1px solid var(--line); border-left-width: 0; padding: 5px 8px; cursor: pointer; }
.seg button:first-child { border-left-width: 1px; border-radius: 4px 0 0 4px; }
.seg button:last-child { border-radius: 0 4px 4px 0; }
.seg button:hover { color: var(--ink); }
.seg button.on { background: var(--sign); color: var(--sign-tx); border-color: var(--sign); }
.seg button:disabled { cursor: not-allowed; }
/* A segment the active model or cycle cannot drive at all. Greyed as a block rather
   than hidden: a control that quietly vanishes reads as a bug, one that is greyed out
   reads as an answer, and a control strip that changes length as you switch models is
   disorienting. */
.seg.unavailable { opacity: .35; }
.seg.unavailable button { cursor: not-allowed; text-decoration: line-through;
  text-decoration-thickness: 1px; }

/* ── misc ─────────────────────────────────────────────── */
.badge {
  display: inline-block; padding: 3px 9px; border-radius: 3px;
  font-size: 10px; font-weight: 900; letter-spacing: .08em; text-transform: uppercase;
}
.badge-live { background: var(--sign); color: var(--sign-tx); }
.badge-new { background: var(--shield-red); color: var(--red-tx); }
.badge-soon { background: var(--card2); color: var(--mut); border: 1px solid var(--line); }

.dim { color: var(--ink2); }
.faint { color: var(--mut); }

.site-footer {
  border-top: 3px solid var(--sign); margin-top: 44px; padding: 18px 0 34px;
  color: var(--ink2); font-size: 12px; font-weight: 600; background: var(--footer-bg);
}
.site-footer a { color: var(--navy); font-weight: 800; }

.skip {
  position: absolute; left: -9999px; top: 0; background: var(--sign); color: var(--sign-tx);
  padding: 9px 14px; z-index: 200; font-weight: 800;
}
.skip:focus { left: 0; }

/* A phone gets the links as one row it can thumb sideways, not three wrapped ones. */
@media (max-width: 700px) {
  .util .bar { flex-wrap: nowrap; gap: 0; padding: 0 10px; }
  .util .bar > .mono { display: none; }
  .util .lnks { flex-wrap: nowrap; overflow-x: auto; gap: 14px; padding: 10px 0;
                scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .util .lnks::-webkit-scrollbar { display: none; }
  .util a { white-space: nowrap; }
}

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

/* ── wind overlay and its options ─────────────────────────────
   The overlay is its own canvas above the map, because a streamline animation
   composites frame to frame and must not be cleared by MapLibre's own redraw. */
#wind-overlay { position: absolute; inset: 0; z-index: 4; pointer-events: none; }

/* The `hidden` attribute is a promise the HTML makes, and a layout rule as ordinary as
   `.toolbar .group > div { display: flex }` outranks it on specificity and quietly
   breaks it. Restore it once, globally, rather than per component. */
[hidden] { display: none !important; }

/* Sub-controls of the wind mode segment, styled as subordinate to it: indented under a
   rule, smaller labels, and absent outright when the mode has nothing for them. */
.wind-opts { display: flex; flex-direction: column; gap: 5px; margin-top: 6px;
             padding-left: 9px; border-left: 2px solid var(--line2, var(--line)); }
.wind-opt { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.wind-opt label { font-size: 9px; letter-spacing: .09em; }
.wind-opt select { padding: 3px 5px; font-size: 11px; font-weight: 700; min-width: 92px; }

/* ── buffer policy chrome ──────────────────────────────────
   The buffer bar's dashed tail is the part of the run deliberately not fetched
   (see Timeline.buffer in maptimeline.js); LOAD ALL beside the frame counter fetches
   it, and says what that costs. */
.tl-buffer.is-held::after {
  content: ""; position: absolute; right: 0; top: 0; height: 100%; width: var(--held, 0%);
  background: repeating-linear-gradient(90deg, var(--line) 0 3px, transparent 3px 6px);
}
.tl-buffer { position: relative; }
.tl-load { font-size: 10px; padding: 4px 8px; margin-top: 4px; letter-spacing: .06em;
           font-family: var(--mono-font); white-space: nowrap; }
.tl-load:hover { border-color: var(--sign); color: var(--sign); }

/* ══ what only Forecast dBZ has ═══════════════════════════════════════════════
   Everything above this line is Forecast Eagle's `forecasteagle.css`, unchanged.
   Everything below is this site's own: its mark, the dark inset radar sits in,
   and the prose and table treatments the document pages use. Keeping the split
   visible is what lets the shared half be re-synced from Eagle by replacing it
   wholesale, which is how it fell three releases behind the last time. */

/* The site's mark: a reflectivity scale, built as a piece of signage.
   Values are the ones people quote — 20 is rain, 40 is heavy, 60 is a core. */
.dbzmark {
  border: 2.5px solid var(--sign-tx); border-radius: 6px; padding: 5px 8px 6px;
  text-align: center; line-height: 1; flex: none; display: inline-block;
  min-width: 96px;
}
.dbzmark .a { font-size: 8px; font-weight: 700; letter-spacing: .16em; color: var(--sign-sub); }
.dbzmark .bar {
  display: block; height: 9px; margin: 4px 0 3px; border-radius: 2px;
  background: linear-gradient(90deg, #1e8fc8 0%, #189248 22%, #20c42c 40%,
              #faf03c 56%, #f7b028 68%, #e62828 80%, #f03cf0 92%, #9628be 100%);
}
.dbzmark .c { font-size: 8px; font-weight: 700; letter-spacing: .1em; color: var(--sign-sub);
  display: flex; justify-content: space-between; font-family: var(--mono-font); }

.mile { display: flex; align-items: center; gap: 10px; margin-top: 22px; flex-wrap: wrap; }

/* The primary exit chip — the one the landing page actually wants you to take. */
.mm.go { background: var(--sign-tx); color: var(--sign); font-weight: 900; }

/* The colour strip along the top of a product card on the landing page. A card for
   "hail" that does not show you the hail scale has answered the wrong question. */
.card .swatch { display: block; height: 7px; }

/* The document pages' footer carries a link row; the viewers' footer is one line. */
.site-footer .row { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 10px; }

/* The dark inset that radar imagery sits in — the one place the paper ground
   gives way, because reflectivity is unreadable on paper and always was. */
.figure {
  background: var(--figure); border: 1px solid var(--figure-line); border-radius: 8px;
  overflow: hidden; box-shadow: var(--shadow-lg);
}
.figure img { display: block; width: 100%; height: auto; }
.figure .cap {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 9px 13px; border-top: 1px solid var(--figure-line);
  color: #9fb0c2; font-size: 11px; font-weight: 700; flex-wrap: wrap;
}
.figure .cap b { color: #e9eef5; font-weight: 900; }

/* ── prose ────────────────────────────────────────────── */
.prose { max-width: 66ch; }
.prose p { color: var(--ink2); font-size: 14.5px; line-height: 1.62; font-weight: 500; }
.prose h3 { margin: 26px 0 6px; font-size: 15px; font-weight: 900; letter-spacing: -.01em; }
.prose ul { color: var(--ink2); font-size: 14.5px; line-height: 1.62; padding-left: 20px; }
.prose li { margin: 5px 0; }
.prose a { color: var(--navy); font-weight: 800; }
.prose strong { color: var(--ink); }
.prose code {
  font-family: var(--mono-font); font-size: 12.5px; background: var(--card2);
  border: 1px solid var(--line2); border-radius: 3px; padding: 1px 5px;
}

table.data { border-collapse: collapse; width: 100%; font-size: 13px; }
table.data th, table.data td {
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line2);
  font-weight: 600; color: var(--ink2);
}
table.data th {
  font-size: 9.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--mut); border-bottom: 2px solid var(--line);
}
table.data td b { color: var(--ink); font-weight: 900; }
/* A table is the one thing on these pages allowed its own scrollbar: shrinking
   a units column to fit a phone makes it unreadable rather than compact. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ══ the dark theme: a heads-up display ═══════════════════════════════════════
 *
 * WHY THIS SITE GETS ONE AND EAGLE DOES NOT (YET)
 * Forecast Eagle deferred a night theme as "a tokens job across a lot of hard-coded
 * colours". That was true here too and is now done — but the reason to do it here
 * first is not effort, it is subject. Eagle's fields are mostly pale: temperature,
 * cloud cover, mean sea-level pressure all read best on a light ground. Radar does
 * not. Reflectivity has needed a dark ground since the first NEXRAD console, which
 * is why the map on this site has always sat in a dark inset panel while the page
 * around it stayed paper.
 *
 * So the dark theme is not an inversion of the light one. It is **the inset growing
 * to fill the page.** The `--figure` colour the radar has always sat on becomes
 * `--paper`, the frame around the map stops being a frame, and the document turns
 * into the instrument it was always carrying.
 *
 * WHAT MAKES IT A HUD RATHER THAN A DARK MODE
 * Four rules, and they are what the dark block below is arranged around:
 *
 *   1. NOTHING IS A BLOCK OF COLOUR. On paper an active control is a filled green
 *      chip. On a HUD a filled chip is a hole punched in the display — so an active
 *      control is a luminous outline, luminous text and a 12%-alpha wash. The only
 *      solid accent left is the skip link, which is a focus affordance and should
 *      shout.
 *   2. SEPARATION IS BY LINE AND LIGHT, NOT BY SHADOW. A drop shadow on near-black
 *      is invisible; `--shadow` becomes a hairline ring plus a one-pixel inner
 *      highlight, which is how a real panel edge catches light.
 *   3. THE DATA GLOWS, THE FURNITURE DOES NOT. `--glow` is spent only on things
 *      that are readings — the valid time, the value under the pointer, the frame
 *      counter. Spend it on borders and the whole page hums and nothing stands out.
 *   4. THE READOUTS OVER THE MAP STAY NEUTRAL. `--fig-*` gets darker and its
 *      hairline gets brighter, but no accent goes near it. Those boxes sit on the
 *      reflectivity field, and a green chrome element next to a green 30 dBZ echo is
 *      a misreading waiting to happen.
 *
 * THE ACCENT IS THE NETWORK'S GREEN, LIFTED
 * #3ddc84 is MUTCD guide-sign green taken up to something that emits rather than
 * reflects. Amber would be the obvious CRT choice and was rejected: the whole estate
 * — weather.city, Forecast Eagle, this — is identified by that green, and a dark
 * theme that changes the accent stops being the same network after dark. Cyan takes
 * the motorist-services blue's job for the same reason.
 *
 * Every value below clears WCAG AA on both --paper and --card; the ratios are in the
 * README. `theme.js` resolves `system` to an explicit attribute before first paint,
 * so this block is written once rather than duplicated into a media query.
 */
:root[data-theme="dark"] {
  --paper: #05080c;              /* what --figure used to be, now the whole page */
  --card: #0b1119;
  --card2: #131b25;
  --field: #0d151e;
  --ink: #e8eef6;                /* 16.7:1 on --paper */
  --ink2: #a9bacb;               /*  9.7:1 */
  --mut: #74889d;                /*  5.3:1 — labels and units, still AA */
  --line: #1f2b3a;
  --line2: #17212c;

  --sign: #3ddc84;               /* 11.0:1 — guide-sign green, lifted to phosphor */
  --sign-dk: #16342a;
  --sign-tx: #04160c;            /* ink ON the green, for the few solid uses left */
  --sign-sub: #8ceab8;
  --sign-keyline: rgba(61, 220, 132, .55);
  --sign-keyline2: rgba(61, 220, 132, .30);

  --blue: #4fc3f7;               /*  9.8:1 — motorist-services blue, lifted */
  --blue-tx: #04151f;
  --blue-dk: #2b6f92;
  --blue-hi: #7ad4fa;
  --navy: #67d4ff;               /* links: the brightest thing that is not a reading */
  --blue-sub: #a9dff9;

  --shield-red: #ff6b5e;
  --red-tx: #1e0503;
  --amber: #ffbe3d;
  --error-tx: #ff9d93;

  --util-bg: #04070a;
  --util-tx: #cfe0ee;
  --util-mut: #74889d;
  --footer-bg: #04070a;

  /* Rule 2: a ring and an inner highlight, not a shadow. */
  --shadow: 0 0 0 1px rgba(120, 170, 210, .07), 0 1px 0 rgba(180, 220, 255, .05) inset;
  --shadow-lg: 0 0 0 1px rgba(120, 170, 210, .10), 0 14px 40px rgba(0, 0, 0, .60);
  --shadow-util: 0 1px 0 rgba(61, 220, 132, .16);

  /* Rule 4: the map inset, now flush with the page, separated by its hairline. */
  --figure: #05080c;
  --figure-line: #26364a;
  --fig-panel: rgba(4, 8, 13, .80);
  --fig-line: #2c405a;
  --fig-tx: #e6edf5;
  --fig-hi: #ffffff;
  --fig-sub: #93a7bd;
  --fig-hover: rgba(255, 255, 255, .14);
  --ctrl-scale: rgba(6, 11, 18, .82);

  /* Rule 3: spent only on readings. */
  --glow: 0 0 14px rgba(61, 220, 132, .30);
  --glow-soft: 0 0 10px rgba(79, 195, 247, .22);
  --hud-tick: rgba(61, 220, 132, .70);
  --scrim: rgba(61, 220, 132, .035);

  color-scheme: dark;
}

/* ── dark: the components that cannot be re-coloured by token alone ──────────
 *
 * Everything above is a value swap. These are the places where the *construction*
 * has to change, because "a solid block of the accent colour" is the right answer
 * on paper and the wrong one on a display. Each is rule 1 from the block above.
 */

/* An active control: outline, luminous label, a wash you can barely see. On paper
   this is a filled chip; filled here it would read as a cut-out. */
:root[data-theme="dark"] .btn.on,
:root[data-theme="dark"] .btn[aria-pressed="true"] {
  background: color-mix(in srgb, var(--blue) 14%, transparent);
  color: var(--blue); border-color: var(--blue); box-shadow: var(--glow-soft);
}
:root[data-theme="dark"] .btn-go {
  background: color-mix(in srgb, var(--blue) 16%, transparent);
  color: var(--blue); border-color: var(--blue);
}
:root[data-theme="dark"] .btn-go:hover {
  background: color-mix(in srgb, var(--blue) 26%, transparent); color: var(--blue-hi);
}
:root[data-theme="dark"] .seg button.on {
  background: color-mix(in srgb, var(--sign) 14%, transparent);
  color: var(--sign); border-color: var(--sign); box-shadow: var(--glow);
}
:root[data-theme="dark"] .badge-live {
  background: color-mix(in srgb, var(--sign) 13%, transparent);
  color: var(--sign); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sign) 55%, transparent);
}
:root[data-theme="dark"] .badge-new {
  background: color-mix(in srgb, var(--shield-red) 15%, transparent);
  color: var(--shield-red);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--shield-red) 55%, transparent);
}
/* The exception, deliberately: a skip link is a focus affordance and should be the
   loudest thing on the page the instant it appears. */
:root[data-theme="dark"] .skip { background: var(--sign); color: var(--sign-tx); }

/* The guide sign itself. A 50px phosphor-green panel would be a floodlight, so the
   sign keeps its *geometry* — the double keyline, the shield, the exit chips — and
   loses its fill. It still reads as a guide sign because a guide sign is a shape and
   a keyline before it is a colour. */
:root[data-theme="dark"] .sign {
  background: linear-gradient(160deg, #0c1620 0%, #081019 60%, #060c14 100%);
  color: var(--ink);
}
:root[data-theme="dark"] .sign a { color: var(--sign); }
:root[data-theme="dark"] .shield,
:root[data-theme="dark"] .dbzmark { border-color: color-mix(in srgb, var(--sign) 70%, transparent); }
:root[data-theme="dark"] .mm {
  background: color-mix(in srgb, var(--sign) 10%, transparent);
  border-color: color-mix(in srgb, var(--sign) 45%, transparent);
  color: var(--sign);
}
:root[data-theme="dark"] .mm:hover {
  background: color-mix(in srgb, var(--sign) 22%, transparent); color: var(--sign-sub);
}
/* The second exception to rule 1, and the last. `.mm.go` is the single primary exit
   on the landing page — the one thing the page is asking you to do — and an outline
   among five other outlines is not asking. Real HUDs light exactly one annunciator
   at a time for the same reason. */
:root[data-theme="dark"] .mm.go {
  background: var(--sign); color: var(--sign-tx); border-color: var(--sign);
  box-shadow: var(--glow);
}
:root[data-theme="dark"] .mm.go:hover { background: var(--sign-sub); color: var(--sign-tx); }
:root[data-theme="dark"] .card .chead {
  background: color-mix(in srgb, var(--sign) 12%, transparent); color: var(--sign);
}
:root[data-theme="dark"] .card .chead.blue {
  background: color-mix(in srgb, var(--blue) 12%, transparent); color: var(--blue);
}

/* Rule 3: the glow is spent on readings, and this is the list of them. Anything not
   named here is furniture and stays matte. */
:root[data-theme="dark"] .tl-lab { color: var(--mut); }
:root[data-theme="dark"] .mono { text-shadow: 0 0 8px rgba(61, 220, 132, .10); }

/* Fields recede rather than advance: on paper an input is white on grey and comes
   forward, on a display it is a well cut into the panel. */
:root[data-theme="dark"] select,
:root[data-theme="dark"] input[type="text"],
:root[data-theme="dark"] input[type="search"] { box-shadow: inset 0 1px 3px rgba(0, 0, 0, .5); }

/* ── the theme control ───────────────────────────────────
   Lives in the utility bar, which is dark in both themes, so it is styled against
   that rather than against the page. Mono and tracked because it reports a state,
   and fixed-width because a control that changes size as you cycle it makes the
   whole bar twitch. */
.theme-btn {
  background: transparent; border: 1px solid var(--util-line, rgba(255, 255, 255, .22));
  color: var(--util-tx); font-family: var(--mono-font); font-size: 10px;
  font-weight: 700; letter-spacing: .1em; padding: 3px 8px; line-height: 1.4;
  min-width: 76px; text-align: center;
}
.theme-btn:hover { border-color: var(--sign); color: var(--sign-sub); }
.theme-btn:focus-visible { outline: 2px solid var(--sign); outline-offset: 1px; }
:root[data-theme="dark"] .theme-btn {
  border-color: color-mix(in srgb, var(--sign) 38%, transparent); color: var(--sign);
}
:root[data-theme="dark"] .theme-btn:hover {
  background: color-mix(in srgb, var(--sign) 14%, transparent); color: var(--sign-sub);
}
/* The utility bar keeps its own baseline so the button sits on the text, not above it. */
.util .lnks { align-items: center; }


/* The section rule's dashes are signage on paper — a dashed guide-sign underline. At
   full accent strength on black they read as a row of landing lights, so they thin to
   a hairline while the heading itself keeps the accent. */
:root[data-theme="dark"] .rule .ln {
  height: 1px;
  background: repeating-linear-gradient(90deg,
              color-mix(in srgb, var(--sign) 45%, transparent) 0 18px,
              transparent 18px 34px);
}


/* ════════════════════════════════════════════════════════════════════════════
   FORECAST SEED — the marks and treatments only this site has.
   Everything above is the shared network system, untouched.

   Forecast Seed's own note within the system is SILVER — the AgI nucleus. The
   favicon is an ice crystal grown around a silver seed, and the accent below is
   that same metal: a cool grey-silver used sparingly, for the things that are
   about seeding itself (the seedmark, evidence chips, the record ribbon).
   Everything navigational stays guide-sign green and blue like the siblings.
   ════════════════════════════════════════════════════════════════════════════ */

:root {
  --silver: #6b7280;        /* readable silver — ink-weight, for text on paper   */
  --silver-hi: #9aa1ad;     /* the metal itself — borders, marks                 */
  --silver-sub: #e3e6eb;    /* silver wash — chip and ribbon grounds             */
  --silver-dk: #474e59;
}
:root[data-theme="dark"] {
  --silver: #aab2bf;
  --silver-hi: #78808c;
  --silver-sub: #1a2028;
  --silver-dk: #cdd3db;
}

/* The seedmark: the site's badge on the masthead, a small legend of the mechanism.
   Mirrors .dbzmark's construction so the two sites mean the same thing by a mark. */
.seedmark {
  display: inline-flex; flex-direction: column; gap: 4px; padding: 8px 12px;
  border: 1px solid var(--silver-hi); border-radius: 6px;
  font-family: var(--mono-font); font-size: 10px; font-weight: 700;
  letter-spacing: .08em; color: var(--silver); background: transparent;
}
.seedmark .a { color: var(--silver); }
.seedmark .bar {
  height: 6px; border-radius: 3px;
  background: linear-gradient(90deg, var(--silver-hi), #cfd4db 45%, var(--sign) 55%, var(--sign-dk));
}
.seedmark .c { display: flex; justify-content: space-between; gap: 10px; }

/* Evidence chips — every factual claim on this site carries its class of evidence.
   RECORD (a filed report), MEASURED (an observation), MODELED (a simulation),
   CLAIMED (an operator's own number). The reader should never have to wonder
   which one they are looking at. */
.ev {
  display: inline-block; padding: 1px 7px 0; border-radius: 4px;
  font-family: var(--mono-font); font-size: 10px; font-weight: 700;
  letter-spacing: .09em; vertical-align: 1px;
}
.ev-record   { background: var(--sign);       color: var(--sign-tx); }
.ev-measured { background: var(--blue);       color: var(--blue-tx); }
.ev-modeled  { background: var(--silver-sub); color: var(--silver-dk); border: 1px solid var(--silver-hi); }
.ev-claimed  { background: transparent;       color: var(--silver);   border: 1px dashed var(--silver-hi); }

/* The record ribbon — a quiet band for provenance lines under figures and tables:
   which dataset, which cycle, which filing. */
.provenance {
  border-left: 3px solid var(--silver-hi); background: var(--card2);
  padding: 8px 12px; margin: 10px 0; border-radius: 0 6px 6px 0;
  font-family: var(--mono-font); font-size: 11.5px; color: var(--ink2);
}
