/* ============================================================================
   HELIOS DESIGN SYSTEM — "paper & ink"
   ----------------------------------------------------------------------------
   Token layer generated by Claude Design (Spectral / IBM Plex Sans / IBM Plex
   Mono; petrol accent; severity scale with measured contrast on paper).
   Component layer re-keyed onto the dashboard's existing selectors so the
   markup and JavaScript are unchanged.

   Three rules this file enforces:
     1. Colour, size, space and radius come from tokens. No literals below.
     2. Severity is never colour alone — always paired with a label or glyph.
     3. Depth is whitespace and 1px rules. The only shadow is the plate edge.
   ========================================================================= */

@import url("https://fonts.googleapis.com/css2?family=Spectral:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500;600&display=swap");

/* ---------------------------------------------------------------------------
   1. TOKENS  (from the design system, verbatim)
   Contrast ratios quoted against the paper ground #EFF1F0.
   ------------------------------------------------------------------------ */
:root {
  /* Surfaces */
  --paper:            #EFF1F0;
  --surface-card:     #FBFCFC;
  --surface-well:     #E3E7E6;
  --surface-plate:    #12161A;   /* dark photographic plate (map / globe) */
  --surface-plate-2:  #1C2126;   /* plate chrome: inset controls, popups   */

  /* Ink */
  --ink-1: #14181A;              /* primary    16.2:1 */
  --ink-2: #414749;              /* secondary   8.3:1 */
  --ink-3: #666D6F;              /* tertiary    4.7:1 */
  --ink-on-plate:     #E7EAEA;
  --ink-on-plate-dim: #98A0A2;

  /* Rules */
  --rule:        #D8DCDB;
  --rule-strong: #B7BEBD;
  --rule-plate:  #262C31;

  /* Accent — petrol */
  --accent:       #0E5C58;       /* 6.9:1 on paper */
  --accent-hover: #0A4744;
  --accent-soft:  #DCEAE8;
  --accent-ink:   #FBFCFC;

  /* Severity — all AA or better as text on paper */
  --sev-quiet:        #5A6068;   /* 5.6:1 */
  --sev-quiet-soft:   #E7E9EA;
  --sev-c:            #1F5E8B;   /* 5.6:1 */
  --sev-c-soft:       #E1EAF1;
  --sev-m:            #9A5410;   /* 5.1:1 */
  --sev-m-soft:       #F6E8D6;
  --sev-x:            #9E241B;   /* 6.8:1 */
  --sev-x-soft:       #F6E0DD;
  --sev-extreme:      #6B1E63;   /* 9.3:1 */
  --sev-extreme-soft: #EFE2EE;

  /* All-clear. The scale had no green because it began at "quiet" (grey) —
     an absence of activity rather than a positive state. The flare-level
     readout needs to say "nothing wrong" at a glance, so quiet gets a green.
     Deep moss rather than a signal green, to stay inside the print palette.
     5.5:1 as text on paper, so it holds at the 12.5px chip as well as the
     37.5px badge. */
  --sev-ok:      #3D6B45;
  --sev-ok-soft: #E2EBE3;

  /* Severity ON THE PLATE. The paper values above go muddy against #12161A,
     so the dark field keeps its own brighter set — these are the values the
     map/globe canvas actually draws. The map legend swatches use these
     because that legend is a key to the plate, not to the page. */
  --sev-quiet-plate: #2FBF71;
  --sev-c-plate:     #F5C542;
  --sev-m-plate:     #FF8A3D;
  --sev-x-plate:     #FF4D5E;

  /* Chart palette */
  --series-1: #1F5E8B;
  --series-2: #0E5C58;
  --series-3: #4E7A4F;
  --series-4: #9A5410;
  --series-5: #6B4E8C;
  --series-muted: #A2A8A7;
  --chart-grid: #E1E5E4;
  --chart-axis: #B7BEBD;
  --chart-plot: #FBFCFC;

  /* Focus */
  --focus-ring: #1F5E8B;
  --focus-ring-plate: #8FC3E8;

  /* Two ambient values that must invert with the theme. Kept as tokens rather
     than literals so the dark block is the only place they are restated: the
     hairline around a legend swatch, and the highlight that sweeps a skeleton. */
  --swatch-edge: rgba(18, 22, 26, 0.25);
  --skel-sweep:  rgba(251, 252, 252, 0.6);

  /* Type — 3 families, 8 steps, ratio 1.20 from a 15px body */
  --font-display: "Spectral", "Iowan Old Style", Georgia, serif;
  --font-sans:    "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif;
  --font-mono:    "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  --fs-1: 10.5px;   /* eyebrow / axis label  */
  --fs-2: 12.5px;   /* caption, table cell   */
  --fs-3: 15px;     /* body — base           */
  --fs-4: 18px;     /* lead body, card title */
  --fs-5: 21.5px;   /* section heading       */
  --fs-6: 26px;     /* card figure           */
  --fs-7: 31px;     /* page title            */
  --fs-8: 37.5px;   /* headline figure       */

  --lh-tight: 1.08;
  --lh-snug:  1.28;
  --lh-body:  1.55;

  --tracking-eyebrow: 0.09em;
  --tracking-tight: -0.011em;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;

  /* Space — 4px base */
  --space-05: 2px;  --space-1: 4px;  --space-2: 8px;  --space-3: 12px;
  --space-4: 16px;  --space-5: 24px; --space-6: 32px; --space-7: 48px;
  --space-8: 64px;

  /* Radius — print-small; radius-3 is the largest in the system */
  --radius-1: 2px;
  --radius-2: 3px;
  --radius-3: 5px;

  --hairline: 1px solid var(--rule);
  --hairline-strong: 1px solid var(--rule-strong);
  --shadow-plate: 0 1px 0 0 rgba(18, 22, 26, 0.16);

  --measure: 68ch;
  --page-max: 1180px;

  /* Motion */
  --dur-1: 90ms; --dur-2: 140ms; --dur-3: 220ms;
  --ease-standard: cubic-bezier(0.2, 0, 0.2, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {
  :root { --dur-1: 0ms; --dur-2: 0ms; --dur-3: 0ms; }
}

/* ---------------------------------------------------------------------------
   2. COMPATIBILITY ALIASES
   The dashboard markup and JS reference these names directly — e.g.
   SEV = { 'C':'var(--c-class)' } and inline style="background:var(--m-class)".
   Mapping them onto the new tokens is what lets the redesign land without
   touching a single line of JavaScript.
   ------------------------------------------------------------------------ */
:root {
  --text:          var(--ink-1);
  --text-dim:      var(--ink-2);
  --text-faint:    var(--ink-3);
  --border:        var(--rule);
  --border-strong: var(--rule-strong);
  --surface:       var(--surface-card);
  --surface-2:     var(--surface-well);
  --bg-0:          var(--paper);
  --bg-1:          var(--paper);

  --ok:      var(--sev-ok);
  --quiet:   var(--sev-quiet);
  --c-class: var(--sev-c);
  --m-class: var(--sev-m);
  --x-class: var(--sev-x);
  --extreme: var(--sev-extreme);

  --accent-2:  var(--series-5);
  --radius:    var(--radius-2);
  --radius-sm: var(--radius-1);
  --shadow:    var(--shadow-plate);
  --maxw:      var(--page-max);
  --ease:      var(--ease-standard);
}

/* ---------------------------------------------------------------------------
   3. BASE
   ------------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0; min-height: 100dvh;
  background: var(--paper); color: var(--ink-1);
  font-family: var(--font-sans); font-size: var(--fs-3); line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

a { color: var(--accent); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-hover); }

h1, h2, h3, h4 {
  margin: 0; font-family: var(--font-display); font-weight: var(--weight-semibold);
  line-height: var(--lh-snug); letter-spacing: var(--tracking-tight);
}

a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-1);
}

.mono, .num {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "zero" 1; letter-spacing: -0.01em;
}
.muted, .q { color: var(--ink-3); }
.wrap { max-width: var(--page-max); margin: 0 auto; padding: 0 var(--space-6) var(--space-8); }
.spacer { flex: 1; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* The old build painted an aurora gradient and a starfield. The ground is
   paper now; both are inert. */
.backdrop, .stars { display: none !important; }

/* ---------------------------------------------------------------------------
   4. MASTHEAD
   ------------------------------------------------------------------------ */
header.top {
  position: sticky; top: 0; z-index: 40;
  background: var(--paper); border-bottom: 2px solid var(--ink-1);
}
.top-inner {
  max-width: var(--page-max); margin: 0 auto; padding: var(--space-3) var(--space-6);
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
}
.logo { display: flex; align-items: center; gap: var(--space-3); }
.logo .mark {
  width: 32px; height: 32px; border-radius: var(--radius-1);
  display: grid; place-items: center;
  background: var(--ink-1); color: var(--paper);
}
.logo b {
  font-family: var(--font-display); font-size: var(--fs-5);
  font-weight: var(--weight-semibold); letter-spacing: -0.02em; line-height: 1.05;
}
.logo span { display: block; font-size: var(--fs-2); color: var(--ink-3); }

/* ---------------------------------------------------------------------------
   5. STATUS PILL
   ------------------------------------------------------------------------ */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-1); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  padding: 3px 8px 3px 7px; border-radius: var(--radius-1);
  border: 1px solid var(--rule-strong); background: var(--surface-card);
  color: var(--ink-2); white-space: nowrap;
}
.dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.dot.live   { background: var(--sev-quiet); }
.dot.cached { background: var(--ink-2); }
.dot.stale  { background: var(--sev-m); }

