/* StratumTap — single stylesheet. No build step, no external fonts.
   Light is the base; dark is a selected set of steps, not an inversion.
   Palette steps come from a validated categorical/status palette (see the
   constellation table in js/components/skyplot.js for the per-GNSS mapping). */

:root {
  color-scheme: light;

  /* surfaces & ink */
  --plane:          #f9f9f7;
  --surface:        #fcfcfb;
  --surface-2:      #f2f1ee;
  --surface-sunken: #eeedea;
  --ink:            #0b0b0b;
  --ink-2:          #52514e;
  --ink-muted:      #6f6e69;
  --hairline:       rgba(11, 11, 11, 0.10);
  --hairline-2:     #e1e0d9;
  --axis:           #c3c2b7;

  /* status (fixed, never themed) */
  --good:     #0ca30c;
  --warning:  #fab219;
  --serious:  #ec835a;
  --critical: #d03b3b;
  --good-ink: #006300;

  /* categorical series */
  --series-1: #2a78d6;  /* blue    */
  --series-2: #eb6834;  /* orange  */
  --series-3: #1baf7a;  /* aqua    */
  --series-4: #eda100;  /* amber   */
  --series-5: #e87ba4;  /* magenta */
  --series-6: #008300;  /* green   */
  --series-7: #4a3aa7;  /* violet  */
  --series-8: #e34948;  /* red     */
  --series-gray: #898781;

  --accent: var(--series-1);
  --accent-soft: rgba(42, 120, 214, 0.12);
  --focus: #1f6fd0;

  /* geometry */
  --r-sm: 4px;
  --r: 8px;
  --r-lg: 12px;
  --gap: 12px;
  --pad: 14px;
  --header-h: 52px;

  --shadow: 0 1px 2px rgba(11, 11, 11, 0.06), 0 1px 8px rgba(11, 11, 11, 0.04);

  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}

/* Dark steps: declared under both the OS media query and the explicit stamp so
   the toggle wins in either direction. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --plane:          #0d0d0d;
    --surface:        #1a1a19;
    --surface-2:      #232322;
    --surface-sunken: #131312;
    --ink:            #ffffff;
    --ink-2:          #c3c2b7;
    --ink-muted:      #949289;
    --hairline:       rgba(255, 255, 255, 0.12);
    --hairline-2:     #2c2c2a;
    --axis:           #383835;

    --series-1: #3987e5;
    --series-2: #d95926;
    --series-3: #199e70;
    --series-4: #c98500;
    --series-5: #d55181;
    --series-6: #008300;
    --series-7: #9085e9;
    --series-8: #e66767;
    --series-gray: #898781;

    --good-ink: #0ca30c;
    --accent: var(--series-1);
    --accent-soft: rgba(57, 135, 229, 0.18);
    --focus: #7fb2f5;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 10px rgba(0, 0, 0, 0.35);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --plane:          #0d0d0d;
  --surface:        #1a1a19;
  --surface-2:      #232322;
  --surface-sunken: #131312;
  --ink:            #ffffff;
  --ink-2:          #c3c2b7;
  --ink-muted:      #949289;
  --hairline:       rgba(255, 255, 255, 0.12);
  --hairline-2:     #2c2c2a;
  --axis:           #383835;

  --series-1: #3987e5;
  --series-2: #d95926;
  --series-3: #199e70;
  --series-4: #c98500;
  --series-5: #d55181;
  --series-6: #008300;
  --series-7: #9085e9;
  --series-8: #e66767;
  --series-gray: #898781;

  --good-ink: #0ca30c;
  --accent: var(--series-1);
  --accent-soft: rgba(57, 135, 229, 0.18);
  --focus: #7fb2f5;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 10px rgba(0, 0, 0, 0.35);
}

/* ------------------------------------------------------------------ base */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--plane);
  color: var(--ink);
  font: 400 15px/1.45 var(--sans);
  overflow-x: hidden;           /* the page itself never scrolls sideways */
  overflow-wrap: break-word;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.25; }

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

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

