/* ============================================================
   Weather-API Demo Gallery — shared design tokens & components
   Dark-first, cinematic. Palette validated (dataviz six checks,
   dark surface #10161c): accents #5578E6/#17A07A/#BD8422,
   status #27A07C/#B58C15/#C93A60.
   ============================================================ */
:root {
  --bg:#0b1016; --surface:#10161c; --surface-2:#161e26; --surface-3:#1d2732;
  --ink:#e4ecf3; --ink-2:#b3c2cf; --ink-3:#7f93a4; --rule:#2b3844;
  --acc-sky:#5578E6;   /* Skycard — consumer forecast */
  --acc-flood:#17A07A; /* Flood Watch — globe */
  --acc-mould:#BD8422; /* Mould Risk Monitor */
  --st-low:#27A07C; --st-elevated:#B58C15; --st-critical:#C93A60;
  /* A fourth severity step (between --st-elevated and --st-critical) for
     4-band scales like the Site Passport's dampness prior (low/moderate/
     elevated/high) — a blend, not a fifth independent hue, so the low→high
     read stays a single green→amber→red progression. */
  --st-elevated-high: color-mix(in srgb, var(--st-critical) 55%, var(--st-elevated));
  /* ---- sky palette (D3 Daylight & Dew Dial's day/night wheel) ----
     Five stops the dial ramps between with color-mix(), so the whole disc
     is themeable from here and a Swift port only has to translate five
     colours. --sky-ink-day is the ink for labels that land ON the bright
     day sector; --star/--horizon/--dew are the night-half marks. */
  --sky-dawn:#E9A26D; --sky-noon:#F0C25B; --sky-dusk:#D1703C;
  --sky-night:#16233C; --sky-midnight:#080E1A;
  --sky-ink-day:#4A3010; --star:#DCE8F8; --horizon:#F5E6CA; --dew:#5FB2E8;
  /* WHO UV-Index band colours (same thresholds as logic/uv-advice.js). */
  --uv-low:#3FBF8F; --uv-moderate:#F2D03A; --uv-high:#F08A2E;
  --uv-very_high:#E2453F; --uv-extreme:#A972E8;
  --sans:"Avenir Next","Helvetica Neue",Helvetica,Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  --maxw:1140px;
}
* { box-sizing:border-box; }
html { scroll-behavior:smooth; }
body { margin:0; background:var(--bg); color:var(--ink);
  font:15px/1.6 var(--sans); -webkit-font-smoothing:antialiased; }
a { color:var(--ink-2); }
a:hover { color:var(--ink); }
code { font-family:var(--mono); font-size:.92em; background:var(--surface-2);
  border:1px solid var(--rule); border-radius:4px; padding:1px 6px; }

/* ---- top bar (every page) ---- */
/* Opaque enough that no scrolled content, however bright, shows through
   the blur (2026-09-06 fix, matching demo/lunar/ and demo/skycard/'s own
   inlined copies of this bar) — the bar's z-index already paints it above
   the page, but at a lower alpha the backdrop-filter blur legitimately
   shows through whatever sits directly behind it once scrolled there. */
.topbar { display:flex; align-items:center; gap:14px; padding:14px 22px;
  border-bottom:1px solid var(--rule); background:rgba(9,13,19,.97);
  backdrop-filter:blur(8px); position:sticky; top:0; z-index:30; }
.topbar .brand { font-weight:700; letter-spacing:-.01em; color:var(--ink);
  text-decoration:none; white-space:nowrap; display:flex; align-items:center; }
.topbar .brand em { font-style:normal; color:var(--ink-3); font-weight:500; }
/* The Mould Detect lockup (white long variant with the colour spore) —
   the same mark moulddetect.ai wears in its dark theme, applied here at
   the client's direction 2026-08-28. The gallery is dark-only, so only
   the white variant ships. width/height attributes carry the intrinsic
   size; this rule sets the rendered size. */
.topbar .brand img { height:22px; width:auto; display:block; }
.topbar .crumb { font:600 11px var(--mono); letter-spacing:.12em;
  text-transform:uppercase; padding:3px 10px; border-radius:99px;
  border:1px solid var(--rule); color:var(--ink-3); white-space:nowrap; }
.topbar .spacer { flex:1; }
.topbar a.gallery { font-size:13.5px; text-decoration:none; white-space:nowrap; flex:none; }

/* ---- badges / chips ---- */
.badge { display:inline-flex; align-items:center; gap:6px; font:600 10.5px var(--mono);
  letter-spacing:.09em; text-transform:uppercase; border-radius:99px;
  padding:3px 11px; border:1px solid var(--rule); color:var(--ink-3);
  white-space:nowrap; flex:none; }
.badge.sample { color:var(--st-elevated); border-color:var(--st-elevated); }
.badge.live { color:var(--st-low); border-color:var(--st-low); }
.chip { font:600 12px var(--sans); color:var(--ink-2); background:var(--surface-2);
  border:1px solid var(--rule); border-radius:99px; padding:7px 14px; cursor:pointer;
  min-height:34px; }