/* Tint the whole pill from its state dot. */
.pill:has(.dot.live)   { color: var(--sev-quiet); border-color: var(--sev-quiet); background: var(--sev-quiet-soft); }
.pill:has(.dot.cached) { background: var(--surface-well); }
.pill:has(.dot.stale)  { color: var(--sev-m); border-color: var(--sev-m); background: var(--sev-m-soft); }

/* ---------------------------------------------------------------------------
   6. BUTTONS, SEGMENTED CONTROLS, FORM CONTROLS
   ------------------------------------------------------------------------ */
button.btn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-family: var(--font-sans); font-size: var(--fs-2); font-weight: var(--weight-medium);
  line-height: 1; padding: 7px 13px; border-radius: var(--radius-1);
  border: 1px solid var(--rule-strong); background: var(--surface-card); color: var(--ink-1);
  cursor: pointer;
  transition: background-color var(--dur-2) var(--ease-standard),
              border-color var(--dur-2) var(--ease-standard);
}
button.btn:hover:not(:disabled) { background: var(--surface-well); border-color: var(--ink-3); }
button.btn:active:not(:disabled) { background: var(--rule); }
button.btn:disabled { opacity: 0.42; cursor: default; }
.btn svg.spin { animation: spin 0.9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.map-toggle {
  display: inline-flex; border: 1px solid var(--rule-strong);
  border-radius: var(--radius-1); overflow: hidden; background: var(--surface-card);
}
.mt-btn {
  font-family: var(--font-sans); font-size: var(--fs-2); font-weight: var(--weight-medium);
  padding: 5px 12px; border: 0; border-right: 1px solid var(--rule);
  background: transparent; color: var(--ink-2); cursor: pointer;
  transition: background-color var(--dur-2) var(--ease-standard),
              color var(--dur-2) var(--ease-standard);
}
.mt-btn:last-child { border-right: 0; }
/* :not(.active) matters -- `.mt-btn:hover:not(:disabled)` (0,3,0) outranks
   `.mt-btn.active` (0,2,0), so hovering the selected button replaced its light
   background while keeping its dark `--paper` label: dark-on-dark, invisible. */
.mt-btn:hover:not(:disabled):not(.active) { background: var(--surface-well); }
.mt-btn.active { background: var(--ink-1); color: var(--paper); }
.mt-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.mt-btn:focus-visible { outline-offset: -2px; }

select, input[type="datetime-local"], input[type="text"] {
  font-family: var(--font-sans); font-size: var(--fs-2); color: var(--ink-1);
  background: var(--surface-card); border: 1px solid var(--rule-strong);
  border-radius: var(--radius-1); padding: 6px 9px;
  transition: border-color var(--dur-2) var(--ease-standard);
}
select:hover, input[type="datetime-local"]:hover { border-color: var(--ink-3); }
input[type="checkbox"] { accent-color: var(--accent); }

/* ---------------------------------------------------------------------------
   7. ALERT BANNER
   ------------------------------------------------------------------------ */
.alert {
  display: none; align-items: flex-start; gap: var(--space-4);
  margin: var(--space-5) 0 var(--space-1);
  border: 1px solid var(--sev-x); border-radius: var(--radius-2);
  padding: var(--space-4) var(--space-5);
  background: var(--sev-x-soft); color: var(--sev-x);
}
.alert.show { display: flex; }
.alert.extreme {
  border-color: var(--sev-extreme); background: var(--sev-extreme-soft); color: var(--sev-extreme);
}
.alert .ic { color: currentColor; flex-shrink: 0; margin-top: 2px; }
.alert h2 {
  font-family: var(--font-display); font-size: var(--fs-4);
  font-weight: var(--weight-semibold); color: currentColor;
}
.alert p { margin: 4px 0 0; font-size: var(--fs-2); color: var(--ink-2); max-width: var(--measure); }

/* ---------------------------------------------------------------------------
   8. SECTIONS + GRIDS
   ------------------------------------------------------------------------ */
.section-title {
  display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap;
  margin: var(--space-7) 0 var(--space-4); padding-bottom: var(--space-2);
  border-bottom: var(--hairline-strong);
}
.section-title h2 {
  font-family: var(--font-display); font-size: var(--fs-5); font-weight: var(--weight-semibold);
}
.section-title .sub {
  font-family: var(--font-sans); font-size: var(--fs-2); color: var(--ink-3);
  margin-left: auto; text-align: right;
}

.grid { display: grid; gap: var(--space-4); }
.hero-grid     { grid-template-columns: 1.3fr 1fr; }
.forecast-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.meta-grid     { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 860px) {
  .hero-grid, .forecast-grid { grid-template-columns: 1fr; }
  .meta-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---------------------------------------------------------------------------
   9. CARD
   ------------------------------------------------------------------------ */
.card {
  background: var(--surface-card); border: var(--hairline);
  border-radius: var(--radius-2); padding: var(--space-5);
}
.card h3 {
  font-family: var(--font-sans); font-size: var(--fs-1); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--ink-3);
}

/* ---------------------------------------------------------------------------
   10. CURRENT CONDITIONS
   ------------------------------------------------------------------------ */
.now { display: flex; flex-direction: column; gap: var(--space-1); }
.now .state-row {
  display: flex; align-items: center; gap: var(--space-4);
  margin-top: var(--space-2); flex-wrap: wrap;
}

.badge-class {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-weight: var(--weight-semibold); font-size: var(--fs-8);
  line-height: 1; letter-spacing: -0.02em;
}

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-sans); font-size: var(--fs-2);
  padding: 3px 9px; border-radius: var(--radius-1);
  border: 1px solid var(--rule); background: var(--surface-card); color: var(--ink-2);
}
.chip .d { width: 8px; height: 8px; border-radius: 50%; flex: none; }