.mono, .num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.muted { color: var(--ink-muted); }
.dim   { color: var(--ink-2); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------- header */

.app-header {
  position: sticky;
  top: 0;
  z-index: 500;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: saturate(180%) blur(8px);
  border-bottom: 1px solid var(--hairline);
}

.header-bar {
  display: flex;
  align-items: center;
  gap: var(--gap);
  padding: 8px 14px;
  min-height: var(--header-h);
  flex-wrap: wrap;
}

.brand { display: flex; align-items: baseline; gap: 8px; margin-right: 4px; min-width: 0; }
.brand h1 { font-size: 15px; letter-spacing: -0.01em; white-space: nowrap; }
.brand .host {
  font-family: var(--mono); font-size: 12px; color: var(--ink-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 14ch;
}

.nav { display: flex; gap: 2px; }
.nav a {
  display: inline-block; padding: 5px 11px; border-radius: 999px;
  font-size: 13px; font-weight: 500; text-decoration: none; color: var(--ink-2);
}
.nav a:hover { background: var(--surface-2); color: var(--ink); }
.nav a[aria-current="page"] { background: var(--accent-soft); color: var(--accent); }

.header-spacer { flex: 1 1 auto; }

.controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }

/* connection indicator */
.conn { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-2); }
.conn .dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--ink-muted); box-shadow: 0 0 0 3px transparent;
}
.conn[data-state="ok"]       .dot { background: var(--good); }
.conn[data-state="degraded"] .dot { background: var(--warning); }
.conn[data-state="failing"]  .dot { background: var(--critical); }
.conn[data-state="failing"]  .dot { animation: pulse 1.6s ease-in-out infinite; }
@keyframes pulse { 50% { box-shadow: 0 0 0 4px rgba(208, 59, 59, 0.25); } }

.refresh-meta {
  font-size: 12px; color: var(--ink-muted); white-space: nowrap;
  /* the "updated N s ago" text changes width every tick; ellipsize it rather
     than letting it push later header items (the settings gear) around */
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
/* the countdown is the first thing to go when the header runs out of room */
@media (max-width: 700px) { .refresh-meta .cd { display: none; } }
/* On wider screens the header is a single right-aligned row, so any width
   change in this text would shove the refresh controls sideways every tick.
   Reserve a constant-width box instead; digits tick in place. */
@media (min-width: 701px) {
  .refresh-meta { width: 34ch; font-variant-numeric: tabular-nums; }
}
.refresh-meta .num { font-size: 12px; }

/* ------------------------------------------------------------- controls */

button, select, input, textarea { font: inherit; color: inherit; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 5px 10px; min-height: 30px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: var(--r);
  font-size: 13px; cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.btn:hover { background: var(--surface-2); }
.btn:active { transform: translateY(0.5px); }
.btn[aria-pressed="true"], .btn.is-on {
  background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--accent);
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-icon { padding: 5px 8px; min-width: 32px; }
.btn-sm { min-height: 26px; padding: 3px 8px; font-size: 12px; }

select.ctl, input.ctl {
  padding: 4px 8px; min-height: 30px;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r); font-size: 13px;
}
input.ctl[type="number"] { width: 11ch; font-family: var(--mono); }

.field { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-2); }
.field > label { white-space: nowrap; }

.switch { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; cursor: pointer; }
.switch input { accent-color: var(--accent); width: 15px; height: 15px; }

/* settings popover for narrow screens */
.settings { position: relative; margin-left: auto; }
.settings > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; min-height: 30px; font-size: 13px;
  border: 1px solid var(--hairline); border-radius: var(--r); background: var(--surface);
}
.settings > summary::-webkit-details-marker { display: none; }
.settings[open] > summary { background: var(--surface-2); }
.settings .popover {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 600;
  min-width: 240px; padding: 12px;
  display: grid; gap: 10px;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--shadow);
}
.settings .popover .field { display: flex; justify-content: space-between; }

/* ---------------------------------------------------------------- layout */

main { padding: var(--gap); max-width: 1600px; margin: 0 auto; }

.grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: 1fr;         /* mobile-first: one column */
  grid-auto-flow: row dense;          /* let narrow cards backfill a short row */
  align-items: start;                 /* cards size to their content, not to the row */
}

@media (min-width: 640px)  { .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1650px) { .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Below the 2-column breakpoint every span collapses to the full single column;
   `span N` against a 1-track grid would otherwise create an implicit column and
   push the body sideways. */
.span-2, .span-3, .span-all { grid-column: 1 / -1; }
@media (min-width: 640px)  { .span-2 { grid-column: span 2; } .span-3 { grid-column: span 2; } }
@media (min-width: 1200px) { .span-3 { grid-column: span 3; } }
@media (min-width: 1650px) { .span-3 { grid-column: span 3; } }
.span-all { grid-column: 1 / -1; }

/* ----------------------------------------------------------------- card */

.card {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: var(--pad);
  box-shadow: var(--shadow);
  min-width: 0;                     /* lets grid children shrink instead of overflowing */
  display: flex; flex-direction: column; gap: 10px;
}

.card > header {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  border-bottom: 1px solid var(--hairline-2);
  padding-bottom: 8px; margin-bottom: 2px;
}
.card > header h2 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-2); }
.card > header .hdr-note { margin-left: auto; font-size: 12px; color: var(--ink-muted); }

