/* Forecast Points — highway signage design system, motorist-services cut
 *
 * Third site on the network's shared visual language, after weather.city and
 * Forecast Eagle: warm paper ground, Overpass (the open metric-compatible cut of
 * FHWA Highway Gothic — the actual Interstate signage face), and MUTCD colours
 * used the way the manual uses them rather than as decoration.
 *
 * Where the others differ
 * -----------------------
 * Eagle leads with guide-sign green (#04663d) and marks itself with the Interstate
 * route shield, because it is about the national network of models. Forecast Points
 * leads with **motorist-services blue** (#0a5ca8) — the colour of the sign that
 * tells you what is available at *this* exit, not where the road goes. That is
 * exactly what a point forecast is: everything on offer at one location. Green
 * stays in the system as the second voice (dew point, section rules, live badges),
 * so the two sites are plainly the same network without being the same page.
 *
 * Light only, on purpose
 * ----------------------
 * There is no dark theme and no `prefers-color-scheme` block anywhere in this
 * file. Highway signage is a reflective-on-dark system read at speed; a document
 * is a printed-page system read at rest, and this is a document. Every colour
 * below is chosen against warm paper, and the meteogram is drawn on white so it
 * prints and screenshots without a second palette existing to drift from the first.
 */

:root {
  /* ── shared network tokens (identical to weather.city / Forecast Eagle) ── */
  --paper: #e6e2da;
  --card: #ffffff;
  --ink: #161616;
  --ink2: #4a463e;
  --sign: #04663d;          /* guide-sign green — the accent here, not the lead */
  --sign-dk: #013d26;
  --sign-sub: #bdebcf;
  --blue: #0a5ca8;          /* motorist services — the lead */
  --blue-dk: #08488a;
  --navy: #103e7e;
  --blue-sub: #cfe2f6;
  --line: #c9c5bc;
  --line2: #e4e1d9;
  --mut: #8a867c;
  --shield-red: #c0331a;
  --amber: #f2ac14;

  /* ── chart palette — must match service/render/layout.py exactly ────────
     The browser and the server-side renderer draw the same meteogram, and a
     colour defined twice is a colour that will eventually be two colours. These
     are the authoritative values; layout.py's constants mirror them. */
  --t-temp: #c0331a;
  --t-feels: #e07b39;
  --t-dew: #04663d;
  --t-rh: #0a5ca8;
  --t-wind: #103e7e;
  --t-gust: #6b8cc7;
  --t-sky: #8a867c;
  --t-pop: #0a5ca8;
  --t-precip: #0a5ca8;
  --t-snow: #5b7fb5;
  --t-ice: #8b3a8b;
  --t-vis: #4a463e;
  --night: #dfe6f0;         /* the night band behind the traces */
  --grid: #eceae4;

  --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: 1620px; margin: 0 auto; padding: 0 18px; }
[hidden] { display: none !important; }