.chip[aria-pressed="true"] { color:var(--ink); border-color:var(--ink-3);
  background:var(--surface-3); }
.chip:focus-visible { outline:2px solid var(--acc-sky); outline-offset:2px; }

/* ---- status (never color alone: pair with .dot + text) ---- */
.dot { display:inline-block; width:9px; height:9px; border-radius:50%;
  margin-right:7px; vertical-align:0; }
.dot.low { background:var(--st-low); } .dot.elevated { background:var(--st-elevated); }
.dot.critical { background:var(--st-critical); }

/* ---- docs strip (below every visualization) ---- */
.docs { max-width:var(--maxw); margin:0 auto; padding:38px 22px 70px; }
.docs h2 { font-size:19px; margin:0 0 4px; }
.docs .sub { color:var(--ink-3); font-size:13.5px; margin:0 0 18px; }
.docs h3 { font:600 11px var(--mono); letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-3); margin:22px 0 6px; }
.docs pre { background:#0a0f14; color:#d7e3ee; border:1px solid var(--rule);
  border-radius:8px; padding:14px 16px; overflow-x:auto; font:12.5px/1.55 var(--mono);
  margin:8px 0; }
.docs .tbl { overflow-x:auto; border:1px solid var(--rule); border-radius:8px; margin:8px 0; }
.docs table { border-collapse:collapse; width:100%; font-size:13px; }
.docs th { text-align:left; font:600 10.5px var(--mono); letter-spacing:.07em;
  text-transform:uppercase; color:var(--ink-3); background:var(--surface-2);
  padding:8px 12px; border-bottom:1px solid var(--rule); }