.now .detail { display: flex; gap: var(--space-6); margin-top: var(--space-5); flex-wrap: wrap; }
.now .detail div span {
  display: block; font-size: var(--fs-1); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  color: var(--ink-3); margin-bottom: var(--space-1);
}
.now .detail div b {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-4); font-weight: var(--weight-regular);
}

/* ---------------------------------------------------------------------------
   11. HEADLINE FORECAST
   ------------------------------------------------------------------------ */
.headline { display: flex; flex-direction: column; justify-content: center; }
.gauge { display: flex; align-items: center; gap: var(--space-5); margin: var(--space-3) 0 var(--space-1); }
.gauge .ring { width: 88px; height: 88px; flex-shrink: 0; }
.gauge .big {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-8); line-height: 1; letter-spacing: -0.02em;
}
.gauge .lbl { font-family: var(--font-display); font-size: var(--fs-4); color: var(--ink-1); margin-top: 6px; }
.gauge .lbl b { font-weight: var(--weight-semibold); }
.src-note { font-size: var(--fs-2); color: var(--ink-3); margin-top: var(--space-2); }

/* ---------------------------------------------------------------------------
   12. HORIZON CARDS + PROBABILITY BARS
   ------------------------------------------------------------------------ */
.horizon h3 {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-2);
  padding-bottom: var(--space-2); border-bottom: var(--hairline);
}
.horizon .exp {
  font-family: var(--font-mono); font-size: var(--fs-1); color: var(--ink-3);
  text-transform: none; letter-spacing: 0;
}