.card-banner {
  padding: 7px 10px; border-radius: var(--r);
  background: var(--surface-sunken); border: 1px solid var(--hairline-2);
  color: var(--ink-muted); font-size: 12px;
}
.card-banner.is-error { border-color: color-mix(in srgb, var(--critical) 40%, transparent); }

/* --------------------------------------------------------------- tiles */

.tiles {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.tile {
  padding: 8px 10px; border-radius: var(--r);
  background: var(--surface-sunken); border: 1px solid var(--hairline-2);
  min-width: 0;
}
.tile .label {
  display: block; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--ink-muted); margin-bottom: 3px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.tile .value {
  display: block; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 15px; line-height: 1.2; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tile .sub {
  display: block; font-size: 11px; color: var(--ink-muted); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tile.is-good .value { color: var(--good-ink); }
.tile.is-warn .value { color: var(--ink); }

/* chips: compact DOP-style readouts */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 3px 8px; border-radius: 999px;
  background: var(--surface-sunken); border: 1px solid var(--hairline-2);
  font-size: 12px;
}
.chip b { font-weight: 600; color: var(--ink-muted); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em; }
.chip span { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* pills: status with an icon + label (never color alone) */
.pills { display: flex; flex-wrap: wrap; gap: 8px; }
.pill {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--hairline);
  font-size: 13px; min-width: 0;
}
.pill .mark { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--ink-muted); }
.pill .k { color: var(--ink-muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; }
.pill .v { font-weight: 500; font-variant-numeric: tabular-nums; }
.pill[data-state="good"]     { border-color: color-mix(in srgb, var(--good) 40%, transparent); }
.pill[data-state="good"]     .mark { background: var(--good); }
.pill[data-state="warning"]  { border-color: color-mix(in srgb, var(--warning) 55%, transparent); }
.pill[data-state="warning"]  .mark { background: var(--warning); }
.pill[data-state="critical"] { border-color: color-mix(in srgb, var(--critical) 45%, transparent); }
.pill[data-state="critical"] .mark { background: var(--critical); }

/* -------------------------------------------------------- key/value rows */

.kv { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr); gap: 4px 12px; font-size: 13px; }
.kv dt { color: var(--ink-muted); white-space: nowrap; }
.kv dd { margin: 0; font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right; }
.kv dd .sub { display: block; font-size: 11px; color: var(--ink-muted); font-family: var(--sans); }

/* ------------------------------------------------------------ hero clock */

.hero { align-items: stretch; }
.hero .clock {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: clamp(2.1rem, 11vw, 3.4rem);
  font-weight: 600; letter-spacing: -0.02em; line-height: 1;
  display: flex; align-items: baseline; gap: 2px;
}
.hero .clock .ms { font-size: 0.52em; color: var(--ink-2); font-weight: 500; }
.hero .clock .zone { font-size: 0.28em; color: var(--ink-muted); font-weight: 500; margin-left: 8px; letter-spacing: 0; }
.hero .datestr { font-size: 13px; color: var(--ink-2); }
.hero .localstr { font-size: 13px; color: var(--ink-muted); }
.hero .syncline { font-size: 12.5px; color: var(--ink-2); display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border-radius: 999px; font-size: 11px; font-weight: 500;
  border: 1px solid var(--hairline);
}
.badge[data-kind="corrected"] { color: var(--good-ink); border-color: color-mix(in srgb, var(--good) 45%, transparent); }
.badge[data-kind="raw"] { color: var(--ink-2); }

details.explain { font-size: 12px; color: var(--ink-muted); }
details.explain > summary { cursor: pointer; color: var(--ink-2); }
details.explain p { margin: 6px 0 0; line-height: 1.5; max-width: 62ch; }
details.explain code { font-family: var(--mono); font-size: 11.5px; background: var(--surface-sunken); padding: 1px 4px; border-radius: 3px; }

/* the dominant single number (system offset) */
.hero-figure {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.hero-figure .fig {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: clamp(1.7rem, 7vw, 2.4rem); font-weight: 600; letter-spacing: -0.02em; line-height: 1;
}
.hero-figure .word { font-size: 14px; color: var(--ink-2); }
.hero-figure[data-level="good"]     .fig { color: var(--good-ink); }
.hero-figure[data-level="warning"]  .fig { color: var(--ink); }
.hero-figure[data-level="critical"] .fig { color: var(--critical); }

/* --------------------------------------------------------------- tables */

.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
table.data {
  width: 100%; border-collapse: collapse; font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
table.data th, table.data td { padding: 5px 8px; text-align: right; white-space: nowrap; }
table.data th:first-child, table.data td:first-child,
table.data th.txt, table.data td.txt { text-align: left; }
table.data thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface); color: var(--ink-muted);
  font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  border-bottom: 1px solid var(--hairline-2);
}
table.data thead th button {
  all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
  font: inherit; color: inherit;
}
table.data thead th button:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
table.data thead th[aria-sort] button { color: var(--ink); }
table.data tbody tr { border-bottom: 1px solid var(--hairline-2); }
table.data tbody tr:last-child { border-bottom: 0; }
table.data tbody tr:hover { background: var(--surface-2); }
table.data tbody tr.is-used td { font-weight: 500; }
table.data tbody tr:not(.is-used) td { color: var(--ink-2); }
table.data td.num { font-family: var(--mono); }

.sat-swatch {
  display: inline-block; width: 9px; height: 9px; border-radius: 2px;
  margin-right: 6px; vertical-align: -1px;
}

/* inline SNR bar inside a table cell */
.snrcell { display: flex; align-items: center; gap: 6px; justify-content: flex-end; }
.snrcell .bar { width: 46px; height: 6px; border-radius: 3px; background: var(--surface-sunken); overflow: hidden; flex: none; }
.snrcell .bar i { display: block; height: 100%; border-radius: 3px; background: var(--series-1); }

/* ------------------------------------------------------- satellite bars */

.satbars { display: grid; gap: 3px; }
.satbar { display: grid; grid-template-columns: 4.5em minmax(0, 1fr) 3.6em; align-items: center; gap: 8px; font-size: 12px; }
.satbar .who { display: flex; align-items: center; gap: 5px; font-family: var(--mono); color: var(--ink-2); }
.satbar .track { height: 9px; border-radius: 3px; background: var(--surface-sunken); position: relative; overflow: hidden; }
.satbar .fill { position: absolute; inset: 0 auto 0 0; border-radius: 3px; }
/* unused satellites read as outline + hatch, so "used" never rests on color alone */
.satbar .fill.unused {
  background-image: repeating-linear-gradient(135deg,
    currentColor 0 2px, transparent 2px 5px);
  background-color: transparent;
  box-shadow: inset 0 0 0 1px currentColor;
  opacity: 0.85;
}
.satbar .val { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink-2); }