/* ── thin utility bar ─────────────────────────────────── */
.util {
  background: var(--ink); color: #cfccc4; border-bottom: 3px solid var(--blue);
  position: sticky; top: 0; z-index: 100; box-shadow: 0 1px 8px rgba(0, 0, 0, .22);
}
.util .bar {
  max-width: 1620px; 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: #e9e7e0; font-weight: 700; font-size: 11px; letter-spacing: .06em; }
.util a:hover { color: var(--blue-sub); text-decoration: none; }
.util a[aria-current="page"] { color: var(--blue-sub); }

/* ── the services sign ────────────────────────────────────
   The blue panel is the site's mark. Real motorist-services signs are a blue
   field with a white border inset and pictographs in a row; the double inset
   box-shadow reproduces that border without an extra element. */
.sign {
  background: var(--blue); border-radius: 10px; color: #fff;
  padding: 26px 24px 24px; position: relative;
  box-shadow: inset 0 0 0 4px var(--blue), inset 0 0 0 6px rgba(255, 255, 255, .9),
              0 10px 30px rgba(0, 0, 0, .16);
}
.sign a { color: #fff; }
.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(--blue-sub); }
.tag {
  margin: 8px 0 0; font-weight: 700; font-size: clamp(13px, 2.2vw, 16px);
  color: var(--blue-sub); letter-spacing: .01em;
}

/* The services plaque — Forecast Points' answer to Eagle's route shield. */
.plaque {
  border: 2.5px solid #fff; border-radius: 6px; padding: 6px 11px 7px;
  text-align: center; line-height: 1; flex: none; display: inline-block;
}
.plaque .a { font-size: 8px; font-weight: 700; letter-spacing: .16em; color: var(--blue-sub); }
.plaque .b { font-size: 19px; font-weight: 900; letter-spacing: .04em; display: block; }
.plaque .c { font-size: 8px; font-weight: 700; letter-spacing: .12em; color: var(--blue-sub); }

.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(--blue-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: #fff;
}
.mm:hover { background: #fff; color: var(--blue); 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(--blue) 0 18px, transparent 18px 34px);
}
.rule h2 {
  margin: 0; color: var(--blue); 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 and panels ─────────────────────────────────── */
.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: 0 6px 22px rgba(0, 0, 0, .08); transition: transform .14s, box-shadow .14s;
}
a.card:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(0, 0, 0, .13); text-decoration: none; }
.card .chead {
  background: var(--blue); color: #fff; padding: 9px 14px;
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .35);
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
}
.card .chead.green { background: var(--sign); }
.card .chead .k { font-size: 10px; font-weight: 700; letter-spacing: .1em; color: var(--blue-sub); }
.card .chead.green .k { color: var(--sign-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: 0 6px 22px rgba(0, 0, 0, .08);
}

/* ── controls ─────────────────────────────────────────── */
.btn {
  cursor: pointer; border: 1px solid var(--line); background: #fff; 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(--blue); color: var(--ink); }
.btn.on, .btn[aria-pressed="true"] { background: var(--blue); color: #fff; border-color: var(--blue-dk); }
.btn:disabled { opacity: .5; cursor: default; }
.btn-go { background: var(--blue); color: #fff; border-color: var(--blue-dk); font-weight: 900; letter-spacing: .06em; }
.btn-go:hover { background: #0b6bc4; color: #fff; }

select, input[type="text"], input[type="search"], input[type="number"] {
  background: #fff; 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, button: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); }

.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 9px; 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(--blue); color: #fff; border-color: var(--blue-dk); }

/* ══════════════════════════════════════════════════════════════════════════
   THE HEADS-UP DISPLAY
   ══════════════════════════════════════════════════════════════════════════
   Everything below belongs to the dashboard. The brief was a trading terminal:
   dense, monospaced, numbers aligned so the eye can run down a column, and no
   decoration that is not carrying information.

   The one rule that keeps it from becoming an actual Bloomberg screen is that it
   stays on paper. Terminals are dark because they are read in a dark room for
   eight hours; a forecast is read for ninety seconds in daylight and then
   printed, mailed or pasted into a briefing. */

/* Dashboard shell — sidebar and stage, collapsing to one column on narrow screens */
.hud {
  display: grid; grid-template-columns: 306px minmax(0, 1fr); gap: 14px;
  align-items: start; padding: 14px 0 40px;
}
@media (max-width: 980px) { .hud { grid-template-columns: minmax(0, 1fr); } }

.hud-side { display: flex; flex-direction: column; gap: 12px; position: sticky; top: 48px; }
@media (max-width: 980px) { .hud-side { position: static; } }

.hud-stage { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

/* Panel with a signage header bar */
.box {
  background: var(--card); border: 1px solid var(--line); border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .07); overflow: hidden;
}
.box > h2, .box > .bhead {
  margin: 0; background: var(--blue); color: #fff;
  padding: 7px 12px; font: 900 10.5px/1.3 var(--mono-font);
  letter-spacing: .14em; text-transform: uppercase;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .3);
}
.box > .bhead.green { background: var(--sign); }
.box > .bhead .n { font-weight: 700; color: var(--blue-sub); letter-spacing: .06em; }
.box .bbody { padding: 12px; }
.box .bbody.tight { padding: 8px; }

/* ── the identity strip: which point, and how sure are we ── */
.ident { padding: 12px 14px; }
.ident .place { font: 900 21px/1.15 var(--font); letter-spacing: -.01em; }
.ident .sub {
  margin-top: 4px; font: 700 10.5px/1.5 var(--mono-font); color: var(--mut);
  letter-spacing: .04em;
}
.ident .sub b { color: var(--ink2); font-weight: 700; }

/* ── stat tiles — the big readouts ────────────────────────
   Grid rather than flex so every tile is the same width and the numbers line up
   into columns down the block. A row of differently sized tiles reads as a list;
   a grid of identical ones reads as an instrument. */
.tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 1px; background: var(--line2);
}
.tile { background: var(--card); padding: 9px 10px 8px; min-width: 0; }
.tile .k {
  font: 700 8.5px/1 var(--mono-font); letter-spacing: .12em; color: var(--mut);
  text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tile .v {
  margin-top: 5px; font: 900 23px/1 var(--mono-font); letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.tile .v .u { font-size: 11px; font-weight: 700; color: var(--mut); margin-left: 2px; }
.tile .v.na { color: var(--line); font-size: 18px; }
.tile.accent .v { color: var(--blue); }
.tile.hot .v { color: var(--shield-red); }
.tile.cool .v { color: var(--navy); }

/* ── the hazard banner ────────────────────────────────────
   Colour comes from the NWS event palette at runtime, so the left rule is set
   inline. Everything else is fixed so a Tornado Warning and a Frost Advisory have
   identical typography and only the colour changes — which is the whole point of
   a standard palette. */
.hazards { display: flex; flex-direction: column; gap: 6px; }
.hazard {
  display: flex; gap: 10px; align-items: baseline; padding: 7px 10px;
  border-left: 5px solid var(--shield-red); background: #faf8f4;
  border-top: 1px solid var(--line2); border-right: 1px solid var(--line2);
  border-bottom: 1px solid var(--line2); border-radius: 0 4px 4px 0;
}
.hazard .ev { font: 900 12px var(--font); letter-spacing: -.01em; }
.hazard .wh { font: 700 10px var(--mono-font); color: var(--mut); letter-spacing: .03em; }
.hazard.none { border-left-color: var(--sign); color: var(--ink2); }
.hazard.none .ev { font-weight: 700; color: var(--sign); }

/* ── element picker ─────────────────────────────────────── */
.picker { display: flex; flex-direction: column; gap: 2px; max-height: 340px; overflow-y: auto; }
.pick {
  display: flex; align-items: center; gap: 8px; padding: 5px 7px; cursor: pointer;
  border-radius: 3px; border: 1px solid transparent; user-select: none;
}
.pick:hover { background: #f5f3ee; border-color: var(--line2); }
.pick input { margin: 0; accent-color: var(--blue); }
.pick .sw { width: 13px; height: 3px; border-radius: 2px; flex: none; }
.pick .nm { font: 700 11.5px var(--font); color: var(--ink2); flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pick .un { font: 700 9px var(--mono-font); color: var(--mut); }
.pick.off .nm { color: var(--mut); }

/* ── search ─────────────────────────────────────────────── */
.search { position: relative; }
.search input { width: 100%; font-size: 13px; padding: 8px 10px; }
.results {
  position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 3px);
  background: #fff; border: 1px solid var(--line); border-radius: 4px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .16); max-height: 300px; overflow-y: auto;
}
.results button {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 7px 10px; cursor: pointer; font: 700 12px var(--font); color: var(--ink);
  border-bottom: 1px solid var(--line2);
}
.results button:last-child { border-bottom: 0; }
.results button:hover, .results button.sel { background: var(--blue); color: #fff; }
.results button .st { font: 700 10px var(--mono-font); color: var(--mut); margin-left: 6px; }
.results button:hover .st, .results button.sel .st { color: var(--blue-sub); }

/* ── the model menu ─────────────────────────────────────── */
.menu-host { overflow-x: auto; }
.menu-host svg { display: block; width: 100%; min-width: 560px; height: auto; }
.menu-legend {
  margin: 6px 0 0; padding-top: 6px; border-top: 1px solid var(--line2);
  font: 700 9px/1.5 var(--mono-font); letter-spacing: .06em; color: var(--mut);
}

/* ── the chart stage ────────────────────────────────────── */
.chart { position: relative; background: #fff; }
/* The earned band's footnote. The dashed rule in front of it is the mark used on the chart,
   so the reader can match the line to the sentence without a legend of its own. */
.earned-note {
  margin: 0; padding: 7px 10px 8px 10px; border-top: 1px solid var(--line2);
  display: flex; align-items: baseline; gap: 8px; line-height: 1.45;
  font: 700 9.5px/1.5 var(--mono-font); letter-spacing: .05em; color: var(--mut);
}
.earned-note::before {
  content: ""; flex: none; width: 22px; height: 0;
  border-top: 1px dashed var(--mut); transform: translateY(-3px);
}
.chart svg { display: block; width: 100%; height: auto; }
.chart .crosshair {
  position: absolute; top: 0; bottom: 0; width: 1px; background: var(--ink);
  opacity: .5; pointer-events: none; display: none;
}
/* The readout follows the cursor and must never sit under it, so it flips side at
   the midpoint (set by JS). Pointer-events off or it steals its own hover. */
.chart .readout {
  position: absolute; pointer-events: none; display: none; z-index: 20;
  background: rgba(255, 255, 255, .97); border: 1px solid var(--line);
  border-left: 3px solid var(--blue); border-radius: 3px; padding: 7px 9px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .18); min-width: 132px;
}
.chart .readout .t {
  font: 900 10.5px var(--mono-font); letter-spacing: .04em; color: var(--ink);
  border-bottom: 1px solid var(--line2); padding-bottom: 4px; margin-bottom: 5px;
}
.chart .readout .r { display: flex; align-items: center; gap: 6px; margin-top: 3px; }
.chart .readout .r .sw { width: 9px; height: 3px; border-radius: 2px; flex: none; }
.chart .readout .r .k { font: 700 9.5px var(--mono-font); color: var(--mut);
  letter-spacing: .06em; flex: 1; }
.chart .readout .r .v { font: 900 11px var(--mono-font); font-variant-numeric: tabular-nums; }

/* ── the tabular forecast ───────────────────────────────── */
.tbl-wrap { overflow-x: auto; }
table.fp { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
table.fp th, table.fp td {
  padding: 4px 9px; text-align: right; white-space: nowrap;
  border-bottom: 1px solid var(--line2); font: 700 11.5px var(--mono-font);
}
table.fp th {
  position: sticky; top: 0; background: #f3f1ec; color: var(--ink2);
  font: 700 9px var(--mono-font); letter-spacing: .1em; text-transform: uppercase;
  border-bottom: 2px solid var(--line); z-index: 2;
}
table.fp td:first-child, table.fp th:first-child { text-align: left; }
table.fp tbody tr:hover { background: #f7f5f1; }
/* A rule at every local midnight, so the eye can find "tomorrow" without reading
   dates down the first column. */
table.fp tr.day td { border-top: 2px solid var(--line); }
table.fp tr.night td:first-child { color: var(--navy); }
table.fp td.num { color: var(--ink); }
table.fp td.na { color: var(--line); }

/* ── map ────────────────────────────────────────────────── */
.mapwrap { position: relative; height: 300px; background: #eceae4; }
.mapwrap .maplibregl-map { position: absolute; inset: 0; }
.maphint {
  position: absolute; left: 8px; bottom: 8px; z-index: 5; pointer-events: none;
  background: rgba(255, 255, 255, .92); border: 1px solid var(--line);
  border-radius: 3px; padding: 4px 8px; font: 700 9.5px var(--mono-font);
  color: var(--ink2); letter-spacing: .04em;
}

/* ── 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: #fff; }
.badge-new { background: var(--shield-red); color: #fff; }
.badge-soon { background: #efece5; color: var(--mut); border: 1px solid var(--line); }

.dim { color: var(--ink2); }
.faint { color: var(--mut); }
.note { font: 600 11.5px/1.55 var(--font); color: var(--ink2); }

/* Status line — the thing that says whether the data is fresh or the fetch failed */
.status {
  font: 700 10px var(--mono-font); letter-spacing: .05em; color: var(--mut);
  display: flex; align-items: center; gap: 7px; padding: 7px 12px;
  border-top: 1px solid var(--line2); background: #faf8f4;
}
.status .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--sign); flex: none; }
.status.warn .dot { background: var(--amber); }
.status.err { color: var(--shield-red); }
.status.err .dot { background: var(--shield-red); }
.status.busy .dot { background: var(--blue); animation: pulse 1.1s ease-in-out infinite; }
.quality {
  padding: 7px 12px; border-top: 1px solid #e2c879; background: #fff8dc;
  color: #664d08; font: 800 9.5px/1.45 var(--mono-font);
  letter-spacing: .04em; text-transform: uppercase;
}
@keyframes pulse { 0%, 100% { opacity: 1 } 50% { opacity: .25 } }

pre.code {
  background: #f7f5f1; border: 1px solid var(--line2); border-radius: 4px;
  padding: 11px 13px; overflow-x: auto; font: 700 11.5px/1.6 var(--mono-font);
  color: var(--ink2); margin: 0;
}
pre.code .c { color: var(--mut); font-weight: 600; }

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

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

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

/* The print stylesheet lives at the end of this file. */

/* The weather column is prose, not a number: left-aligned, not tabular, and allowed
   to be the widest thing in the table. */
table.fp td.wx {
  text-align: left; font-family: var(--font); font-weight: 700;
  font-size: 11.5px; color: var(--ink2); white-space: nowrap;
}


/* ═══════════════════════════════════════════════════════════════════════════
   THE DERIVED VIEWS
   Everything below reads `digest.js` rather than the raw series: the written
   summary, the day strip, the almanac. They are three presentations of one
   derivation, which is why none of them does any arithmetic of its own.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── the forecast in words ──────────────────────────────────
   Set as prose, not as a data readout. This is the one part of the page meant to
   be read straight through rather than scanned, so it gets the text face, a
   comfortable measure and real line height — a monospaced summary reads as debug
   output no matter how carefully it is worded. */
.summary {
  margin: 0; font: 600 14.5px/1.65 var(--font); color: var(--ink2);
  max-width: 78ch;
}
.summary .cl.alert { font-weight: 900; }
.summary .cl.now { font-weight: 800; color: var(--ink); }
.summary .cl.today, .summary .cl.tonight { color: var(--ink); font-weight: 700; }
.summary .cl.astro { color: var(--mut); font-size: 13px; }

/* ── the day strip ──────────────────────────────────────────
   One card per local day, in a scrolling row that becomes a grid when there is
   room. Each is a button because each does something: clicking zooms the chart to
   that day. Cards are equal-width so the highs line up into a readable row of
   numbers down the strip — the comparison a reader is actually making. */
.days {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(104px, 1fr);
  gap: 1px; background: var(--line2); overflow-x: auto;
}
@media (max-width: 720px) {
  .days { grid-auto-columns: minmax(92px, 44%); }
}
/* Scoped to the ribbon on purpose. `.day` was a bare class, and the hourly table marks the first
   row of each day with the same name — so a table row became a flex container and its cells
   became blocks, which is why the table opened with one row's numbers stacked vertically while
   every row below it was fine. */
.days .day {
  appearance: none; border: 0; cursor: pointer; text-align: center;
  background: var(--card); padding: 9px 6px 10px; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  font-family: var(--mono-font); position: relative;
  border-top: 3px solid transparent;
  transition: background .12s;
}
.days .day:hover { background: #f4f2ed; }
.days .day:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
.days .day.alerted { border-top-color: var(--alert, var(--shield-red)); }
/* A day only partly covered by the run is marked rather than hidden: the numbers
   in it are real, they just describe less than a whole day. */
.days .day.part { background: repeating-linear-gradient(135deg,
  var(--card) 0 7px, #f6f4f0 7px 14px); }
.day .dn { font: 900 11px/1 var(--mono-font); letter-spacing: .1em; color: var(--ink); }
.day .dd { font: 700 9px/1 var(--mono-font); letter-spacing: .08em; color: var(--mut); }
.day .di { display: block; margin: 3px 0 1px; line-height: 0; }
.day .dt { display: flex; align-items: baseline; gap: 6px; }
.day .dt b { font: 900 19px/1 var(--mono-font); color: var(--shield-red);
  font-variant-numeric: tabular-nums; }
.day .dt i { font: 800 13px/1 var(--mono-font); font-style: normal; color: var(--navy);
  font-variant-numeric: tabular-nums; }
.day .dt i.trace { color: var(--mut); }
.day .dw { display: flex; gap: 6px; align-items: baseline; min-height: 12px; }
.day .dw em { font: 800 10px/1 var(--mono-font); font-style: normal; color: var(--blue); }
.day .dw u { font: 800 10px/1 var(--mono-font); text-decoration: none; color: var(--navy); }

/* ── tile sparklines ────────────────────────────────────────
   A tile without one answers "what is it now" and nothing else, which is the
   question a reader has least often — they can feel the current temperature.
   "72 and falling fast" is the useful sentence, and it takes sixty pixels. */
.tile .sp { margin-top: 5px; display: flex; align-items: center; gap: 6px; }
.tile .sp svg { display: block; flex: none; opacity: .85; }
.tile .sp .d {
  font: 700 8.5px/1 var(--mono-font); color: var(--mut); letter-spacing: .04em;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}

/* ── sun, moon, almanac ─────────────────────────────────────
   A two-column key/value list rather than a table: six rows do not need a header,
   and the sidebar is narrow enough that a table would wrap its own captions. */
.astro { display: flex; flex-direction: column; }
.astro .ar {
  display: flex; justify-content: space-between; gap: 8px; padding: 3px 4px;
  border-bottom: 1px solid var(--line2);
}
.astro .ar .k { font: 700 10px var(--mono-font); letter-spacing: .06em; color: var(--mut); }
.astro .ar .v { font: 800 11px var(--mono-font); color: var(--ink);
  font-variant-numeric: tabular-nums; }
.astro .moon { display: flex; align-items: center; gap: 10px; padding: 9px 4px 3px; }
.astro .moon .mg { line-height: 0; flex: none; }
.astro .moon .mt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.astro .moon .mt b { font: 900 12px var(--font); letter-spacing: -.01em; }
.astro .moon .mt i {
  font: 700 9.5px var(--mono-font); font-style: normal; color: var(--mut);
  letter-spacing: .03em;
}
.alm { margin-top: 8px; }
table.fp.tiny th, table.fp.tiny td { padding: 3px 5px; font-size: 10px; }

.btn.wide { width: 100%; margin-top: 9px; }
.btn.tiny { padding: 2px 7px; font-size: 9.5px; }

/* ── the brush ──────────────────────────────────────────────
   Dragging across the chart with a mouse selects a window to zoom into. Drawn as
   an overlay rather than into the SVG so it costs no redraw — the chart is
   several hundred elements and rebuilding it on every pointer move to show a
   rectangle would make the gesture feel broken. */
.chart .brush {
  position: absolute; background: rgba(10, 92, 168, .13);
  border-left: 1.5px solid var(--blue); border-right: 1.5px solid var(--blue);
  pointer-events: none; z-index: 15;
}
/* A pinned crosshair is a different state from a hovered one and has to look it,
   or a reader who tapped once wonders why the readout has stopped following. */
.chart .crosshair.pinned { background: var(--blue); opacity: .85; width: 1.5px; }
.chart { touch-action: pan-y; }
.chart:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* ── forecast distribution research preview ───────────────
   Kept outside the live meteogram until the point API supplies the same contract
   for the requested location and run. Isolated range columns are intentional:
   joining this sparse fixture would visually invent all the hours between them. */
.uncertainty-host { padding: 0 !important; }
.uncertainty-box { scroll-margin-top: 48px; }
.uncertainty-host > .note { font-size: 12px; padding: 12px 14px; }
.uncertainty-box > .bhead { font-size: 12px; }
.uncertainty-disclosure > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center;
  justify-content: space-between; gap: 16px; padding: 13px 14px;
  border-bottom: 0 solid var(--line2); color: var(--ink);
}
.uncertainty-disclosure[open] > summary { border-bottom-width: 1px; }
.uncertainty-disclosure > summary::-webkit-details-marker { display: none; }
.uncertainty-disclosure > summary::before {
  content: '+'; display: inline-grid; place-items: center; width: 22px; height: 22px;
  border: 1px solid var(--blue); border-radius: 50%; color: var(--blue);
  font: 900 16px/1 var(--mono-font); flex: none;
}
.uncertainty-disclosure[open] > summary::before { content: '−'; }
.uncertainty-summary-title { font: 900 15px/1.2 var(--font); margin-right: auto; }
.uncertainty-summary-meta {
  font: 700 12px/1.3 var(--mono-font); color: var(--mut); letter-spacing: .04em;
  text-align: right;
}
.uncertainty-body { padding: 12px 14px 16px; }
.uncertainty-warning {
  margin: 0 0 12px; padding: 7px 10px; border: 1px solid #a16800;
  border-left-width: 5px; border-radius: 3px; background: #fff7df; color: #5f3d00;
  font: 900 12px/1.4 var(--mono-font); letter-spacing: .07em; text-transform: uppercase;
}
.uncertainty-intro {
  display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(245px, .8fr);
  gap: 18px; align-items: start;
}
.uncertainty-intro h3 {
  margin: 0 0 5px; font: 900 13px/1.25 var(--font); letter-spacing: -.01em;
}
.uncertainty-narrative > p {
  margin: 0 0 7px; max-width: 82ch; font-size: 12.5px; line-height: 1.55;
  font-weight: 650; color: var(--ink2);
}
.uncertainty-narrative > p.note { font-size: 12px; color: var(--mut); }
.uncertainty-provenance {
  padding: 10px 12px; border: 1px solid var(--line2); border-radius: 4px;
  background: #faf8f4;
}
.uncertainty-provenance dl {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 9px; margin: 0;
}
.uncertainty-provenance dt {
  color: var(--mut); font: 700 12px/1.4 var(--mono-font);
  letter-spacing: .07em; text-transform: uppercase;
}
.uncertainty-provenance dd {
  margin: 0; color: var(--ink2); font: 700 12px/1.4 var(--mono-font);
  overflow-wrap: anywhere;
}
.uncertainty-legend { display: flex; gap: 8px 15px; flex-wrap: wrap; margin-top: 10px; }
.uncertainty-legend .legend-item {
  display: inline-flex; align-items: center; gap: 6px;
  font: 700 12px/1 var(--mono-font); color: var(--ink2);
}
.uncertainty-legend i { display: inline-block; width: 22px; height: 12px; position: relative; }
.uncertainty-legend b { font-weight: 700; }
.uncertainty-legend .outer i::after,
.uncertainty-legend .inner i::after {
  content: ''; position: absolute; left: 10px; top: 0; height: 12px;
  border-left: 2px solid var(--navy);
}
.uncertainty-legend .inner i::after { border-left: 7px solid var(--blue); }
.uncertainty-legend .median i::after {
  content: ''; position: absolute; width: 8px; height: 8px; border-radius: 50%;
  background: var(--shield-red); border: 1px solid #fff; left: 7px; top: 2px;
}
.uncertainty-legend .probability i::after {
  content: ''; position: absolute; width: 13px; height: 9px; left: 5px; top: 2px;
  background: var(--sign); border: 1px solid var(--sign-dk);
}
.uncertainty-legend .gap i {
  border: 1px solid var(--line); background: repeating-linear-gradient(
    135deg, transparent 0 4px, var(--line2) 4px 6px);
}
.uncertainty-gap-note {
  margin: 12px 0 8px; padding: 7px 9px; background: #f3f1ec;
  border-left: 3px solid var(--mut); color: var(--ink2);
  font: 700 12px/1.5 var(--mono-font);
}
.uncertainty-chart-wrap { overflow-x: auto; padding-bottom: 3px; }
.uncertainty-chart-wrap:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.uncertainty-chart { display: block; min-width: 680px; width: 100%; height: auto; }
.uncertainty-chart text { font-family: var(--mono-font); }
.uncertainty-grid { stroke: var(--grid); stroke-width: 1; }
.uncertainty-threshold { stroke: var(--shield-red); stroke-width: 1.5; stroke-dasharray: 6 4; }
.uncertainty-threshold + .threshold-label, .threshold-label {
  fill: var(--shield-red); font-size: 12px; font-weight: 900;
}
.gap-hatch-line { stroke: var(--line2); stroke-width: 3; }
.uncertainty-gap { opacity: .34; }
.gap-label { fill: var(--mut); font-size: 12px; font-weight: 700; letter-spacing: .04em; }
.axis-label, .time-label { fill: var(--mut); font-size: 12px; font-weight: 700; }
.lead-label { fill: var(--ink2); font-size: 12px; font-weight: 900; }
.panel-label { fill: var(--mut); font-size: 12px; font-weight: 900; letter-spacing: .08em; }
.range-10-90 { stroke: var(--navy); stroke-width: 2.5; stroke-linecap: round; }
.range-25-75 { stroke: var(--blue); stroke-width: 10; stroke-linecap: round; }
.median-dot { fill: var(--shield-red); stroke: #fff; stroke-width: 1.5; }
.median-value, .probability-value {
  fill: var(--ink); font-size: 12px; font-weight: 900; paint-order: stroke;
  stroke: #fff; stroke-width: 3px; stroke-linejoin: round;
}
.probability-bar { fill: var(--sign); stroke: var(--sign-dk); stroke-width: 1; }
.missing-mark { fill: var(--shield-red); font-size: 18px; font-weight: 900; }
.uncertainty-table-wrap { max-height: 280px; overflow: auto; margin-top: 4px; }
.uncertainty-table caption {
  caption-side: top; text-align: left; padding: 5px 9px; color: var(--mut);
  font: 700 12px/1.4 var(--mono-font);
}
table.fp.uncertainty-table th, table.fp.uncertainty-table td { font-size: 12px; }
.uncertainty-table tr.missing th { border-left: 3px solid var(--shield-red); }

@media (max-width: 720px) {
  .uncertainty-disclosure > summary { align-items: flex-start; flex-wrap: wrap; gap: 8px; }
  .uncertainty-summary-meta { width: calc(100% - 38px); margin-left: 38px; text-align: left; }
  .uncertainty-intro { grid-template-columns: 1fr; }
  .uncertainty-body { padding-left: 10px; padding-right: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .uncertainty-disclosure *, .uncertainty-disclosure *::before,
  .uncertainty-disclosure *::after { scroll-behavior: auto !important; transition: none !important; }
}

@media (forced-colors: active) {
  .uncertainty-warning, .uncertainty-provenance, .uncertainty-gap-note {
    forced-color-adjust: auto; background: Canvas; color: CanvasText; border-color: CanvasText;
  }
  .uncertainty-grid, .gap-hatch-line { stroke: GrayText; }
  .uncertainty-threshold, .range-10-90 { stroke: CanvasText; }
  .range-25-75 { stroke: Highlight; }
  .median-dot { fill: CanvasText; stroke: Canvas; }
  .probability-bar { fill: Highlight; stroke: CanvasText; }
  .uncertainty-chart text { fill: CanvasText; stroke: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   PRINT — the briefing
   A point forecast is printed and pasted into briefings far more often than a
   model map is, so this is a real layout rather than a hidden-chrome fallback.
   The order is the reading order of a briefing: who and where, the hazard, the
   sentence, the week, then the chart, then the numbers.
   ═══════════════════════════════════════════════════════════════════════════ */
@media print {
  .util, .hud-side, .site-footer, .no-print, .status, .quality { display: none !important; }
  body { background: #fff; color: #000; }
  .wrap-wide { max-width: none; padding: 0; }
  .hud { grid-template-columns: 1fr; padding: 0; gap: 0; }
  .box {
    box-shadow: none; border: 0; border-top: 1.5px solid #000;
    break-inside: avoid; margin-bottom: 9px;
  }
  .box > .bhead {
    background: none; color: #000; padding: 3px 0;
    box-shadow: none; font-size: 9px; letter-spacing: .16em;
  }
  .box > .bhead .n { color: #666; }
  .box .bbody { padding: 4px 0; }
  .ident { padding: 0 0 4px; }
  /* The identity block leads, so it gets no rule above it. */
  .hud-stage > .box:first-child { border-top: 0; }
  .tiles { gap: 0; background: none; }
  .tile { border: 1px solid #ccc; margin: -0.5px; }
  .tile .sp { display: none; }          /* ink, for a line the chart already shows */
  .days { background: none; gap: 0; }
  .day { border: 1px solid #ccc; margin: -0.5px; }
  .summary { max-width: none; font-size: 11.5pt; }
  .chart { break-inside: avoid; }
  /* Everything past the first two days of hours is padding in a printed packet,
     and it is the part that turns one page into four. */
  #table { max-height: none !important; overflow: visible !important; }
  table.fp tbody tr:nth-child(n+49) { display: none; }
  a[href]::after { content: ""; }       /* no printed URLs beside every link */
}

/* ═══════════════════════════════════════════════════════════════════════════
   COMPARE
   Four points, two views: the overlay answers "when", the matrix answers
   "which". Colours come from `compare.js` — a four-slot categorical set checked
   for colourblind separation rather than chosen by eye — and are set inline from
   the point's slot, so nothing here names a hue.
   ═══════════════════════════════════════════════════════════════════════════ */

.chosen { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.chip {
  display: flex; align-items: center; gap: 8px; padding: 5px 6px;
  background: #faf8f4; border: 1px solid var(--line2); border-radius: 4px;
}
.chip .sw { width: 12px; height: 12px; border-radius: 2px; flex: none; }
.chip .nm { font: 800 11.5px var(--mono-font); flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip .x {
  appearance: none; border: 0; background: none; cursor: pointer; flex: none;
  font: 900 15px/1 var(--font); color: var(--mut); padding: 0 3px;
}
.chip .x:hover { color: var(--shield-red); }

.chart.cmp { padding: 4px 0 0; }

/* ── the day matrix ─────────────────────────────────────────
   The point column is a row header rather than a cell: it is the axis of the
   table, and screen readers should announce it as one. */
table.mtx { table-layout: fixed; }
table.mtx th.pt {
  text-align: left; width: 190px; vertical-align: top; padding-top: 8px;
  border-right: 1px solid var(--line2); background: #faf8f4;
}
table.mtx th.pt .sw {
  display: inline-block; width: 10px; height: 10px; border-radius: 2px;
  margin-right: 6px; vertical-align: baseline;
}
table.mtx th.pt .nm { font: 800 11.5px var(--mono-font); }
table.mtx th.pt .off {
  display: block; font: 600 9px var(--mono-font); color: var(--mut);
  letter-spacing: .04em; margin: 2px 0 0 16px;
}
table.mtx thead th { text-align: center; font-size: 10px; letter-spacing: .08em;
  color: var(--mut); }
table.mtx td.cell {
  text-align: center; padding: 6px 4px; vertical-align: middle;
  border-left: 1px solid var(--line2); border-top: 3px solid transparent;
}
table.mtx td.cell.alerted { border-top-color: var(--alert, var(--shield-red)); }
table.mtx td.cell .ci { display: block; line-height: 0; margin-bottom: 2px; }
table.mtx td.cell .ci svg { display: inline-block; }
table.mtx td.cell .cv { display: block; }
table.mtx td.cell .cv b { font: 900 15px var(--mono-font); color: var(--ink2); }
table.mtx td.cell .cv i {
  font: 800 11px var(--mono-font); font-style: normal; color: var(--mut);
  margin-left: 5px;
}
/* The warmest and coolest high in a column, marked. The number a reader wants out
   of a comparison table is nearly always an extreme, and finding it by scanning
   four three-digit numbers is exactly the work the table should be doing. */
table.mtx td.cell .cv b.warmest { color: var(--shield-red); }
table.mtx td.cell .cv b.coolest { color: var(--navy); }
table.mtx td.cell .cp {
  display: block; font: 800 9.5px var(--mono-font); color: var(--blue);
  min-height: 11px; letter-spacing: .03em;
}
table.fp th.pt { text-align: left; }
table.fp th.pt .sw {
  display: inline-block; width: 10px; height: 10px; border-radius: 2px;
  margin-right: 6px;
}
table.fp th.pt .nm { font: 800 11.5px var(--mono-font); }

@media (max-width: 720px) {
  table.mtx th.pt { width: 118px; }
  table.mtx td.cell .cv b { font-size: 13px; }
}

/* Run-over-run history: a sparkline of the day's high across recent runs. Colour is the
   category, not the value — the eye needs "steady / drifting / flip-flopping", not a number. */
.days .day .dh { display: block; line-height: 0; margin-top: 3px; }
.days .day .hs { display: block; }
.days .day .hs-steady { color: var(--mut); }
.days .day .hs-warming { color: var(--shield-red); }
.days .day .hs-cooling { color: var(--navy); }
.days .day .hs-flip { color: #8a3fa0; }
.cl.history { color: var(--mut); }

/* The model menu, in miniature: how much the seven sources agree about this day. Muted while
   they agree, and only a fork earns the alarm colour — a mark that shouts on every card
   teaches the reader to stop looking at it. */
.days .day .dm { display: block; line-height: 0; margin-top: 5px; }
.days .day .ms { display: block; color: var(--mut); }
.days .day .ms-spread { color: var(--ink); }
.days .day .ms-outlier { color: var(--ink); }
.days .day .ms-fork { color: var(--shield-red); }

/* The revision fan: one hour as every recent run saw it. */
.revision-host { padding: 8px 10px 4px; }
.revision-host svg.fan { display: block; width: 100%; height: auto; font-family: var(--mono-font); }