.pbar { margin-top: var(--space-3); }
.pbar .lab {
  display: flex; justify-content: space-between; align-items: center;
  font-size: var(--fs-2); margin-bottom: 5px;
}
.pbar .lab .name {
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: var(--weight-medium); color: var(--ink-2);
}
.pbar .lab .name i {
  width: 9px; height: 9px; border-radius: var(--radius-1);
  display: inline-block; flex: none;
}
.pbar .lab .val {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--fs-2);
}

.track {
  height: 8px; background: var(--surface-well);
  border: 1px solid var(--rule); border-radius: var(--radius-1); overflow: hidden;
}
/* The fill animates transform, not width: scaling a composited layer keeps the
   bar off the layout path. .track owns the radius and clips, so scaleX cannot
   distort a corner. JS sets scaleX(fraction); see the pbar fill in index.html. */
.track > i {
  display: block; height: 100%; width: 100%;
  transform: scaleX(0); transform-origin: left center;
  transition: transform var(--dur-3) var(--ease-out);
}

/* ---------------------------------------------------------------------------
   13. METRIC TILE
   ------------------------------------------------------------------------ */
.tile span {
  display: block; font-size: var(--fs-1); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  color: var(--ink-3); margin-bottom: var(--space-1);
}
.tile b {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-6); font-weight: var(--weight-medium);
}
.tile small { font-size: var(--fs-2); color: var(--ink-2); }

/* ---------------------------------------------------------------------------
   14. CHARTS
   ------------------------------------------------------------------------ */
.chart-card { padding: var(--space-4); }
#flux-chart { width: 100%; height: 260px; display: block; }
#exp-chart  { width: 100%; height: 340px; display: block; }
@media (max-width: 640px) { #exp-chart { height: 300px; } }

.legend {
  display: flex; gap: var(--space-4); flex-wrap: wrap;
  margin-top: var(--space-3); padding-top: var(--space-2);
  border-top: var(--hairline); font-size: var(--fs-2); color: var(--ink-2);
}
.legend i { display: inline-block; width: 18px; height: 3px; vertical-align: middle; margin-right: 6px; }

.exp-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); margin-bottom: var(--space-3);
}
#exp-dl {
  font-family: var(--font-mono); font-size: var(--fs-1);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  color: var(--accent); text-decoration: none;
  border: 1px solid var(--rule-strong); border-radius: var(--radius-1); padding: 4px 9px;
}
#exp-dl:hover { border-color: var(--accent); background: var(--accent-soft); }

/* ---------------------------------------------------------------------------
   15. THE PLATE — map / globe
   The light-to-dark transition is deliberate: a paper mat with a strong
   hairline frames the dark field, and every control, legend and caption
   stays outside on paper.
   ------------------------------------------------------------------------ */