.legend { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 11.5px; color: var(--ink-2); }
.legend .item { display: inline-flex; align-items: center; gap: 5px; }
.legend .sw { width: 9px; height: 9px; border-radius: 2px; flex: none; }

/* ---------------------------------------------------------------- map */

.map-holder { position: relative; border-radius: var(--r); overflow: hidden; border: 1px solid var(--hairline-2); }
#map, .leaflet-holder { height: 320px; width: 100%; background: var(--surface-sunken); }
@media (min-width: 1024px) { .leaflet-holder { height: 440px; } }
.map-notice {
  position: absolute; left: 8px; bottom: 8px; z-index: 450;
  padding: 5px 10px; border-radius: var(--r); font-size: 12px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  border: 1px solid var(--hairline); color: var(--ink-2);
  box-shadow: var(--shadow); max-width: calc(100% - 16px);
}
.leaflet-container { font: inherit; background: var(--surface-sunken); }
.leaflet-container a { color: var(--accent); }
/* keep Leaflet's own chrome legible in dark mode without inverting the tiles */
:root[data-theme="dark"] .leaflet-bar a,
:root[data-theme="dark"] .leaflet-control-attribution,
:root[data-theme="dark"] .leaflet-control-scale-line {
  background: #232322; color: #c3c2b7; border-color: #383835;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .leaflet-bar a,
  :root:not([data-theme="light"]) .leaflet-control-attribution,
  :root:not([data-theme="light"]) .leaflet-control-scale-line {
    background: #232322; color: #c3c2b7; border-color: #383835;
  }
}