.docs td { padding:8px 12px; border-bottom:1px solid var(--rule); color:var(--ink-2); }
.docs tr:last-child td { border-bottom:none; }
.tok-k{color:#7fd1c0}.tok-s{color:#e6b877}.tok-n{color:#e88}.tok-c{color:#6b7f8f;font-style:italic}

/* ---- footer ---- */
.foot { border-top:1px solid var(--rule); padding:20px 22px 36px;
  font:12px var(--mono); color:var(--ink-3); text-align:center; }
.foot a { color:var(--ink-3); }

/* ---- controls row (filters above/below charts) ---- */
.controls { display:flex; flex-wrap:wrap; align-items:center; gap:10px; }
input[type="range"] { accent-color:var(--acc-flood); height:32px; }

@media (max-width:700px) {
  .topbar { padding:12px 14px; gap:10px; }
  .topbar .crumb { display:none; }
  .docs { padding:28px 14px 54px; }
}

/* Below ~420px (design review defect: the "MOCK DATA" badge wrapped onto
   two lines at 390px), the crumb is already hidden — shrink the logo and
   badge further instead, so the now-`nowrap` badge (above) has room to
   stay on one line without pushing "← Gallery" off-screen. */
@media (max-width:420px) {
  .topbar { gap:7px; }
  .topbar .brand img { height:18px; }
  .badge { font-size:9px; letter-spacing:.05em; padding:3px 8px; }
}

/* ============================================================
   Shared chart/panel components (demo/mould/components/) reused
   across D2/D3/D6 and future demos — ADR-0004. Kept here (not in
   any one demo page) precisely because they're shared: BandScale,
   SourcesRow, CaveatCard, PrintSheet, HourGridHeatmap, RingDial,
   MoonPill, SlotPlanner. Page-specific layout (hero sentences,
   per-day cards, tab bars) stays in each demo's own <style> block.
   ============================================================ */

/* ---- BandScale ---- */
.bs-empty { color:var(--ink-3); font-size:13px; }
.bs-scale { display:flex; flex-direction:column; gap:10px; }
.bs-ladder { position:relative; display:flex; flex-direction:column-reverse; gap:3px; padding-left:6px; }
.bs-row { display:flex; align-items:center; gap:10px; padding:8px 10px; border-radius:8px;
  background:var(--surface-2); border:1px solid transparent; }
.bs-row.bs-current { border-color:var(--ink-3); background:var(--surface-3); }
.bs-swatch { width:12px; height:12px; border-radius:3px; flex:none; }
.bs-range { font:600 11px var(--mono); color:var(--ink-3); min-width:38px; }
.bs-label { font-size:13px; color:var(--ink-2); flex:1; }
.bs-row.bs-current .bs-label { color:var(--ink); font-weight:600; }
.bs-you { font:700 10px var(--mono); letter-spacing:.06em; text-transform:uppercase;
  color:var(--acc-mould); border:1px solid var(--acc-mould); border-radius:99px; padding:2px 8px; }
.bs-marker { position:absolute; left:-6px; transform:translateY(50%); pointer-events:none; }
.bs-marker-value { display:none; }
.bs-summary { color:var(--ink-3); font-size:12px; margin:0; }

/* ---- SourcesRow ---- */
.src-empty { color:var(--ink-3); font-size:12.5px; }
.src-row { display:flex; flex-wrap:wrap; align-items:center; gap:10px 12px; font-size:12px;
  color:var(--ink-3); padding:10px 0 0; border-top:1px solid var(--rule); margin-top:14px; }
.src-lbl { font:700 10.5px var(--mono); letter-spacing:.1em; text-transform:uppercase; color:var(--ink-3); }
.src-chips { display:flex; flex-wrap:wrap; gap:6px; }
.src-chip { font:600 11px var(--sans); color:var(--ink-2); background:var(--surface-2);
  border:1px solid var(--rule); border-radius:99px; padding:3px 10px; }
.src-asof, .src-run { color:var(--ink-3); }

/* ---- CaveatCard ---- */
.caveat-empty { color:var(--ink-3); font-size:13px; }
.caveat-card { background:var(--surface-2); border:1px solid var(--rule); border-radius:12px;
  padding:16px 18px 18px; }
.caveat-heading { font-size:14px; margin:0 0 6px; color:var(--ink); }
.caveat-summary { font-size:12.5px; color:var(--ink-2); margin:0 0 12px; line-height:1.5; }
.caveat-cols { display:grid; grid-template-columns:1fr 1fr; gap:16px; }
.caveat-col-h { font:700 10.5px var(--mono); letter-spacing:.08em; text-transform:uppercase;
  margin:0 0 6px; }
.caveat-col-h--yes { color:var(--st-low); }
.caveat-col-h--no { color:var(--st-critical); }
.caveat-list { margin:0; padding-left:18px; font-size:12.5px; color:var(--ink-2); line-height:1.55; }
.caveat-list li { margin:3px 0; }
.caveat-how { margin-top:12px; font-size:12.5px; }
.caveat-how summary { cursor:pointer; color:var(--ink-2); font-weight:600; }
.caveat-how-body { margin-top:8px; color:var(--ink-2); line-height:1.55; }
.caveat-how-body code { font-size:.92em; }
@media (max-width:560px) { .caveat-cols { grid-template-columns:1fr; } }

/* ---- PrintSheet (screen preview; @media print rules live per-page) ---- */
.print-sheet { background:#fff; color:#111; border-radius:10px; padding:0; }
.ps-head { padding:6px 0 14px; border-bottom:2px solid #111; margin-bottom:14px; }
.ps-title { font-size:20px; margin:0 0 4px; color:#111; }
.ps-subtitle { font-size:13px; color:#444; margin:0 0 8px; }
.ps-meta { font:600 11px var(--mono); color:#555; display:flex; gap:8px; flex-wrap:wrap; }
.ps-meta-sep { color:#999; }
.ps-body-empty { color:#777; font-size:13px; padding:20px 0; }
.ps-sources, .ps-caveat { margin-top:16px; }
.print-sheet .src-row, .print-sheet .caveat-card { background:#f4f4f4; border-color:#ddd; color:#333; }
.print-sheet .caveat-list, .print-sheet .caveat-summary, .print-sheet .src-lbl,
.print-sheet .caveat-heading, .print-sheet .ps-title { color:#111; }
.print-sheet .caveat-list { color:#333; }

/* ---- HourGridHeatmap ---- */
.hgh-empty { color:var(--ink-3); font-size:13px; }
.hgh-wrap { display:flex; flex-direction:column; gap:10px; --hgh-row-h:16px; --hgh-header-h:22px; }
.hgh-legend { display:flex; flex-wrap:wrap; align-items:center; gap:8px; font-size:12px; color:var(--ink-2); }
.hgh-legend-item { display:inline-flex; align-items:center; gap:5px; margin-left:10px; }
.hgh-legend-swatch { display:inline-block; width:14px; height:14px; border-radius:3px; vertical-align:-3px; }
.hgh-legend-low { background:color-mix(in srgb, var(--acc-mould) 10%, var(--surface-2)); }
.hgh-legend-high { background:var(--acc-mould); }
.hgh-legend-ramp { display:inline-block; width:48px; height:8px; border-radius:4px;
  background:linear-gradient(90deg, color-mix(in srgb, var(--acc-mould) 10%, var(--surface-2)), var(--acc-mould)); }
.hgh-legend-night { background:repeating-linear-gradient(135deg,
  color-mix(in srgb, var(--ink) 22%, var(--surface-3)) 0 4px, var(--surface-3) 4px 8px); border:1px solid var(--rule); }
.hgh-legend-hatch { background:repeating-linear-gradient(45deg,
  var(--st-critical) 0 3px, color-mix(in srgb, var(--st-critical) 25%, var(--surface-2)) 3px 8px); }
.hgh-legend-best { border-radius:3px; border:2px solid var(--ink); background:transparent; }
/* ---- hour axis (stays put; only .hgh-scroll below scrolls) ---- */
.hgh-body { display:flex; align-items:flex-start; gap:6px; }
.hgh-axis { flex:0 0 auto; display:flex; flex-direction:column; }
.hgh-axis-spacer { height:var(--hgh-header-h); }
.hgh-axis-rows { position:relative; display:grid; grid-template-columns:15px 36px; column-gap:4px; }
.hgh-axis-night-band { grid-column:1; border-radius:3px;
  background:repeating-linear-gradient(135deg, color-mix(in srgb, var(--ink) 22%, var(--surface-3)) 0 4px, var(--surface-3) 4px 8px);
  display:flex; align-items:center; justify-content:center; }
.hgh-axis-night-label { writing-mode:vertical-rl; transform:rotate(180deg); font:700 8.5px var(--mono);
  letter-spacing:.06em; color:var(--ink-3); text-transform:uppercase; }
.hgh-axis-hour { grid-column:2; display:flex; align-items:center; font:10px var(--mono); color:var(--ink-3);
  white-space:nowrap; }
.hgh-axis-hour-emph { color:var(--ink); font-weight:700; }
.hgh-scroll { overflow-x:auto; padding-bottom:4px; flex:1 1 auto; min-width:0; }
.hgh-grid { display:flex; gap:3px; width:100%; min-width:100%; }
.hgh-day { display:flex; flex-direction:column; gap:4px; flex:1 1 0; min-width:34px; }
/* display:block (not flex) — text-overflow:ellipsis is unreliable on a flex
 * container's own text content; a block box with a fixed line-height is the
 * standard reliable pattern for single-line, centred, truncating text. */
.hgh-day-label { height:var(--hgh-header-h); line-height:var(--hgh-header-h);
  font:700 11.5px var(--sans); color:var(--ink); text-align:center; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; padding:0 2px; }
.hgh-day-cells { display:flex; flex-direction:column; }
.hgh-cell { position:relative; height:var(--hgh-row-h); border-bottom:1px solid var(--surface); cursor:default; }
.hgh-cell.hgh-night { background:repeating-linear-gradient(135deg,
  color-mix(in srgb, var(--ink) 18%, var(--surface-3)) 0 5px, var(--surface-3) 5px 10px); }
.hgh-cell.hgh-best { outline:2px solid var(--ink); outline-offset:-2px; z-index:1; }
.hgh-cell.hgh-hatch { background:repeating-linear-gradient(45deg,
  var(--st-critical) 0 3px, color-mix(in srgb, var(--st-critical) 25%, var(--surface-2)) 3px 8px); }
.hgh-cell:focus-visible { outline:2px solid var(--acc-sky); outline-offset:1px; z-index:2; }
.hgh-hatch-mark { position:absolute; top:0; right:2px; font-size:8px; line-height:1; color:#fff;
  text-shadow:0 0 2px rgba(0,0,0,.6); }
.hgh-summary { color:var(--ink-3); font-size:12px; margin:0; }

/* ---- RingDial ----
 * The 24-hour day/night wheel: a full disc, noon at the top. Everything is
 * painted from the --sky-* / --uv-* tokens above so the SwiftUI port needs
 * only that palette. The SVG has no max-width of its own; .dial-layout in
 * demo/dial/index.html sizes the column that holds it, and the viewBox is
 * 1.14x wider than tall to make room for the sunrise/sunset rim labels. */
.rd-empty { color:var(--ink-3); font-size:13px; }
.rd-wrap { display:flex; flex-direction:column; align-items:center; gap:10px; width:100%; }
.rd-svg { width:100%; height:auto; }
/* Wedge fills are inline color-mix() values (the conic-gradient stand-in);
   only the seam behaviour is styled here. */
.rd-wedge { stroke:none; }
.rd-disc-night { fill:var(--sky-night); }
.rd-disc-day { fill:var(--sky-noon); }
.rd-rim { fill:none; stroke:var(--rule); stroke-width:1.25; }
.rd-star { fill:var(--star); }
.rd-horizon { stroke:var(--horizon); stroke-width:1.5; opacity:.95; stroke-linecap:round; }
.rd-horizon-tick { stroke:var(--horizon); stroke-width:1.6; }
.rd-horizon-cap { fill:var(--ink-3); font:700 8.5px var(--mono); letter-spacing:.1em; text-transform:uppercase; }
.rd-horizon-time { fill:var(--ink); font:700 11px var(--mono); }
.rd-dew-band { fill:var(--dew); opacity:.3; }
.rd-dew-edge { fill:none; stroke:var(--dew); stroke-width:1.6; stroke-linejoin:round; opacity:.85; }
.rd-ray-track { stroke:var(--horizon); stroke-width:5.5; stroke-linecap:round; opacity:.32; }
.rd-ray-casing { stroke:var(--sky-ink-day); stroke-width:6; stroke-linecap:round; opacity:.42; }
.rd-ray { stroke-width:3.4; stroke-linecap:round; }
.rd-ray-low { stroke:var(--uv-low); } .rd-ray-moderate { stroke:var(--uv-moderate); }
.rd-ray-high { stroke:var(--uv-high); } .rd-ray-very_high { stroke:var(--uv-very_high); }
.rd-ray-extreme { stroke:var(--uv-extreme); }
.rd-uv-peak { fill:var(--sky-ink-day); font:700 10px var(--mono); letter-spacing:.02em; }
.rd-cond-window { fill:var(--st-critical); opacity:.62; }
.rd-cond-drop path { fill:var(--st-critical); stroke:var(--bg); stroke-width:.8; }
.rd-tick { stroke:var(--ink); stroke-width:1; opacity:.4; }
.rd-tick-major { stroke-width:1.6; opacity:.68; }
.rd-tick-label { fill:var(--ink-2); font:700 10px var(--mono); letter-spacing:.04em; }
.rd-word { fill:var(--ink-2); font:700 9.5px var(--mono); letter-spacing:.16em; text-transform:uppercase; }
.rd-word-day { fill:var(--sky-noon); }
.rd-word-twilight { fill:var(--sky-dawn); }
.rd-word-night { fill:var(--ink-3); }
.rd-hub { fill:var(--surface); stroke:var(--rule); stroke-width:1.25; }
.rd-now-kicker { fill:var(--ink-3); font:700 8.5px var(--mono); letter-spacing:.22em; text-transform:uppercase; }
.rd-now-time { fill:var(--ink); font:700 27px var(--mono); letter-spacing:-.01em; }
.rd-hub-daylight { fill:var(--ink-2); font:600 11px var(--sans); }
.rd-hub-state { font:700 10px var(--mono); letter-spacing:.06em; text-transform:uppercase; }
.rd-hub-state-neutral { fill:var(--ink-3); }
.rd-hub-state-sun { fill:var(--sky-noon); }
.rd-hub-state-risk { fill:var(--st-critical); }
.rd-hub-state-dry { fill:var(--st-low); }
.rd-now-line { stroke:var(--ink); stroke-width:1.8; }
.rd-now-dot { stroke:var(--bg); stroke-width:1.4; }
.rd-now-sun { fill:var(--sky-noon); }
.rd-now-night { fill:var(--surface); stroke:var(--ink); stroke-width:1.8; }
.rd-legend { display:flex; flex-wrap:wrap; justify-content:center; gap:6px 14px; margin:0;
  font:11.5px var(--sans); color:var(--ink-2); }
.rd-legend-item { display:inline-flex; align-items:center; gap:6px; white-space:nowrap; }
.rd-legend-swatch { display:inline-block; width:14px; height:6px; border-radius:3px; }
.rd-legend-swatch-uv { background:linear-gradient(90deg, var(--uv-low), var(--uv-high)); }
.rd-legend-swatch-dew { background:var(--dew); opacity:.65; }
.rd-legend-glyph { width:9px; height:12px; display:block; }
.rd-legend-glyph path { fill:var(--st-critical); }
.rd-legend-cond { color:var(--st-critical); font-weight:600; }
.rd-summary { color:var(--ink-3); font-size:12px; margin:0; text-align:center; max-width:66ch; }
/* On a phone the wheel is only ~330 px wide, so the SVG's user-unit type
   scales down with it and the rim words stop being readable. Nudging the
   type up ~25 % inside the same viewBox restores legibility; the values are
   capped so "sunrise" still clears the left edge of the canvas and no two
   rim words touch (see periodLabels' 27.7 deg separation guarantee). */
@media (max-width:700px) {
  .rd-word { font-size:12px; letter-spacing:.09em; }
  .rd-tick-label { font-size:12.5px; }
  .rd-horizon-cap { font-size:10.5px; letter-spacing:.06em; }
  .rd-horizon-time { font-size:13.5px; }
  .rd-now-kicker { font-size:11px; letter-spacing:.18em; }
  .rd-now-time { font-size:33px; }
  .rd-hub-daylight { font-size:14px; }
  .rd-hub-state { font-size:12.5px; }
  .rd-uv-peak { font-size:12.5px; }
  .rd-legend { font-size:12px; }
}

/* ---- MoonPill ---- */
.moonpill { display:inline-flex; align-items:center; gap:10px; }
.moonpill-compact { display:inline-flex; }
.moonpill-glyph { display:block; flex:none; }
.moonpill-text { display:flex; flex-direction:column; }
.moonpill-phase { font:600 12.5px var(--sans); color:var(--ink); }
.moonpill-illum { font:11px var(--mono); color:var(--ink-3); }

/* ---- MoonDisc + LunarWheel (the Lunar Card's pair) ----
 * MoonDisc is the ACCURATE glyph (MoonPill above is the schematic one);
 * LunarWheel is the whole synodic month as a ring of MoonDiscs. Both are
 * shared components, so their CSS lives here rather than in any one demo —
 * except demo/lunar/, which claims :root itself (like skycard/) and so
 * restates this block at the bottom of its own styles.css. Every component
 * emits var(--token, fallback), so the discs still draw if a page forgets
 * these; the tokens are what make the pair themeable from one place. */
:root {
  --moon-lit:#dce6f5; --moon-lit-hi:#ffffff; --moon-dark:#1b2436;
  --moon-mare:#a9bcd6; --moon-rim:rgba(255,255,255,.20); --moon-glow:#cfe0ff;
  --lw-today:var(--acc-mould); --lw-guide:rgba(255,255,255,.10);
}
.md { display:block; overflow:visible; }
.md-full { filter:drop-shadow(0 6px 18px rgba(120,160,255,.18)); }
.lw { margin:0; }
.lw-svg { display:block; width:100%; height:auto; }
/* The wheel draws at ~320-380 px wide on every breakpoint (the card that
   holds it is a fixed column), so the rim words are sized once here rather
   than nudged up by a media query the way RingDial's are. */
.lw-label { font-family:var(--sans); font-size:10px; font-weight:700;
  letter-spacing:.09em; fill:var(--ink-3); }
.lw-label-principal { fill:var(--ink-2); }
.lw-label-half { font-size:8.8px; letter-spacing:.14em; fill:var(--ink-3); opacity:.8; }
.lw-disc.is-estimated { opacity:.42; }
.lw-caption, .lw-note { margin:8px 0 0; font-size:11.5px; line-height:1.45;
  color:var(--ink-3); text-align:center; }
.lw-note { margin-top:4px; font-style:italic; }
.lw-empty { padding:24px; text-align:center; font-size:13px; color:var(--ink-3); }
.lw-sr { position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0,0,0,0); white-space:nowrap; }

/* =====================================================   D1/D4/D5 shared components (ADR-0004 §5) — BandedLineChart,
   MeterWithReasons, SoilTriangle, CompassRose, StackedFractionBars,
   ConditionsSheet. Same rule as the block above: kept here because
   they are shared across demo pages, not owned by any one of them.
   ============================================================ */

/* ---- BandedLineChart ---- */
.blc-empty { color:var(--ink-3); font-size:13px; }
.blc-wrap { display:flex; flex-direction:column; gap:8px; }
.blc-svg { width:100%; height:auto; display:block; }
.blc-band-label { fill:var(--ink-3); font:9.5px var(--mono); }
.blc-band-label-compact { font-size:15px; }
.blc-axis-label { fill:var(--ink-3); font:10px var(--mono); }
.blc-axis-label-compact { font-size:14px; }
.blc-axis-label-today { fill:var(--ink); font-weight:700; }
.blc-axis-tick { stroke:var(--rule); stroke-width:1; }
.blc-split-line { stroke:var(--ink-3); stroke-width:1; stroke-dasharray:2 3; }
.blc-phase-label { fill:var(--ink-3); font:700 10px var(--mono); letter-spacing:.08em; text-transform:uppercase; }
.blc-line-past { fill:none; stroke:var(--acc-mould); stroke-width:2.5; stroke-linejoin:round; stroke-linecap:round; }
.blc-line-forecast { fill:none; stroke:var(--acc-mould); stroke-width:2.5; stroke-linejoin:round; stroke-linecap:round; opacity:.55; }
.blc-line-secondary { fill:none; stroke:var(--ink-2); stroke-width:1.75; stroke-dasharray:4 3; stroke-linejoin:round; }
.blc-point { fill:var(--surface); stroke:var(--acc-mould); stroke-width:1.5; cursor:default; }
.blc-point:focus-visible { outline:2px solid var(--acc-sky); outline-offset:1px; }
.blc-point-growth { fill:var(--st-critical); stroke:var(--st-critical); }
.blc-legend { display:flex; flex-wrap:wrap; gap:14px; font-size:12px; color:var(--ink-2); }
.blc-legend-item { display:inline-flex; align-items:center; gap:6px; }
.blc-legend-swatch { display:inline-block; width:16px; height:3px; border-radius:2px; }
.blc-legend-swatch.blc-swatch-secondary { background:none; border-top:2px dashed var(--ink-2); height:0; }
.blc-summary { color:var(--ink-3); font-size:12px; margin:0; }

/* ---- MeterWithReasons ---- */
.mwr-empty { color:var(--ink-3); font-size:13px; }
.mwr-wrap { display:flex; flex-direction:column; gap:12px; }
.mwr-head { display:flex; align-items:baseline; justify-content:space-between; gap:10px; flex-wrap:wrap; }
.mwr-title { font-size:14px; color:var(--ink); margin:0; }
.mwr-score { font:700 22px var(--sans); color:var(--ink); }
.mwr-score .mwr-max { font:600 13px var(--mono); color:var(--ink-3); }
.mwr-band-chip { font:700 10.5px var(--mono); letter-spacing:.06em; text-transform:uppercase;
  border-radius:99px; padding:4px 11px; border:1px solid var(--rule); white-space:nowrap; }
.mwr-track { position:relative; height:10px; border-radius:99px; background:var(--surface-3); overflow:hidden; }
.mwr-fill { position:absolute; inset:0 auto 0 0; border-radius:99px; }
.mwr-reasons-h { font:700 10.5px var(--mono); letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-3); margin:0 0 6px; }
.mwr-reasons { margin:0; padding-left:18px; font-size:13px; color:var(--ink-2); line-height:1.55; }
.mwr-reasons li { margin:3px 0; }
.mwr-summary { color:var(--ink-3); font-size:12px; margin:0; }

/* ---- SoilTriangle ---- */
.st-empty { color:var(--ink-3); font-size:13px; }
.st-wrap { display:flex; flex-direction:column; align-items:center; gap:10px; }
.st-svg { width:100%; max-width:260px; height:auto; }
.st-outline { fill:none; stroke:var(--rule); stroke-width:1.5; }
.st-grid { stroke:var(--rule); stroke-width:.5; opacity:.6; }
.st-axis-label { fill:var(--ink-2); font:700 11px var(--sans); }
.st-point { fill:var(--acc-mould); stroke:var(--surface); stroke-width:2; }
.st-point-label { fill:var(--ink); font:700 10px var(--mono); }
.st-class { font:700 15px var(--sans); color:var(--ink); margin:0; }
.st-drainage { font-size:12.5px; color:var(--ink-2); margin:2px 0 0; text-align:center; max-width:34ch; }
.st-summary { color:var(--ink-3); font-size:12px; margin:0; text-align:center; }

/* ---- CompassRose ---- */
.cr-empty { color:var(--ink-3); font-size:13px; }
.cr-wrap { display:flex; flex-direction:column; align-items:center; gap:8px; }
.cr-svg { width:100%; max-width:240px; height:auto; }
.cr-ring { fill:none; stroke:var(--rule); stroke-width:1.5; }
.cr-tick { stroke:var(--rule); stroke-width:1; }
.cr-cardinal { fill:var(--ink-2); font:700 11px var(--sans); }
.cr-shaded { fill:var(--acc-mould); opacity:.22; }
.cr-sunpath { fill:none; stroke:var(--st-elevated); stroke-width:2; stroke-dasharray:1 4; stroke-linecap:round; }
.cr-arrow { fill:var(--acc-sky); stroke:var(--acc-sky); }
.cr-arrow-label { fill:var(--ink); font:700 12px var(--sans); }
.cr-flat { color:var(--ink-3); font:12px var(--sans); margin:0; }
/* Legend line BELOW the rose (design review defect D4-4: these captions used
   to sit inside the SVG at a fixed position and overlapped the N/S cardinal
   labels at every width). */
.cr-legend { display:flex; flex-wrap:wrap; justify-content:center; gap:12px;
  font:700 9px var(--mono); letter-spacing:.04em; text-transform:uppercase; }
.cr-legend-item { display:inline-flex; align-items:center; gap:5px; }
.cr-legend-swatch { display:inline-block; width:12px; height:2px; border-radius:1px; }
.cr-legend-swatch-sun { border-top:2px dashed var(--st-elevated); height:0; }
.cr-legend-swatch-shade { background:var(--acc-mould); opacity:.5; height:8px; border-radius:2px; }
.cr-summary { color:var(--ink-3); font-size:12px; margin:0; text-align:center; max-width:36ch; }

/* ---- StackedFractionBars ---- */
.sfb-empty { color:var(--ink-3); font-size:13px; }
.sfb-wrap { display:flex; flex-direction:column; gap:8px; }
.sfb-bar { display:flex; height:22px; border-radius:6px; overflow:hidden; background:var(--surface-3); gap:2px; }
.sfb-seg { display:flex; align-items:center; justify-content:center; min-width:2px; cursor:default; }
.sfb-seg:focus-visible { outline:2px solid var(--acc-sky); outline-offset:1px; }
.sfb-seg.sfb-seg-other { background:var(--surface-3); }
.sfb-legend { display:flex; flex-wrap:wrap; gap:10px 16px; font-size:12px; color:var(--ink-2); }
.sfb-legend-item { display:inline-flex; align-items:center; gap:6px; }
.sfb-legend-swatch { width:11px; height:11px; border-radius:3px; flex:none; }
.sfb-summary { color:var(--ink-3); font-size:12px; margin:0; }

/* ---- ConditionsSheet (D5 print-first A4 document) ---- */
.cs-doc { background:#fff; color:#111; border-radius:10px; padding:24px 26px 30px;
  font:13px/1.5 var(--sans); max-width:800px; margin:0 auto; }
.cs-head { display:flex; justify-content:space-between; align-items:flex-start; gap:16px;
  border-bottom:2px solid #111; padding-bottom:12px; margin-bottom:16px; flex-wrap:wrap; }
/* Black long-form logo on the white sheets (the topbar's white variant would
   vanish on paper). Intrinsic 2124x276; height sets the rendered size. */
.cs-logo, .ps-logo { display:block; height:22px; width:auto; margin:0 0 10px; }
.cs-title { font-size:19px; margin:2px 0 6px; color:#111; }
.cs-meta { font:600 11px var(--mono); color:#555; display:flex; flex-wrap:wrap; gap:6px 10px; }
.cs-meta-sep { color:#aaa; }
.cs-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:10px; margin:14px 0; }
.cs-card { border:1px solid #ddd; border-radius:8px; padding:10px 12px; background:#fafafa; }
.cs-card-h { font:700 10px var(--mono); letter-spacing:.07em; text-transform:uppercase; color:#666; margin:0 0 6px; }
.cs-stat { display:flex; justify-content:space-between; gap:8px; font-size:13px; padding:2px 0; }
.cs-stat dt { color:#666; margin:0; }
.cs-stat dd { margin:0; font-weight:600; color:#111; text-align:right; }
.cs-band-chip { font:700 10px var(--mono); letter-spacing:.05em; text-transform:uppercase;
  border-radius:99px; padding:2px 9px; border:1px solid #ccc; color:#333; }
.cs-flag { border-radius:8px; padding:10px 12px; margin:14px 0; font-size:13px; border:1px solid #ddd; }
.cs-flag-yes { background:#fdf1ee; border-color:#e2b3a6; color:#7a2e1c; }
.cs-flag-no { background:#f0f7f3; border-color:#bcdcc9; color:#1e5c37; }
.cs-selector { display:flex; flex-wrap:wrap; gap:6px; margin:6px 0 10px; }
.cs-selector label { font:600 11.5px var(--sans); border:1px solid #ccc; border-radius:99px;
  padding:4px 11px; color:#444; cursor:pointer; }
.cs-selector input { margin-right:5px; }
.cs-badge { display:inline-flex; align-items:center; gap:6px; font:700 10.5px var(--mono);
  letter-spacing:.05em; text-transform:uppercase; border:1px solid #ccc; border-radius:99px; padding:3px 10px; color:#333; }
.cs-section-h { font:700 11px var(--mono); letter-spacing:.08em; text-transform:uppercase; color:#666; margin:16px 0 6px; }
.cs-method p, .cs-method li { font-size:12px; color:#333; line-height:1.55; }
.cs-method ul { margin:4px 0; padding-left:18px; }
.cs-foot { margin-top:16px; padding-top:10px; border-top:1px solid #ddd; font-size:11px; color:#777; }
.cs-empty-stat { color:#999; font-style:italic; }
.cs-sr-only { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; }
@media (max-width:560px) { .cs-head { flex-direction:column; } }
/* ---- SlotPlanner ----
 * Generic multi-day slot-card planner — Airwatch's ventilation planner and
 * the Drying Window Planner's day-hour slots both render through this one
 * component (design brief §5b). Every slot's colour comes from the caller's
 * `statuses[key].colorVar` via the inline `--sp-c` custom property set per
 * element, never a fixed per-feature class. */
.sp-empty { color:var(--ink-3); font-size:13px; padding:8px 2px; }
.sp-wrap { display:flex; flex-direction:column; }
.sp-legend { display:flex; flex-wrap:wrap; gap:16px; font-size:12.5px; color:var(--ink-2);
  margin:0 0 14px; align-items:center; }
.sp-legend-item { display:inline-flex; align-items:center; gap:6px; }
.sp-legend-swatch { display:inline-block; width:12px; height:12px; border-radius:3px;
  background:var(--sp-c, var(--ink-3)); }
.sp-scroll { overflow-x:auto; padding-bottom:6px; }
.sp-strip { display:flex; gap:12px; width:max-content; min-width:100%; }
.sp-day { display:flex; flex-direction:column; gap:6px; min-width:118px; }
.sp-day-head { display:flex; justify-content:space-between; align-items:baseline; gap:6px; padding:0 2px; }
.sp-day-label { font:700 12.5px var(--sans); color:var(--ink); }
.sp-day-stat { font:600 10.5px var(--mono); color:var(--ink-3); }
.sp-day-slots { display:flex; flex-direction:column; gap:4px; }
.sp-slot { display:flex; align-items:center; justify-content:space-between; gap:8px;
  border-radius:8px; padding:8px 10px; border:1px solid var(--sp-c, transparent);
  background:color-mix(in srgb, var(--sp-c, var(--surface-3)) 20%, var(--surface-2)); }
.sp-slot-time { font:600 11.5px var(--mono); color:var(--ink); opacity:.85; }
.sp-slot-status { font:700 10px var(--mono); letter-spacing:.06em; color:var(--sp-c, var(--ink-2)); }
.sp-slot-best { border-width:2px; }
.sp-slot-flag { border-color:var(--st-critical); border-style:dashed; border-width:2px; }
.sp-slot-muted { opacity:.55; }
.sp-slot:focus-visible { outline:2px solid var(--ink); outline-offset:2px; }
.sp-footnote { color:var(--ink-3); font-size:11.5px; margin:14px 0 0; line-height:1.55; }
.sp-summary { color:var(--ink-3); font-size:12px; margin:8px 0 0; }

/* ---- Print: never print the gallery chrome, whichever route the user took
   (the page's own "Print" button toggles body.print-mode; browser Cmd/Ctrl+P
   does not). Without this the dark topbar printed as an empty framed box. */
@media print {
  .topbar { display:none !important; }
}