.map-card { padding: var(--space-4); }
.map-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap; margin-bottom: var(--space-3);
}
.map-head-right { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.map-status-group { display: flex; gap: var(--space-2); flex-wrap: wrap; }

.layer-toggles { display: flex; gap: var(--space-4); align-items: center; flex-wrap: wrap; }
.layer-toggles .lyr {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-2); color: var(--ink-2); cursor: pointer; user-select: none;
}
.lyr-sw { display: inline-block; width: 13px; height: 7px; border: 1px solid var(--swatch-edge); }
.lyr-sw.hf  { background: linear-gradient(90deg, var(--sev-c), var(--sev-x)); }
.lyr-sw.aur { background: linear-gradient(90deg, var(--series-3), var(--series-2)); }

/* Mat (paper) wrapping field (dark) — achieved without touching the markup. */
.map-wrap {
  position: relative; width: 100%;
  background: var(--surface-card);
  border: var(--hairline-strong); border-radius: var(--radius-3);
  padding: 8px; box-shadow: var(--shadow-plate);
}
#hazard-map, #hazard-globe {
  display: block; width: 100%;
  background: var(--surface-plate);
  border: 1px solid var(--rule-plate); border-radius: var(--radius-2);
}
#hazard-map { aspect-ratio: 2 / 1; }
#hazard-map[hidden], #hazard-globe[hidden] { display: none; }
#hazard-globe { height: 460px; }
@media (max-width: 640px) { #hazard-globe { height: 340px; } }

.map-legend { display: flex; gap: var(--space-4); flex-wrap: wrap; font-size: var(--fs-2); color: var(--ink-2); }
.map-legend .sw {
  display: inline-block; width: 11px; height: 11px;
  border: 1px solid var(--swatch-edge); vertical-align: -1px; margin-right: 6px;
}
.map-legend .sw.sun   { background: #E8A33D; border-radius: 50%; }
.map-legend .sw.night { background: var(--surface-plate); }
.map-legend .sw.aur   { background: linear-gradient(90deg, var(--series-3), var(--series-2)); }

.map-caption {
  font-size: var(--fs-2); color: var(--ink-3); line-height: var(--lh-snug);
  margin: var(--space-3) 2px 2px; max-width: var(--measure);
}
.map-caption b { font-weight: var(--weight-semibold); }

/* ---------------------------------------------------------------------------
   16. SATELLITE LAYER  (popup and tooltip sit ON the plate, so they go dark)
   ------------------------------------------------------------------------ */
#sat-controls {
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
  margin-top: var(--space-3); font-size: var(--fs-2); color: var(--ink-2);
}
#sat-controls[hidden] { display: none; }
.sat-toggle { display: inline-flex; align-items: center; gap: var(--space-2); cursor: pointer; user-select: none; }
.sat-legend { display: flex; gap: var(--space-3); flex-wrap: wrap; }
.sat-legend .sw {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  border: 1px solid var(--swatch-edge); vertical-align: -1px; margin-right: 5px;
}

.sat-bands {
  display: inline-flex; border: 1px solid var(--rule-strong);
  border-radius: var(--radius-1); overflow: hidden;
}
.sat-band {
  font-family: var(--font-sans); font-size: var(--fs-1); font-weight: var(--weight-medium);
  padding: 4px 9px; border: 0; border-right: 1px solid var(--rule);
  background: transparent; color: var(--ink-2); cursor: pointer;
  transition: background-color var(--dur-2) var(--ease-standard),
              color var(--dur-2) var(--ease-standard);
}
.sat-band:last-child { border-right: 0; }
.sat-band:hover { background: var(--surface-well); }
.sat-band.active { background: var(--ink-1); color: var(--paper); }
.sat-band:focus-visible { outline-offset: -2px; }

.sat-count {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-1); color: var(--ink-3); margin-left: auto;
}
.sat-count .sat-cdot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin: 0 3px 0 var(--space-2); }
.sat-count .sat-shown { color: var(--ink-2); }

#sat-popup {
  position: absolute; z-index: 6; width: 268px;
  background: var(--surface-plate-2); border: 1px solid var(--rule-plate);
  border-radius: var(--radius-2); padding: var(--space-3) var(--space-4) var(--space-4);
  color: var(--ink-on-plate);
}
#sat-popup[hidden] { display: none; }
#sat-popup .sat-x {
  position: absolute; top: 6px; right: 9px; border: 0; background: none;
  color: var(--ink-on-plate-dim); font-size: 15px; line-height: 1; cursor: pointer;
}
#sat-popup .sat-x:hover { color: var(--ink-on-plate); }
#sat-popup .sat-x:focus-visible { outline-color: var(--focus-ring-plate); }
#sat-popup .sat-name { font-family: var(--font-display); font-size: var(--fs-3); padding-right: var(--space-4); }
#sat-popup .sat-tier {
  font-family: var(--font-sans); font-size: var(--fs-1); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; margin: 3px 0 var(--space-3);
}
#sat-popup .sat-dl {
  display: grid; grid-template-columns: auto 1fr; gap: 3px var(--space-3);
  margin: var(--space-3) 0; font-size: var(--fs-2);
}
#sat-popup .sat-dl dt {
  color: var(--ink-on-plate-dim); font-size: var(--fs-1);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
}
#sat-popup .sat-dl dd { margin: 0; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
#sat-popup .sat-why {
  font-size: var(--fs-2); color: var(--ink-on-plate-dim); margin-top: var(--space-3);
  border-top: 1px solid var(--rule-plate); padding-top: var(--space-2);
}