/* --------------------------------------------------------------- charts */

.chart {
  position: relative;
  width: 100%;
  min-width: 0;
}
.chart canvas { display: block; width: 100%; height: 120px; }
.chart .chart-head {
  display: flex; align-items: baseline; gap: 8px; margin-bottom: 2px;
  font-size: 12px; color: var(--ink-muted);
}
.chart .chart-head .t { color: var(--ink-2); font-weight: 500; }
.chart .chart-head .cur {
  margin-left: auto; font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink);
}
.chart-tip {
  position: absolute; pointer-events: none; z-index: 5;
  padding: 5px 8px; border-radius: var(--r-sm); font-size: 11.5px;
  background: var(--surface); border: 1px solid var(--hairline);
  box-shadow: var(--shadow); white-space: nowrap;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  opacity: 0; transition: opacity 100ms ease;
}
.chart-tip.on { opacity: 1; }

.seg { display: inline-flex; border: 1px solid var(--hairline); border-radius: var(--r); overflow: hidden; }
.seg button {
  all: unset; cursor: pointer; padding: 4px 10px; font-size: 12px; color: var(--ink-2);
  border-right: 1px solid var(--hairline);
}
.seg button:last-child { border-right: 0; }
.seg button:hover { background: var(--surface-2); }
.seg button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); font-weight: 500; }
.seg button:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* --------------------------------------------------------------- gauge */

.gauge { display: grid; gap: 8px; justify-items: center; }
.gauge svg { width: 100%; max-width: 380px; height: auto; display: block; }
.gauge .readout {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: clamp(1.5rem, 6vw, 2rem); font-weight: 600; line-height: 1;
}
.gauge .readout[data-level="good"] { color: var(--good-ink); }
.gauge .readout[data-level="critical"] { color: var(--critical); }
.gauge .sub { font-size: 12px; color: var(--ink-muted); text-align: center; }

/* ------------------------------------------------------------- sky plot */

.skyplot { display: grid; gap: 8px; }
.skyplot svg { width: 100%; max-width: 460px; margin: 0 auto; height: auto; display: block; }
.sky-ring { fill: none; stroke: var(--hairline-2); stroke-width: 1; }
.sky-disc { fill: var(--surface-sunken); }
.sky-spoke { stroke: var(--hairline-2); stroke-width: 1; }
.sky-label { fill: var(--ink-muted); font-size: 9px; font-family: var(--sans); }
.sky-card { fill: var(--ink-2); font-size: 11px; font-weight: 600; font-family: var(--sans); }
.sky-prn { fill: var(--ink-2); font-size: 11px; font-family: var(--mono); pointer-events: none; }
.sky-sat { stroke-width: 1.5; }

/* --------------------------------------------------------------- misc */

pre.raw {
  margin: 8px 0 0; padding: 10px; border-radius: var(--r);
  background: var(--surface-sunken); border: 1px solid var(--hairline-2);
  font-family: var(--mono); font-size: 11.5px; line-height: 1.45;
  max-height: 380px; overflow: auto; white-space: pre;
}
details.raw-panel { border-top: 1px solid var(--hairline-2); padding-top: 8px; }
details.raw-panel > summary { cursor: pointer; font-size: 13px; color: var(--ink-2); }
details.raw-panel > summary:hover { color: var(--ink); }

.banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 12px; margin-bottom: var(--gap);
  border-radius: var(--r); font-size: 13px;
  background: var(--surface); border: 1px solid color-mix(in srgb, var(--critical) 45%, transparent);
  color: var(--ink);
}
.banner .mark { width: 8px; height: 8px; border-radius: 50%; background: var(--critical); flex: none; }
.banner .grow { flex: 1 1 auto; }

.skeleton {
  border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--surface-sunken) 25%, var(--surface-2) 37%, var(--surface-sunken) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
  color: transparent !important;
  min-height: 1em;
}
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

.rowline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rowline .grow { flex: 1 1 auto; }

.footer-note { padding: 4px 14px 20px; font-size: 11.5px; color: var(--ink-muted); text-align: center; }

/* Screens below 640px: collapse the header's secondary controls. */
.only-wide { display: none; }
@media (min-width: 900px) {
  .only-wide { display: flex; }
  .settings.only-narrow { display: none; }
}

/* Hero band: clock on the left, sync explanation on the right; stacks below
   700px so the clock always gets the full measure. */