.sat-tip {
  position: absolute; z-index: 7; pointer-events: none;
  background: var(--surface-plate-2); border: 1px solid var(--rule-plate);
  border-radius: var(--radius-1); padding: 4px 8px;
  font-size: var(--fs-1); color: var(--ink-on-plate); white-space: nowrap;
}
.sat-tip[hidden] { display: none; }
.sat-tip b { font-family: var(--font-sans); font-weight: var(--weight-semibold); }

/* ---------------------------------------------------------------------------
   17. IMPACT PANEL
   ------------------------------------------------------------------------ */
.impact-row { display: flex; gap: var(--space-4); padding: var(--space-4) 0; border-bottom: var(--hairline); }
.impact-row:last-child { border-bottom: 0; }
.impact-code {
  font-family: var(--font-mono); font-size: var(--fs-4); font-weight: var(--weight-semibold);
  min-width: 56px; text-align: center; padding: 4px 0 5px; height: fit-content;
  border: 1px solid; border-radius: var(--radius-1);
}
.impact-row b { font-family: var(--font-display); font-size: var(--fs-4); font-weight: var(--weight-semibold); }
.impact-domain {
  display: block; font-size: var(--fs-1); letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase; color: var(--ink-3); margin-top: 3px;
}
.impact-text { margin: var(--space-2) 0 0; font-size: var(--fs-2); color: var(--ink-2); max-width: 62ch; }

.impact-alerts { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-3); }
.impact-alerts[hidden] { display: none; }
.impact-alert {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); border-radius: var(--radius-2); font-size: var(--fs-2);
  border: 1px solid var(--sev-m); background: var(--sev-m-soft); color: var(--sev-m);
}
.impact-alert.severe { border-color: var(--sev-x); background: var(--sev-x-soft); color: var(--sev-x); }
.impact-alert.watch  { border-color: var(--sev-c); background: var(--sev-c-soft); color: var(--sev-c); }
.impact-alert .ia-lvl { font-family: var(--font-mono); font-weight: var(--weight-semibold); white-space: nowrap; }

.notify-acc { font-size: var(--fs-2); color: var(--ink-2); }

/* ---------------------------------------------------------------------------
   18. TABLES
   ------------------------------------------------------------------------ */
table.tracks, table.regions { width: 100%; border-collapse: collapse; font-size: var(--fs-2); }
table.tracks th, table.regions th {
  font-family: var(--font-sans); font-size: var(--fs-1); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--ink-3);
  padding: var(--space-2); border-bottom: var(--hairline-strong);
  white-space: nowrap; text-align: left;
}
table.tracks td, table.regions td {
  padding: 9px var(--space-2); border-bottom: var(--hairline);
  color: var(--ink-1); vertical-align: baseline;
}
table.tracks tbody tr:last-child td, table.regions tbody tr:last-child td { border-bottom: 0; }
table.tracks tbody tr:hover td, table.regions tbody tr:hover td { background: var(--surface-well); }
table.tracks td.num, table.regions td.num {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right;
}
table.tracks .muted { color: var(--ink-3); }

.region-wrap { overflow-x: auto; }
table.regions { min-width: 560px; }
table.regions th, table.regions td { text-align: right; }
table.regions th:first-child, table.regions td:first-child { text-align: left; }
table.regions th { cursor: pointer; user-select: none; }
table.regions th:hover { color: var(--accent); }
table.regions tr.reg-quiet { color: var(--ink-3); }

.reg-tag {
  display: inline-block; margin-left: var(--space-2); padding: 1px 7px;
  font-family: var(--font-sans); font-size: var(--fs-1); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  border: 1px solid; border-radius: var(--radius-1); vertical-align: 1px; white-space: nowrap;
}
.reg-tag.quiet  { color: var(--sev-quiet); border-color: var(--sev-quiet); background: var(--sev-quiet-soft); }
.reg-tag.active,
.reg-tag.c      { color: var(--sev-c); border-color: var(--sev-c); background: var(--sev-c-soft); }
.reg-tag.m      { color: var(--sev-m); border-color: var(--sev-m); background: var(--sev-m-soft); }
.reg-tag.x      { color: var(--sev-x); border-color: var(--sev-x); background: var(--sev-x-soft); }

/* ---------------------------------------------------------------------------
   19. FOOTER
   ------------------------------------------------------------------------ */
footer {
  margin-top: var(--space-8); padding: var(--space-5) 0 var(--space-7);
  border-top: var(--hairline-strong);
  display: flex; flex-direction: column; gap: var(--space-2);
  font-size: var(--fs-2); color: var(--ink-3);
}
footer a { color: var(--ink-2); }
.disc {
  background: var(--surface-well); border: var(--hairline); border-radius: var(--radius-1);
  padding: var(--space-3) var(--space-4); margin-top: var(--space-2);
  max-width: var(--measure); line-height: var(--lh-snug);
}