.hero-band { display: flex; flex-wrap: wrap; gap: var(--gap) 28px; align-items: flex-start; }
.hero-left { flex: 1 1 320px; min-width: 0; display: grid; gap: 4px; }
.hero-right { flex: 1 1 300px; min-width: 0; display: grid; gap: 8px; align-content: start; }

/* ------------------------------------------------------------- live raw */
/* The streamed console on #/detail. The log scrolls inside its own box in
   both axes — the page never moves. Rows are plain flex lines rather than a
   table so appending a batch costs no layout of the rows already there. */

.rawlog { display: grid; gap: 8px; min-width: 0; }

.rl-controls { gap: 8px 12px; }
.rl-sources { gap: 10px; }
.rl-sep { width: 1px; align-self: stretch; min-height: 22px; background: var(--hairline-2); }
.rl-controls input[type="search"] { width: 18ch; max-width: 100%; }
@media (max-width: 640px) { .rl-sep { display: none; } }

.rl-status { gap: 8px 10px; font-size: 12px; }
.rl-note { font-size: 11.5px; }
.rl-counts { font-size: 11.5px; }

/* state pill: color is always backed by the word next to it */
.rl-pill {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  padding: 3px 11px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--hairline);
  font-size: 12px; text-transform: lowercase;
}
.rl-pill .mark { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--ink-muted); }
.rl-pill[data-state="live"] { border-color: color-mix(in srgb, var(--good) 45%, transparent); color: var(--good-ink); }
.rl-pill[data-state="live"] .mark { background: var(--good); }
.rl-pill[data-state="connecting"] .mark,
.rl-pill[data-state="reconnecting"] .mark { background: var(--warning); }
.rl-pill[data-state="reconnecting"] { border-color: color-mix(in srgb, var(--warning) 55%, transparent); }
.rl-pill[data-state="refused"] { border-color: color-mix(in srgb, var(--critical) 45%, transparent); color: var(--critical); }
.rl-pill[data-state="refused"] .mark { background: var(--critical); }

/* stat + rate chips */
.rl-stats, .rl-rates { gap: 6px; }
.chip.is-warn span { color: var(--serious); font-weight: 600; }
.chip.is-warn { border-color: color-mix(in srgb, var(--warning) 60%, transparent); }
.chip.is-bad span { color: var(--critical); font-weight: 600; }
.chip.is-bad { border-color: color-mix(in srgb, var(--critical) 45%, transparent); }
.chip.is-total { background: var(--surface-2); }

/* the log itself */
.rl-log {
  max-height: 420px; min-height: 120px;
  overflow: auto; overscroll-behavior: contain;
  padding: 6px 8px; border-radius: var(--r);
  background: var(--surface-sunken); border: 1px solid var(--hairline-2);
  font-family: var(--mono); font-size: 11.5px; line-height: 1.5;
  contain: content;                 /* rows never reflow the rest of the card */
}
.rl-log:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }

.rl-row {
  display: flex; align-items: baseline; gap: 8px;
  width: max-content; min-width: 100%;
  white-space: pre; padding: 0 2px; border-radius: 2px;
}
.rl-row:hover { background: var(--surface-2); }
.rl-t { flex: none; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.rl-b {
  flex: none; padding: 0 5px; border-radius: 3px;
  font-size: 9.5px; letter-spacing: 0.04em; line-height: 1.6;
  border: 1px solid var(--hairline-2); color: var(--ink-muted); background: var(--surface);
}
.rl-row[data-kind="nmea"] .rl-b { color: var(--series-1); border-color: color-mix(in srgb, var(--series-1) 45%, transparent); }
.rl-row[data-kind="gpsd"] .rl-b { color: var(--series-3); border-color: color-mix(in srgb, var(--series-3) 45%, transparent); }
.rl-row[data-kind="ntp"]  .rl-b { color: var(--series-7); border-color: color-mix(in srgb, var(--series-7) 45%, transparent); }
.rl-tag { flex: none; color: var(--ink-2); font-weight: 600; }
.rl-l { flex: 1 1 auto; min-width: 0; color: var(--ink); }
.rl-row.is-bad { background: color-mix(in srgb, var(--critical) 14%, transparent); }
.rl-row.is-bad .rl-l { color: var(--critical); }

.rl-empty {
  padding: 12px 4px; font-family: var(--sans); font-size: 12px; white-space: normal;
}

.rl-save { gap: 8px; }