/* ---------------------------------------------------------------------------
   20. LOADING + ERROR
   ------------------------------------------------------------------------ */
.skel {
  background: var(--surface-well); border-radius: var(--radius-1);
  position: relative; overflow: hidden; color: transparent !important;
}
.skel::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, var(--skel-sweep), transparent);
  transform: translateX(-100%);
  animation: hl-sweep 1.4s var(--ease-standard) infinite;
}
@keyframes hl-sweep { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .skel::after { animation: none; } }

.error-box {
  display: none; text-align: left;
  border: 1px solid var(--rule-strong); border-left: 3px solid var(--sev-x);
  border-radius: var(--radius-1); background: var(--surface-card);
  padding: var(--space-4) var(--space-5); color: var(--ink-2);
}
.error-box.show { display: flex; flex-direction: column; gap: var(--space-2); align-items: flex-start; }

/* ---------------------------------------------------------------------------
   21. DARK THEME — "the page becomes the plate"
   ----------------------------------------------------------------------------
   The light theme is paper with ink laid on it. The dark theme is not an
   inversion of that; it is the system's own photographic plate (#12161A)
   scaled up until it IS the page. Every relationship from the light theme is
   preserved rather than mirrored:

     · a raised card is lighter than the ground, a sunken well is darker
     · the plate still recedes from the page, so it goes darker again
     · depth is whitespace and 1px rules — no shadows, no glows
     · severity is re-tuned, never merely brightened: each value below is
       measured as text against the dark ground and lands at AA or better

   Only tokens are restated here. Because every rule above resolves colour
   through var(), no component selector needs a dark variant.

   Applied via [data-theme="dark"], stamped on <html> by the inline script in
   index.html before first paint. With JavaScript off the page stays light,
   which is a legible default rather than a broken one.
   ------------------------------------------------------------------------ */
:root[data-theme="dark"] {
  color-scheme: dark;

  /* Surfaces — card rises, well sinks, plate recedes furthest */
  --paper:            #12161A;
  --surface-card:     #191E24;
  --surface-well:     #0D1114;
  --surface-plate:    #080B0D;
  --surface-plate-2:  #14181D;

  /* Ink, measured against the #12161A ground */
  --ink-1: #E7EAEA;              /* primary    15.2:1 */
  --ink-2: #B0B7B9;              /* secondary   8.8:1 */
  --ink-3: #868E90;              /* tertiary    5.3:1 */
  --ink-on-plate:     #E7EAEA;   /* plate is still dark — unchanged */
  --ink-on-plate-dim: #98A0A2;

  /* Rules */
  --rule:        #262C31;
  --rule-strong: #3B4349;
  --rule-plate:  #1E242A;

  /* Accent — the same petrol, lifted until it carries on a dark ground */
  --accent:       #4FB3AC;       /* 7.2:1 */
  --accent-hover: #6FC9C2;
  --accent-soft:  #12302E;
  --accent-ink:   #08201E;       /* dark ink on the solid accent */

  /* Severity — re-measured as text on #12161A, all AA or better */
  --sev-quiet:        #98A1A5;   /* 6.7:1 */
  --sev-quiet-soft:   #1C2226;
  --sev-c:            #6FADDE;   /* 7.5:1 */
  --sev-c-soft:       #14212C;
  --sev-m:            #E09A4A;   /* 7.6:1 */
  --sev-m-soft:       #291E12;
  --sev-x:            #F1786F;   /* 6.6:1 */
  --sev-x-soft:       #2B1614;
  --sev-extreme:      #CE92C6;   /* 7.3:1 */
  --sev-extreme-soft: #241823;

  --sev-ok:      #8FBE90;   /* 8.5:1 */
  --sev-ok-soft: #16241A;

  /* The plate severity set is what the map canvas draws onto a dark field.
     That field is dark in BOTH themes, so these do not change. */

  /* Chart palette — same five hues, lifted with the accent */
  --series-1: #6FADDE;
  --series-2: #4FB3AC;
  --series-3: #8FBE90;
  --series-4: #E09A4A;
  --series-5: #B79AD8;
  --series-muted: #6E7679;
  --chart-grid: #20262B;
  --chart-axis: #3B4349;
  --chart-plot: #191E24;

  /* Focus */
  --focus-ring: #6FADDE;

  /* Ambient values invert: the swatch hairline and the skeleton sweep are now
     light-on-dark instead of dark-on-light. */
  --swatch-edge: rgba(231, 234, 234, 0.28);
  --skel-sweep:  rgba(231, 234, 234, 0.10);

  /* The one shadow in the system — a contact edge under the plate mat. */
  --shadow-plate: 0 1px 0 0 rgba(0, 0, 0, 0.55);
}

/* ---------------------------------------------------------------------------
   22. THEME TOGGLE
   The masthead control. Icon-only, sized to sit level with Refresh. The two
   glyphs are stacked in one button and swapped by the theme attribute, so the
   button always shows the mode it will switch TO.
   ------------------------------------------------------------------------ */
button.btn.theme-toggle { padding: 7px 9px; }
.theme-toggle .ti-moon { display: none; }
.theme-toggle .ti-sun  { display: block; }
:root[data-theme="dark"] .theme-toggle .ti-moon { display: block; }
:root[data-theme="dark"] .theme-toggle .ti-sun  { display: none; }

/* Theme switching must be instantaneous.

   Two reasons. The design reason: a theme change is a change of ground, not a
   state change on a control — cross-fading every surface for 140ms reads as a
   glitch, and this system's motion is meant to be short and purposeful.

   The mechanical reason: several controls transition background-color, and that
   colour comes from a custom property. When the property itself changes, the
   in-flight interpolation keeps the OLD resolved colour and the element gets
   stuck on the previous theme's value. Suppressing transitions for the frame in
   which the attribute flips sidesteps the interpolation entirely. */
:root.theme-switching,
:root.theme-switching *,
:root.theme-switching *::before,
:root.theme-switching *::after {
  transition: none !important;
}


/* ---------------------------------------------------------------
   Storm forecast banner — the geomagnetic-storm probability, shown
   prominently on the map itself (visible in both 2D and 3D modes).
   Tier colours track probability; a freshness chip is always shown so
   a cached/stale solar-wind read can never masquerade as live.
   --------------------------------------------------------------- */
.storm-banner {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
  border: 1px solid var(--border);
  border-left-width: 4px;
  border-radius: var(--radius-3);
  background: var(--surface-well);
}
.storm-banner[hidden] { display: none; }
.storm-banner .sb-pct {
  font-family: var(--font-mono); font-size: 30px; line-height: 1;
  font-weight: 600; letter-spacing: -0.02em; white-space: nowrap;
}
.storm-banner .sb-body { flex: 1; min-width: 0; }
.storm-banner .sb-head { font-size: 14px; font-weight: 600; color: var(--text); }
.storm-banner .sb-sub  { font-size: 12px; color: var(--text-dim); margin-top: 2px; }
.storm-banner .sb-side {
  display: flex; flex-direction: column; align-items: flex-end;
  gap: var(--space-1); white-space: nowrap;
}
.storm-banner .sb-chip {
  font-family: var(--font-mono); font-size: 11px;
  padding: 2px 6px; border-radius: var(--radius-2);
  border: 1px solid var(--border); color: var(--text-dim);
}
.storm-banner .sb-chip.stale { color: var(--sev-m); border-color: var(--sev-m); background: var(--sev-m-soft); }
.storm-banner .sb-chip.live  { color: var(--sev-ok); border-color: var(--sev-ok); background: var(--sev-ok-soft); }

.storm-banner.tier-quiet { border-left-color: var(--sev-quiet); }
.storm-banner.tier-quiet .sb-pct { color: var(--sev-quiet); }
.storm-banner.tier-mod   { border-left-color: var(--sev-c); background: var(--sev-c-soft); }
.storm-banner.tier-mod   .sb-pct { color: var(--sev-c); }
.storm-banner.tier-elev  { border-left-color: var(--sev-m); background: var(--sev-m-soft); }
.storm-banner.tier-elev  .sb-pct { color: var(--sev-m); }
.storm-banner.tier-sev   { border-left-color: var(--sev-x); background: var(--sev-x-soft); }
.storm-banner.tier-sev   .sb-pct { color: var(--sev-x); }
.storm-banner.tier-na    { border-left-color: var(--sev-quiet); }
.storm-banner.tier-na    .sb-pct { color: var(--text-faint); }

@media (max-width: 620px) {
  .storm-banner { flex-wrap: wrap; gap: var(--space-2); }
  .storm-banner .sb-side { align-items: flex-start; width: 100%; flex-direction: row; }
}


/* HF-blackout colour bar in the map legend. Gradient stops sit at the TRUE
   position of each HAF_STOPS value on a 3..40 MHz axis, so the bar is the
   ramp the map actually draws -- including the magenta top end, which the old
   three-swatch legend omitted entirely. */
.map-legend .hf-scale { display: inline-flex; align-items: center; gap: var(--space-2); }
.map-legend .hf-bar {
  position: relative; display: inline-block; width: 132px; height: 11px;
  margin-bottom: 9px;   /* room for the tick labels underneath */
}
.map-legend .hf-bar > i {
  position: absolute; inset: 0; border: 1px solid var(--swatch-edge);
  background: linear-gradient(90deg,
    rgb(245,197,66) 0%, rgb(245,197,66) 8.1%, rgb(255,160,60) 24.3%,
    rgb(255,120,60) 45.9%, rgb(255,77,94) 73%, rgb(255,43,208) 100%);
}
.map-legend .hf-bar > em {
  position: absolute; top: 12px; transform: translateX(-50%);
  font-style: normal; font-family: var(--font-mono); font-size: 9px;
  color: var(--ink-3); white-space: nowrap;
}
.map-legend .hf-bar > em:first-of-type  { transform: none; }
.map-legend .hf-bar > em:last-of-type   { transform: translateX(-100%); }
