/* ═══════════════════════════════════════════════════════════════
   MRT Jakarta — Integrated Operations Display
   Design tokens: dark control-room surface, validated palette.
   Categorical + status hexes are validated via dataviz
   scripts/validate_palette.js against surface #10141a (dark).
   ═══════════════════════════════════════════════════════════════ */

:root {
  /* — surfaces (layered, cool near-black) — */
  --plane:      #080a0d;
  --surface-1:  #10141a;   /* validated chart surface */
  --surface-2:  #171d26;
  --surface-3:  #1e2630;
  --hairline:   rgba(255,255,255,.075);
  --hairline-2: rgba(255,255,255,.13);

  /* — ink — */
  --ink:        #eef2f7;
  --ink-2:      #9dabbb;
  --ink-3:      #6b7b8c;

  /* — categorical (validated all-pairs, dark) — */
  --accent:     #3987e5;   /* North–South Line / live train */
  --accent-2:   #d55181;   /* East–West Line (future view) */

  /* — status (reserved; always ships with glyph + label) — */
  --good:       #0ca30c;
  --warn:       #fab219;
  --serious:    #ec835a;
  --critical:   #d03b3b;

  /* — sequential blue ramp (magnitude) — */
  --seq-1: #184f95; --seq-2: #256abf; --seq-3: #3987e5;
  --seq-4: #6da7ec; --seq-5: #9ec5f4;

  --grid:       var(--tint-2);
  --radius:     10px;

  /* — neutral tint scale (surfaces lifted off the plane) — */
  --tint-1: rgba(255,255,255,.022);
  --tint-2: rgba(255,255,255,.05);
  --tint-3: rgba(255,255,255,.12);
  --tint-4: rgba(255,255,255,.2);
  --tint-5: rgba(255,255,255,.34);

  /* — roles that invert oppositely between themes — */
  --fg-max:     #ffffff;   /* maximum contrast against the surface */
  --on-accent:  #04070c;   /* text sitting on a saturated fill */
  --halo:       #10141a;   /* knockout stroke separating a dot from what's under it */

  --seg-bg:     rgba(0,0,0,.28);
  --shadow:     rgba(0,0,0,.5);
  --scrim:      rgba(8,10,13,.72);
  --toast-good-bg: rgba(7,20,7,.93);
  --toast-warn-bg: rgba(22,17,6,.93);
  --toast-crit-bg: rgba(20,10,12,.93);

  /* status used as TEXT needs its own step — the fill hexes are too
     saturated to read as type on either surface */
  --good-ink:     #7fe07f;
  --warn-ink:     #ffd677;
  --serious-ink:  #ffb694;
  --critical-ink: #ffb3b3;

  /* — map/diagram colours the SVG layers read at draw time — */
  --grid-line:      rgba(255,255,255,.03);
  --tunnel:         rgba(255,255,255,.22);
  --tunnel-under:   rgba(255,255,255,.10);
  --compass-fill:   rgba(8,10,13,.55);
  --compass-stroke: rgba(255,255,255,.13);
  --track-idle:     rgba(255,255,255,.4);
  --fleet-standby:  #6da7ec;
  --fleet-maint:    #4a5563;
  --fleet-maint-ink:#c3c2b7;

  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
  --sans: system-ui, -apple-system, "Segoe UI", sans-serif;
}


/* ═══════════════════════════════════════════════════════════════
   LIGHT THEME — a selected palette, not an inversion.

   Reusing the dark status hexes on a light surface fails contrast
   outright (warn #fab219 → 1.71:1, serious #ec835a → 2.46:1
   against #f5f7fa), so both accents, all four status steps and the
   sequential ramp carry their own values. Everything below was
   checked with the dataviz validator against surface #f5f7fa:
     · categorical #1f6fd0 / #c0396e — all-pairs CVD ΔE 16.0
       (protan), normal-vision 27.2, contrast ≥ 3:1
     · sequential ramp — monotone, adjacent ΔL ≥ 0.06,
       light-end contrast 2.28:1
     · status fills — good 5.09:1, warn 4.14:1, serious 4.24:1,
       critical 5.52:1
   ═══════════════════════════════════════════════════════════════ */
:root[data-theme="light"] {
  --plane:      #e9edf3;
  --surface-1:  #f5f7fa;   /* validated chart surface */
  --surface-2:  #ffffff;
  --surface-3:  #eaeff5;
  --hairline:   rgba(16,26,42,.10);
  --hairline-2: rgba(16,26,42,.17);

  --ink:        #0f1620;
  --ink-2:      #46566b;
  --ink-3:      #6a7a8d;

  --accent:     #1f6fd0;
  --accent-2:   #c0396e;

  --good:       #0e7a2e;
  --warn:       #a86a00;
  --serious:    #c2551f;
  --critical:   #c02626;

  /* magnitude now reads darker, so the ramp runs light → dark */
  --seq-1: #7aa9e2; --seq-2: #5589d3; --seq-3: #3a6ec0;
  --seq-4: #28518f; --seq-5: #1a3a68;

  --grid:       rgba(16,26,42,.055);

  --tint-1: rgba(16,26,42,.030);
  --tint-2: rgba(16,26,42,.055);
  --tint-3: rgba(16,26,42,.13);
  --tint-4: rgba(16,26,42,.24);
  --tint-5: rgba(16,26,42,.38);

  --fg-max:     #0f1620;
  --on-accent:  #ffffff;
  --halo:       #ffffff;

  --seg-bg:     rgba(16,26,42,.05);
  --shadow:     rgba(16,26,42,.16);
  --scrim:      rgba(233,237,243,.80);
  --toast-good-bg: #eef7f0;
  --toast-warn-bg: #fbf4e6;
  --toast-crit-bg: #fdeeee;

  --good-ink:     #0b5f24;
  --warn-ink:     #7d4f00;
  --serious-ink:  #963f16;
  --critical-ink: #961d1d;

  --grid-line:      rgba(16,26,42,.05);
  --tunnel:         rgba(16,26,42,.28);
  --tunnel-under:   rgba(16,26,42,.13);
  --compass-fill:   rgba(255,255,255,.78);
  --compass-stroke: rgba(16,26,42,.16);
  --track-idle:     rgba(16,26,42,.42);
  --fleet-standby:  #5589d3;
  --fleet-maint:    #b3bfcd;
  --fleet-maint-ink:#2b3644;
}

/* The depth wash is tuned for a dark plane; on light it muddies the
   surface, so it is dialled back rather than removed. */
:root[data-theme="light"] body::before { opacity: .5; }

* { box-sizing: border-box; }

html, body {
  height: 100%; margin: 0;
  background: var(--plane);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

/* soft depth wash — the only decorative gradient in the build */
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(1100px 620px at 42% 32%, color-mix(in srgb, var(--accent) 7.5%, transparent), transparent 70%),
    radial-gradient(760px 520px at 88% 88%, color-mix(in srgb, var(--accent-2) 4.5%, transparent), transparent 72%);
}

/* ══════════ LAYOUT ══════════ */
.app {
  position: relative; z-index: 1;
  display: grid; height: 100vh; gap: 9px; padding: 9px;
  grid-template-columns: 264px minmax(0,1fr) 290px 374px;
  grid-template-rows: 58px minmax(200px,1fr) 150px 188px;
  grid-template-areas:
    "hdr  hdr  hdr  hdr"
    "rail map  stn  detail"
    "rail trk  trk  detail"
    "rail str  str  detail";
}

/* shared panel chrome */
.panel, .rail, .detail, .hdr {
  background: linear-gradient(180deg, var(--surface-2), var(--surface-1) 62%);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  position: relative;
  min-width: 0; min-height: 0;
}

/* corner brackets — control-room motif, 1px and quiet */
.panel::before, .panel::after {
  content: ""; position: absolute; width: 11px; height: 11px; pointer-events: none;
  border-color: var(--hairline-2); border-style: solid; border-width: 0;
}
.panel::before { top: -1px; left: -1px; border-top-width: 1px; border-left-width: 1px; border-top-left-radius: var(--radius); }
.panel::after  { bottom: -1px; right: -1px; border-bottom-width: 1px; border-right-width: 1px; border-bottom-right-radius: var(--radius); }

.panel { display: flex; flex-direction: column; overflow: hidden; }

.panel__hd {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 9px 13px 7px; border-bottom: 1px solid var(--hairline); flex: none;
}
.panel__t {
  margin: 0; font-size: 11px; font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink);
}
.panel__meta {
  font-size: 10px; letter-spacing: .07em; color: var(--ink-3);
  font-family: var(--mono); white-space: nowrap;
}

/* ══════════ HEADER ══════════ */
.hdr {
  grid-area: hdr; display: flex; align-items: center; gap: 20px; padding: 0 16px;
}
.hdr__id { display: flex; align-items: center; gap: 11px; min-width: 0; }
.hdr__mark { display: grid; place-items: center; flex: none; }
.hdr__mark svg { animation: slowspin 24s linear infinite; }
@keyframes slowspin { to { transform: rotate(360deg); } }
.hdr__title {
  font-size: 13px; font-weight: 600; letter-spacing: .05em; white-space: nowrap;
}
.hdr__sub {
  display: flex; align-items: center; gap: 9px; margin-top: 2px;
  font-size: 9.5px; letter-spacing: .08em; color: var(--ink-3); font-family: var(--mono);
  white-space: nowrap;
}
.hdr__demo {
  color: var(--warn); border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
  border-radius: 3px; padding: 1px 5px; letter-spacing: .12em; font-size: 8.5px;
}

.hdr__status {
  display: flex; align-items: center; gap: 8px; margin-left: auto;
  padding: 6px 13px; border-radius: 999px;
  border: 1px solid var(--hairline-2); background: var(--tint-1);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em;
}
.hdr__status .dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--good);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--good) 16%, transparent); animation: pulse 2.6s ease-in-out infinite;
}
.hdr__status.is-alarm .dot { background: var(--critical); box-shadow: 0 0 0 3px color-mix(in srgb, var(--critical) 20%, transparent); animation-duration: 1s; }
.hdr__status.is-alarm { border-color: color-mix(in srgb, var(--critical) 45%, transparent); color: var(--critical-ink); }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

.hdr__clock { text-align: right; font-family: var(--mono); flex: none; }
.clock__time { font-size: 21px; font-weight: 500; letter-spacing: .04em; line-height: 1; }
.clock__meta { font-size: 9px; color: var(--ink-3); margin-top: 3px; letter-spacing: .06em; }

.hdr__ctl { display: flex; align-items: center; gap: 7px; flex: none; }

.seg {
  display: flex; border: 1px solid var(--hairline-2); border-radius: 7px;
  overflow: hidden; background: var(--seg-bg);
}
.seg__b {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  color: var(--ink-3); font-family: var(--mono); font-size: 10px; letter-spacing: .09em;
  padding: 6px 10px; transition: background .16s, color .16s;
}
.seg__b + .seg__b { border-left: 1px solid var(--hairline); }
.seg__b:hover { color: var(--ink); background: var(--tint-2); }
.seg__b.is-on { color: var(--fg-max); background: color-mix(in srgb, var(--accent) 24%, transparent); box-shadow: inset 0 -2px 0 var(--accent); }

.btn {
  appearance: none; cursor: pointer; display: flex; align-items: center; gap: 7px;
  border-radius: 7px; padding: 7px 13px; font-family: var(--mono);
  font-size: 10px; letter-spacing: .1em; transition: .16s;
  border: 1px solid color-mix(in srgb, var(--critical) 42%, transparent); background: color-mix(in srgb, var(--critical) 12%, transparent); color: var(--critical-ink);
}
.btn:hover { background: color-mix(in srgb, var(--critical) 24%, transparent); color: var(--fg-max); border-color: var(--critical); }
.btn:disabled { opacity: .35; cursor: not-allowed; }
.btn__glyph { font-size: 9px; }

/* ══════════ LEFT RAIL ══════════ */
.rail {
  grid-area: rail; padding: 11px 12px; overflow-y: auto; overflow-x: hidden;
  display: flex; flex-direction: column;
}
.rail__hd {
  font-size: 9.5px; letter-spacing: .17em; color: var(--ink-3);
  font-family: var(--mono); padding-bottom: 7px; margin-bottom: 9px;
  border-bottom: 1px solid var(--hairline); flex: none;
}
.rail__hd--mt { margin-top: 15px; }

/* hero figure — exactly one per view */
.hero { flex: none; margin-bottom: 13px; }
.hero__lab { font-size: 10px; color: var(--ink-2); letter-spacing: .03em; }
.hero__val {
  font-size: 41px; font-weight: 600; line-height: 1.04; margin-top: 2px;
  letter-spacing: -.018em; font-variant-numeric: proportional-nums;
}
.hero__spark { height: 30px; margin: 5px 0 3px; overflow: hidden; }
.hero__spark svg { width: 100%; height: 30px; display: block; }
.hero__foot { font-size: 9.5px; color: var(--ink-3); font-family: var(--mono); letter-spacing: .04em; }

.tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; flex: none; }
.tile {
  background: var(--tint-1); border: 1px solid var(--hairline);
  border-radius: 8px; padding: 8px 9px;
}
.tile__lab {
  font-size: 8.5px; letter-spacing: .1em; color: var(--ink-3);
  text-transform: uppercase; line-height: 1.35; min-height: 22px;
}
.tile__val {
  font-size: 19px; font-weight: 600; margin-top: 2px; letter-spacing: -.01em;
  display: flex; align-items: baseline; gap: 3px;
}
.tile__unit { font-size: 9.5px; color: var(--ink-3); font-weight: 400; font-family: var(--mono); }
.tile__sub {
  font-size: 9px; font-family: var(--mono); color: var(--ink-3); margin-top: 3px;
  display: flex; align-items: center; gap: 4px;
}
.tile.is-good .tile__val { color: var(--good); }
.tile.is-warn .tile__val { color: var(--warn); }
.tile.is-serious .tile__val { color: var(--serious); }
.tile.is-critical .tile__val { color: var(--critical); }

/* fleet disposition — stacked bar, 2px surface gaps */
.fleetbar { display: flex; height: 26px; gap: 2px; flex: none; }
.fleetbar span {
  border-radius: 2px; transition: flex-grow .5s ease;
  display: grid; place-items: center; font-family: var(--mono); font-size: 9.5px;
  color: var(--on-accent); font-weight: 700;
}
.fleetlegend {
  display: flex; flex-direction: column; gap: 4px; margin-top: 8px; flex: none;
  font-size: 9.5px; font-family: var(--mono); color: var(--ink-2);
}
.fleetlegend div { display: flex; align-items: center; gap: 6px; }
.fleetlegend i { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.fleetlegend b { margin-left: auto; color: var(--ink); font-weight: 500; }

.energy { display: flex; flex-direction: column; gap: 7px; flex: none; }
.erow { font-size: 9.5px; font-family: var(--mono); color: var(--ink-2); }
.erow__top { display: flex; justify-content: space-between; margin-bottom: 4px; }
.erow__top b { color: var(--ink); font-weight: 500; }
.meter { height: 4px; border-radius: 2px; background: color-mix(in srgb, var(--accent) 16%, transparent); overflow: hidden; }
.meter i { display: block; height: 100%; border-radius: 2px; background: var(--accent); transition: width .5s ease; }

/* alert + predictive-flag log */
.alog { display: flex; flex-direction: column; gap: 5px; flex: none; padding-bottom: 6px; }
.alog__r {
  display: grid; grid-template-columns: 13px 1fr; gap: 7px; align-items: start;
  padding: 6px 8px; border-radius: 6px; cursor: pointer;
  background: var(--tint-1); border: 1px solid var(--hairline);
  transition: background .15s, border-color .15s;
}
.alog__r:hover { background: var(--tint-2); border-color: var(--hairline-2); }
.alog__g { font-size: 9px; line-height: 1.5; text-align: center; }
.alog__set { font-family: var(--mono); font-size: 9.5px; color: var(--ink); letter-spacing: .04em; }
.alog__b { font-size: 9.5px; color: var(--ink-3); line-height: 1.4; margin-top: 1px; }
.alog__r.is-critical { border-color: color-mix(in srgb, var(--critical) 42%, transparent); background: color-mix(in srgb, var(--critical) 9%, transparent); }
.alog__r.is-serious  { border-color: color-mix(in srgb, var(--serious) 34%, transparent); background: color-mix(in srgb, var(--serious) 7%, transparent); }
.alog__r.is-warn     { border-color: color-mix(in srgb, var(--warn) 30%, transparent);  background: color-mix(in srgb, var(--warn) 6%, transparent); }
.alog__none { font-family: var(--mono); font-size: 9.5px; color: var(--ink-3); padding: 4px 2px; }

/* ══════════ MAP ══════════ */
.panel--map { grid-area: map; }
.map__wrap { position: relative; flex: 1; min-height: 0; }
.map__svg { position: absolute; inset: 0; width: 100%; height: 100%; }

.map__legend {
  position: absolute; left: 12px; bottom: 11px; display: flex; flex-direction: column; gap: 5px;
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-2);
  background: var(--scrim); border: 1px solid var(--hairline);
  border-radius: 7px; padding: 8px 10px; backdrop-filter: blur(7px);
}
.map__legend div { display: flex; align-items: center; gap: 7px; white-space: nowrap; }
.map__legend i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.map__legend .ln { width: 15px; height: 2.5px; border-radius: 2px; }
.map__scale {
  position: absolute; right: 12px; bottom: 11px;
  font-family: var(--mono); font-size: 9px; color: var(--ink-3); letter-spacing: .06em;
}

/* map atoms */
.stn-dot { fill: var(--surface-1); stroke: var(--ink-2); stroke-width: 1.4; }
.stn-dot--int { stroke: var(--ink); stroke-width: 2; }
.stn-lab { font-family: var(--sans); font-size: 8.5px; fill: var(--ink-2); letter-spacing: .02em; }
.stn-code { font-family: var(--mono); font-size: 7.5px; fill: var(--ink-3); }

.trainG { cursor: pointer; }
.trainG .body { fill: var(--accent); stroke: var(--surface-1); stroke-width: 2; }
.trainG .halo { fill: var(--accent); opacity: .17; }
.trainG:hover .halo { opacity: .32; }
.trainG.is-sel .body { fill: var(--fg-max); }
.trainG.is-sel .ring { stroke: var(--fg-max); }
.trainG.is-alarm .body { fill: var(--critical); }
.trainG.is-alarm .halo { fill: var(--critical); opacity: .3; }
.trainG.is-warn .body { fill: var(--warn); }
.trainG.is-warn .halo { fill: var(--warn); opacity: .26; }
.trainG .lbl { font-family: var(--mono); font-size: 7.5px; fill: var(--ink); pointer-events: none; }

/* ══════════ STATION LIST ══════════ */
.panel--stn { grid-area: stn; }
.stnlist { flex: 1; overflow-y: auto; padding: 5px 9px 9px; }
.srow {
  display: grid; grid-template-columns: 30px 1fr 40px; align-items: center;
  gap: 8px; padding: 4px 3px; border-bottom: 1px solid var(--tint-2);
}
.srow__code { font-family: var(--mono); font-size: 9px; color: var(--ink-3); }
.srow__name { font-size: 10px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.srow__bar { height: 5px; border-radius: 3px; background: var(--tint-2); overflow: hidden; margin-top: 3px; }
.srow__bar i { display: block; height: 100%; border-radius: 3px; transition: width .6s ease, background .3s; }
.srow__n { font-family: var(--mono); font-size: 9.5px; color: var(--ink-2); text-align: right; font-variant-numeric: tabular-nums; }
.srow.is-hot .srow__name { color: var(--ink); }

/* ══════════ TRACK SCHEMATIC + STRING ══════════ */
.panel--trk { grid-area: trk; }
.panel--str { grid-area: str; }
.trk__svg, .str__svg { flex: 1; width: 100%; min-height: 0; display: block; }

.trk-rail { stroke: var(--tint-3); stroke-width: 2.5; }
.trk-tick { stroke: var(--tint-3); stroke-width: 1; }
.trk-lab  { font-family: var(--mono); font-size: 7.5px; fill: var(--ink-3); }
.trk-dir  { font-family: var(--mono); font-size: 8px; fill: var(--ink-3); letter-spacing: .1em; }
.trk-tunnel { fill: var(--tint-1); }
.trk-tunlab { font-family: var(--mono); font-size: 7.5px; fill: var(--ink-3); letter-spacing: .08em; }

.str-line { fill: none; stroke: var(--accent); stroke-width: 1.35; opacity: .5; stroke-linecap: round; }
.str-line.is-sel { stroke: var(--fg-max); opacity: 1; stroke-width: 2; }
.str-line.is-alarm { stroke: var(--critical); opacity: .95; stroke-width: 2; }
.str-grid { stroke: var(--grid); stroke-width: 1; }
.str-axis { font-family: var(--mono); font-size: 7.5px; fill: var(--ink-3); }
.str-now { stroke: var(--tint-5); stroke-width: 1; stroke-dasharray: 2 3; }

/* ══════════ DETAIL PANEL ══════════ */
.detail {
  grid-area: detail; overflow-y: auto; overflow-x: hidden;
  display: flex; flex-direction: column;
}
.detail__empty[hidden], .detail__body[hidden] { display: none !important; }
.detail__empty {
  margin: auto; text-align: center; color: var(--ink-3); padding: 26px 20px;
  display: flex; flex-direction: column; align-items: center; gap: 11px;
}
.detail__empty p { margin: 0; font-size: 11.5px; max-width: 190px; line-height: 1.5; }
.detail__emptysub { font-family: var(--mono); font-size: 8.5px; letter-spacing: .1em; opacity: .65; }

.dhd {
  padding: 12px 14px 11px; border-bottom: 1px solid var(--hairline);
  position: sticky; top: 0; z-index: 2;
  background: linear-gradient(180deg, var(--surface-3), var(--surface-2));
}
.dhd__top { display: flex; align-items: center; gap: 9px; }
.dhd__set {
  font-family: var(--mono); font-size: 17px; font-weight: 600; letter-spacing: .04em;
}
.dhd__pill {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .1em; padding: 3px 7px;
  border-radius: 4px; border: 1px solid var(--hairline-2); color: var(--ink-2);
}
.dhd__pill.is-alarm { color: var(--critical-ink); border-color: color-mix(in srgb, var(--critical) 50%, transparent); background: color-mix(in srgb, var(--critical) 14%, transparent); }
.dhd__close {
  margin-left: auto; appearance: none; background: transparent; border: 1px solid var(--hairline-2);
  color: var(--ink-3); border-radius: 5px; width: 22px; height: 22px; cursor: pointer; font-size: 12px;
}
.dhd__close:hover { color: var(--ink); border-color: var(--hairline-2); background: var(--tint-2); }
.dhd__sub {
  margin-top: 6px; font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}

.dsec { padding: 11px 14px 13px; border-bottom: 1px solid var(--hairline); }
.dsec__t {
  font-size: 9px; letter-spacing: .16em; color: var(--ink-3); font-family: var(--mono);
  margin-bottom: 9px; display: flex; align-items: center; gap: 7px;
}
.dsec__t::after { content: ""; flex: 1; height: 1px; background: var(--hairline); }

.kv { display: grid; grid-template-columns: 1fr auto; gap: 5px 10px; }
.kv dt { font-size: 10px; color: var(--ink-3); }
.kv dd {
  margin: 0; font-family: var(--mono); font-size: 11px; color: var(--ink);
  text-align: right; font-variant-numeric: tabular-nums;
}
.kv dd small { color: var(--ink-3); font-size: 9px; }
.kv dd.is-good { color: var(--good); }
.kv dd.is-warn { color: var(--warn); }
.kv dd.is-serious { color: var(--serious); }
.kv dd.is-critical { color: var(--critical); }

/* big readouts */
.readouts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 10px; }
.ro { background: var(--tint-1); border: 1px solid var(--hairline); border-radius: 8px; padding: 8px 10px; }
.ro__l { font-size: 8.5px; letter-spacing: .1em; color: var(--ink-3); text-transform: uppercase; }
.ro__v { font-size: 22px; font-weight: 600; margin-top: 1px; letter-spacing: -.015em; }
.ro__v small { font-size: 10px; color: var(--ink-3); font-weight: 400; font-family: var(--mono); margin-left: 2px; }

/* speed dial */
.dial { display: block; margin: 0 auto 4px; }

/* per-car occupancy */
.cars { display: flex; gap: 2px; align-items: flex-end; height: 78px; margin-bottom: 6px; }
.car { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; height: 100%; justify-content: flex-end; }
.car__track {
  width: 100%; flex: 1; background: color-mix(in srgb, var(--accent) 15%, transparent); border-radius: 3px;
  display: flex; align-items: flex-end; overflow: hidden;
}
.car__fill { width: 100%; border-radius: 3px; transition: height .6s ease, background .3s; }
.car__n { font-family: var(--mono); font-size: 8px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.car__id { font-family: var(--mono); font-size: 7.5px; color: var(--ink-3); }
.car__w { font-family: var(--mono); font-size: 6.5px; color: var(--accent-2); letter-spacing: .04em; }

/* health rows */
.hrow { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.hrow__l { font-size: 10px; color: var(--ink-2); width: 96px; flex: none; }
.hrow__m { flex: 1; height: 4px; border-radius: 2px; background: var(--tint-2); overflow: hidden; }
.hrow__m i { display: block; height: 100%; border-radius: 2px; transition: width .5s ease; }
.hrow__v {
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-2); width: 52px;
  text-align: right; font-variant-numeric: tabular-nums; flex: none;
}

/* status chip — colour NEVER alone: glyph + label always */
.chip {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px;
  border-radius: 999px; font-family: var(--mono); font-size: 9px; letter-spacing: .07em;
  border: 1px solid var(--hairline-2); color: var(--ink-2);
}
.chip__g { font-size: 9px; line-height: 1; }
.chip.is-good     { color: var(--good-ink); border-color: color-mix(in srgb, var(--good) 45%, transparent);  background: color-mix(in srgb, var(--good) 12%, transparent); }
.chip.is-warn     { color: var(--warn-ink); border-color: color-mix(in srgb, var(--warn) 45%, transparent); background: color-mix(in srgb, var(--warn) 12%, transparent); }
.chip.is-serious  { color: var(--serious-ink); border-color: color-mix(in srgb, var(--serious) 45%, transparent); background: color-mix(in srgb, var(--serious) 12%, transparent); }
.chip.is-critical { color: var(--critical-ink); border-color: color-mix(in srgb, var(--critical) 50%, transparent);   background: color-mix(in srgb, var(--critical) 15%, transparent); }

.dsec--rec { background: color-mix(in srgb, var(--warn) 4.5%, transparent); }

/* recommendation block */
.rec {
  background: color-mix(in srgb, var(--warn) 7%, transparent); border: 1px solid color-mix(in srgb, var(--warn) 28%, transparent);
  border-radius: 8px; padding: 10px 11px; margin-top: 4px;
}
.rec__t {
  font-family: var(--mono); font-size: 9px; letter-spacing: .12em; color: var(--warn);
  display: flex; align-items: center; gap: 6px; margin-bottom: 7px;
}
.rec ol { margin: 0; padding-left: 16px; }
.rec li { font-size: 10.5px; color: var(--ink-2); line-height: 1.5; margin-bottom: 4px; }
.rec li b { color: var(--ink); font-family: var(--mono); font-weight: 500; }
.rec__why {
  margin-top: 8px; padding-top: 8px; border-top: 1px solid color-mix(in srgb, var(--warn) 20%, transparent);
  font-size: 9.5px; color: var(--ink-3); line-height: 1.5;
}

/* ══════════ TOASTS ══════════ */
.toasts {
  position: fixed; left: 300px; top: 78px; z-index: 40;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
}
.toast {
  display: flex; align-items: flex-start; gap: 9px; max-width: 340px;
  background: var(--toast-crit-bg); border: 1px solid color-mix(in srgb, var(--critical) 45%, transparent);
  border-left-width: 3px; border-radius: 8px; padding: 10px 13px;
  backdrop-filter: blur(9px); box-shadow: 0 8px 26px var(--shadow);
  animation: toastIn .3s cubic-bezier(.2,.8,.2,1);
}
.toast.is-warn { border-color: color-mix(in srgb, var(--warn) 45%, transparent); background: var(--toast-warn-bg); }
.toast.is-good { border-color: color-mix(in srgb, var(--good) 45%, transparent); background: var(--toast-good-bg); }
.toast__g { font-size: 11px; line-height: 1.3; color: var(--critical); }
.toast.is-warn .toast__g { color: var(--warn); }
.toast.is-good .toast__g { color: var(--good); }
.toast__t { font-family: var(--mono); font-size: 9.5px; letter-spacing: .09em; color: var(--ink); }
.toast__b { font-size: 10.5px; color: var(--ink-2); margin-top: 3px; line-height: 1.45; }
@keyframes toastIn { from { opacity: 0; transform: translateY(-10px); } }

/* ══════════ SCROLLBARS ══════════ */
::-webkit-scrollbar { width: 7px; height: 7px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--tint-3); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--tint-4); }

/* ══════════ RESPONSIVE ══════════ */
@media (max-width: 1700px) {
  .app { grid-template-columns: 234px minmax(0,1fr) 250px 336px; }
  .toasts { left: 268px; }
  .hero__val { font-size: 35px; }
}
@media (max-width: 1450px) {
  .app {
    grid-template-columns: 214px minmax(0,1fr) 316px;
    grid-template-rows: 58px minmax(180px,1fr) 140px 172px;
    grid-template-areas:
      "hdr  hdr  hdr"
      "rail map  detail"
      "rail trk  detail"
      "rail str  detail";
  }
  .panel--stn { display: none; }
  .toasts { left: 248px; }
  .hdr__sub { display: none; }
}
@media (max-width: 1150px) {
  /* overflow:auto alone does nothing while html/body are pinned to
     height:100% — the document cannot grow, so it clips instead of
     scrolling. The clamp has to be released wherever scrolling is on. */
  html, body { overflow: auto; height: auto; min-height: 100%; }
  .app {
    height: auto; grid-template-columns: 1fr;
    grid-template-rows: auto;
    grid-template-areas: "hdr" "map" "rail" "trk" "str" "stn" "detail";
  }
  .panel--stn { display: flex; }
  .panel--map { min-height: 440px; }
  .panel--trk { min-height: 150px; }
  .panel--str { min-height: 190px; }
  .detail { min-height: 300px; }
  .hdr { flex-wrap: wrap; height: auto; padding: 10px 14px; gap: 12px; }
  .toasts { left: 14px; top: auto; bottom: 14px; }
}

/* phones — the wall is a wide-screen display, but the link still has to open
   cleanly on a handset. Nothing may scroll the page sideways. */
@media (max-width: 900px) {
  html, body { overflow-x: hidden; }
  .app { padding: 7px; gap: 7px; width: 100%; max-width: 100vw; }

  .hdr {
    flex-wrap: wrap; justify-content: center; row-gap: 9px; column-gap: 10px;
    padding: 11px 12px;
  }
  .hdr__id { flex: 1 1 100%; justify-content: center; min-width: 0; }
  .hdr__title { font-size: 12.5px; white-space: normal; text-align: center; }
  /* the base rule pins these with flex:none, which stops them wrapping */
  .hdr__clock  { flex: 0 1 auto; order: 1; text-align: center; min-width: 0; }
  .hdr__status { flex: 0 1 auto; order: 2; margin-left: 0; font-size: 9.5px; padding: 5px 11px; min-width: 0; }
  .clock__time { font-size: 19px; }
  .hdr__ctl {
    flex: 1 1 100%; order: 3; flex-wrap: wrap; justify-content: center;
    gap: 6px; min-width: 0;
  }
  .btn { padding: 6px 11px; }

  .panel__hd { flex-wrap: wrap; row-gap: 3px; }
  .panel__meta { white-space: normal; font-size: 9px; }
  .panel--map { min-height: 400px; }

  .map__legend { font-size: 8.5px; padding: 6px 8px; gap: 3px; left: 8px; bottom: 8px; }
  .map__scale { right: 8px; bottom: 8px; font-size: 8px; }

  .tiles { grid-template-columns: 1fr 1fr; }
  .hero__val { font-size: 34px; }
  .detail { min-height: auto; }
  .toasts { left: 8px; right: 8px; top: auto; bottom: 10px; align-items: stretch; }
  .toast { max-width: none; }
}

@media (max-width: 520px) {
  .panel__meta { display: none; }
  .panel__t { font-size: 10px; letter-spacing: .1em; }
  .readouts, .tiles { grid-template-columns: 1fr; }
  .hrow__l { width: 78px; font-size: 9.5px; }
}

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

/* ══════════ ENVIRONMENT MODE ══════════
   Reuses the RAIL grid and tokens; only the centre content differs. */

.envnote {
  font-size: 10px; line-height: 1.5; color: var(--ink-3);
  border-left: 2px solid var(--hairline-2); padding-left: 9px;
}

/* station strip — one row per station, ECS or SAC */
.estnwrap { flex: 1; overflow-y: auto; padding: 4px 0; }
.estn {
  display: grid; grid-template-columns: 40px minmax(0,1fr) 34px 8px 34px;
  align-items: center; gap: 8px; padding: 5px 13px; cursor: pointer;
  border-bottom: 1px solid var(--tint-1);
}
.estn:hover { background: var(--tint-2); }
.estn.is-att { background: color-mix(in srgb, var(--warn) 6%, transparent); }
.estn__c { font-family: var(--mono); font-size: 9.5px; color: var(--ink-4); }
.estn__n { font-size: 11.5px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.estn__t { font-family: var(--mono); font-size: 8.5px; color: var(--ink-3); letter-spacing: .08em; }
.estn__d { width: 7px; height: 7px; border-radius: 50%; }
.estn__k { font-family: var(--mono); font-size: 9.5px; color: var(--ink-3); text-align: right; }

/* service queue */
.qrow {
  display: grid; grid-template-columns: 8px 84px minmax(0,1fr) 58px;
  align-items: center; gap: 8px; padding: 5px 3px; cursor: pointer;
  border-bottom: 1px solid var(--tint-1);
}
.qrow:hover { background: var(--tint-2); }
.qrow.is-sel { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.qrow__d { width: 7px; height: 7px; border-radius: 50%; }
.qrow__id { font-family: var(--mono); font-size: 10px; color: var(--ink); }
.qrow__id .ls { color: var(--warn); font-style: normal; font-size: 8px; margin-left: 3px; }
.qrow__s { font-size: 10.5px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qrow__w { font-family: var(--mono); font-size: 11px; color: var(--ink-2); text-align: right; }
.q__u { color: var(--ink-4); font-size: 9px; }

/* asset detail */
.dls {
  font-size: 10px; line-height: 1.45; color: var(--warn);
  border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
  background: color-mix(in srgb, var(--warn) 8%, transparent);
  border-radius: 6px; padding: 7px 9px; margin-bottom: 10px;
}
.dsev {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .1em;
  border: 1px solid; border-radius: 3px; padding: 2px 6px; white-space: nowrap;
}
.dgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; margin-bottom: 11px; }
.dcell { background: var(--tint-1); border: 1px solid var(--hairline); border-radius: 7px; padding: 7px 9px; }
.dcell__l { font-size: 9px; letter-spacing: .06em; color: var(--ink-3); }
.dcell__v { font-family: var(--mono); font-size: 15px; color: var(--ink); margin-top: 2px; }
.dcell__u { font-size: 9.5px; color: var(--ink-3); }
.dci { font-size: 10px; color: var(--ink-3); }
.dact {
  margin-top: 11px; font-size: 11px; line-height: 1.5; color: var(--ink);
  border-left: 2px solid var(--accent); padding-left: 9px;
}
.dsrc { margin-top: 8px; font-family: var(--mono); font-size: 9px; color: var(--ink-4); }
.drow {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 4px 0; border-bottom: 1px solid var(--tint-1); font-size: 11px;
}
.drow:last-of-type { border-bottom: 0; }
.drow > span:first-child { color: var(--ink-3); }
.drow > span:last-child { font-family: var(--mono); color: var(--ink-2); }

/* ENVIRONMENT — centre panel tabs */
.etabs { display: flex; gap: 4px; }
.etab {
  appearance: none; border: 1px solid var(--hairline-2); background: var(--seg-bg);
  color: var(--ink-3); font-family: var(--mono); font-size: 9px; letter-spacing: .1em;
  padding: 3px 9px; border-radius: 5px; cursor: pointer; transition: .15s;
}
.etab:hover { color: var(--ink-2); }
.etab.is-on { color: var(--fg-max); background: color-mix(in srgb, var(--accent) 22%, transparent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.estn.is-fault { background: color-mix(in srgb, var(--critical) 12%, transparent); }

/* plant schematic */
.plantbar { display: flex; align-items: center; gap: 4px; padding: 7px 13px 0; flex: none; }
.pbtn {
  appearance: none; border: 1px solid var(--hairline-2); background: transparent;
  color: var(--ink-3); font-family: var(--mono); font-size: 9px; padding: 2px 7px;
  border-radius: 4px; cursor: pointer;
}
.pbtn.is-on { color: var(--fg-max); background: color-mix(in srgb, var(--accent) 22%, transparent); }
.plantbar__n { margin-left: auto; font-size: 10.5px; color: var(--ink-2); }
.plantwrap { flex: 1; min-height: 0; padding: 4px 8px 8px; }
.plant__svg { width: 100%; height: 100%; display: block; }
.pbox { cursor: pointer; }
.pbox:hover rect { filter: brightness(1.25); }

/* energy view */
.ewrap { flex: 1; overflow-y: auto; padding: 10px 13px 12px; }
.ehead { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; margin-bottom: 10px; }
.ecard { background: var(--tint-1); border: 1px solid var(--hairline); border-radius: 7px; padding: 8px 10px; }
.ecard__l { font-size: 9px; color: var(--ink-3); letter-spacing: .05em; }
.ecard__v { font-family: var(--mono); font-size: 17px; color: var(--ink); margin-top: 3px; }
.ecard__u { font-size: 9.5px; color: var(--ink-3); margin-left: 3px; }
.elegend { display: flex; gap: 14px; margin-bottom: 8px; font-size: 9.5px; color: var(--ink-3); }
.elegend i { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 5px; vertical-align: middle; }
.erow {
  display: grid; grid-template-columns: 36px minmax(0,150px) minmax(0,1fr) 62px 38px;
  align-items: center; gap: 9px; padding: 4px 0; border-bottom: 1px solid var(--tint-1);
}
.erow__c { font-family: var(--mono); font-size: 9.5px; color: var(--ink-4); }
.erow__n { font-size: 11px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.erow__bar { display: flex; height: 7px; border-radius: 3px; overflow: hidden; background: var(--tint-1); }
.erow__lwbp { background: var(--accent); }
.erow__wbp { background: var(--serious); }
.erow__k, .erow__w { font-family: var(--mono); font-size: 10px; color: var(--ink-3); text-align: right; }
.enote { margin-top: 11px; font-size: 10px; line-height: 1.55; color: var(--ink-3); border-left: 2px solid var(--hairline-2); padding-left: 9px; }

/* ═══ FACILITIES mode ═══════════════════════════════════════════
   System-first navigation. The system rail is the primary control,
   so it gets the affordances the mode switch normally would. */

.fsyswrap { display:flex; flex-direction:column; gap:9px; padding-bottom:8px; }
.fgrp__h {
  font-size:9px; letter-spacing:.13em; text-transform:uppercase;
  color:var(--muted); margin:0 0 3px 2px;
}
.fsys {
  display:flex; align-items:center; gap:7px; width:100%;
  background:var(--surface-2); border:1px solid var(--line);
  border-radius:5px; padding:5px 7px; margin-bottom:3px;
  cursor:pointer; text-align:left; font:inherit; color:var(--fg);
  transition:border-color .12s, background .12s;
}
.fsys:hover { border-color:var(--accent); }
.fsys.is-on { border-color:var(--accent); background:var(--surface-3); }
.fsys__d { width:7px; height:7px; border-radius:50%; flex:0 0 auto; }
.fsys__n { flex:1 1 auto; font-size:11px; line-height:1.25; }
.fsys__c {
  font-size:10px; color:var(--muted); font-variant-numeric:tabular-nums;
  flex:0 0 auto;
}
.fsys .ls { font-style:normal; color:var(--warn); font-size:8px; margin-left:3px; }

/* the system's assets across every location */
.facwrap { overflow:auto; flex:1 1 auto; padding:2px 0 6px; }
.frow {
  display:grid;
  grid-template-columns:9px 96px 1fr 88px 74px 132px;
  align-items:center; gap:8px;
  padding:4px 10px; cursor:pointer;
  border-left:2px solid transparent;
  font-size:11px;
}
.frow:hover { background:var(--surface-2); }
.frow.is-sel { background:var(--surface-3); border-left-color:var(--accent); }
.frow__d { width:7px; height:7px; border-radius:50%; }
.frow__id { font-family:var(--mono,ui-monospace,monospace); font-size:10px; }
.frow__loc { color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.frow__bar {
  height:5px; border-radius:3px; background:var(--surface-3);
  overflow:hidden; display:block;
}
.frow__bar i { display:block; height:100%; border-radius:3px; }
.frow__v { text-align:right; font-variant-numeric:tabular-nums; }
.frow__w { text-align:right; font-variant-numeric:tabular-nums; font-size:10px; }
.frow .ls { font-style:normal; color:var(--warn); font-size:8px; margin-left:3px; }

.fband {
  font-size:9px; color:var(--muted); margin-left:4px;
  font-variant-numeric:tabular-nums;
}
.fmuted { color:var(--muted); }
.fnote {
  margin-top:9px; padding:7px 9px; border-radius:5px;
  background:var(--surface-2); border:1px solid var(--line);
  font-size:9.5px; line-height:1.45; color:var(--muted);
}
.fnote--ls { border-color:var(--warn); color:var(--fg); }

@media (max-width:1500px) {
  .frow { grid-template-columns:9px 84px 1fr 64px 66px 108px; font-size:10px; }
}

/* FACILITIES — geographic panel */
.facmapwrap { flex:1 1 auto; min-height:0; position:relative; }
.facmap { width:100%; height:100%; display:block; }
.panel--map { display:flex; flex-direction:column; }

/* FACILITIES — full asset record in the right rail */
.detail { overflow-y:auto; }
.dsec__h {
  font-size:9px; letter-spacing:.13em; text-transform:uppercase;
  color:var(--muted); margin:14px 0 5px;
  padding-bottom:4px; border-bottom:1px solid var(--line);
  display:flex; align-items:center; justify-content:space-between; gap:6px;
}
.drow--tot { border-top:1px solid var(--line); margin-top:3px; padding-top:5px; }
.drow--tot b { color:var(--accent); }

.dpeer { margin:6px 0 8px; }
.dpeer__bar {
  position:relative; height:6px; border-radius:3px;
  background:linear-gradient(90deg,var(--ok),var(--warn),var(--critical));
  opacity:.55;
}
.dpeer__med, .dpeer__me {
  position:absolute; top:-3px; width:2px; height:12px; border-radius:1px;
}
.dpeer__med { background:var(--muted); }
.dpeer__me  { background:var(--fg); width:3px; height:14px; top:-4px; }
.dpeer__lab {
  display:flex; justify-content:space-between; gap:8px;
  font-size:9px; color:var(--muted); margin-top:5px;
}

.wochip {
  font-size:8px; letter-spacing:.09em; text-transform:uppercase;
  padding:1px 6px; border-radius:9px; border:1px solid currentColor;
}
.wochip--critical { color:var(--critical); }
.wochip--serious  { color:var(--serious); }
.wochip--warn     { color:var(--warn); }
.wochip--ok       { color:var(--muted); }

.dwo {
  font-size:10.5px; line-height:1.5; margin:5px 0 7px;
  padding:7px 9px; border-radius:5px;
  background:var(--surface-2); border-left:2px solid var(--accent);
}
.dparts { display:flex; flex-wrap:wrap; gap:4px; margin-bottom:7px; }
.dparts span {
  font-size:9px; padding:2px 6px; border-radius:3px;
  background:var(--surface-3); color:var(--muted);
}

.dhist {
  display:grid; grid-template-columns:26px 1fr auto;
  gap:7px; align-items:center;
  padding:4px 0; font-size:10px;
  border-bottom:1px solid var(--line);
}
.dhist__t {
  font-size:8px; text-align:center; padding:1px 0; border-radius:3px;
  letter-spacing:.05em;
}
.dhist__t--pm { background:var(--surface-3); color:var(--muted); }
.dhist__t--cm { background:var(--warn); color:var(--on-accent); }
.dhist__w { font-family:var(--mono,ui-monospace,monospace); font-size:9.5px; color:var(--muted); }
.dhist__d { color:var(--muted); font-size:9.5px; }

/* Detail rows must wrap, not clip. A flex item defaults to
   min-width:auto, so a long value ("Water-cooled centrifugal chiller")
   refuses to shrink and runs under the panel's overflow-x:hidden.
   Both sides need min-width:0 before the value is allowed to wrap. */
.detail .drow { align-items:flex-start; }
.detail .drow > span:first-child { flex:0 1 auto; min-width:0; }
.detail .drow > b {
  flex:1 1 auto; min-width:0; text-align:right;
  white-space:normal; overflow-wrap:anywhere; line-height:1.35;
}
.detail .dhist__w, .detail .dhist__d { min-width:0; overflow-wrap:anywhere; }
.detail__body { padding-right:2px; }

/* ══════════ CARD AFFORDANCES ══════════
   Scope, range, expand, export — the four verbs a facility-analytics
   card is expected to carry. Built from the display's own segmented
   control and hairline tokens so a toolbar reads as part of the
   operations display rather than as a dashboard pasted into it. */
.panel__hd--tools { align-items: center; }
.ptools { display: flex; align-items: center; gap: 6px; margin-left: auto; flex: none; }

.seg--tool { border-radius: 6px; }
.seg--tool .seg__b { padding: 4px 7px; font-size: 9px; letter-spacing: .08em; }
.seg--tool .seg__b.is-on { box-shadow: inset 0 -2px 0 var(--accent); }

.ptool {
  appearance: none; cursor: pointer; display: grid; place-items: center;
  width: 24px; height: 22px; border-radius: 6px; padding: 0;
  border: 1px solid var(--hairline-2); background: var(--seg-bg); color: var(--ink-3);
  transition: background .16s, color .16s, border-color .16s;
}
.ptool:hover { color: var(--fg-max); background: var(--tint-2); border-color: var(--accent); }
.ptool svg { display: block; }
.ptool--x svg + svg { display: none; }
.panel.is-max .ptool--x svg:first-child { display: none; }
.panel.is-max .ptool--x svg + svg { display: block; }

.pselw { position: relative; display: inline-flex; align-items: center; }
.pselw > i {
  position: absolute; right: 7px; font-size: 8px; color: var(--ink-3);
  pointer-events: none; font-style: normal;
}
.psel {
  appearance: none; cursor: pointer; max-width: 220px; text-overflow: ellipsis;
  border: 1px solid var(--hairline-2); border-radius: 6px; background: var(--seg-bg);
  color: var(--ink); font-family: var(--mono); font-size: 9.5px; letter-spacing: .04em;
  padding: 4px 19px 4px 8px; transition: color .16s, border-color .16s;
}
.psel:hover { color: var(--fg-max); border-color: var(--accent); }
.psel:focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; }

/* ── expand ── */
.panel.is-max {
  position: fixed; inset: 16px; z-index: 50;
  box-shadow: 0 28px 90px var(--shadow);
}
body.has-max::before {
  content: ""; position: fixed; inset: 0; z-index: 49;
  background: color-mix(in srgb, var(--bg) 76%, transparent);
  backdrop-filter: blur(2px);
}

/* ── shared tooltip ── */
.ctip {
  position: fixed; z-index: 60; pointer-events: none; opacity: 0;
  transform: translate(-50%, -100%) translateY(-12px);
  transition: opacity .11s ease-out;
  min-width: 130px; max-width: 280px;
  padding: 7px 9px; border-radius: 7px;
  border: 1px solid var(--hairline-2); background: var(--surface-2);
  box-shadow: 0 10px 28px var(--shadow);
  font-family: var(--mono); font-size: 10px; line-height: 1.5; color: var(--ink);
}
.ctip.is-on { opacity: 1; }
.ctip.is-below { transform: translate(-50%, 0) translateY(12px); }
.ctip__t {
  color: var(--fg-max); font-size: 10.5px; letter-spacing: .04em;
  margin-bottom: 4px; padding-bottom: 4px; border-bottom: 1px solid var(--hairline);
}
.ctip__r { display: flex; justify-content: space-between; gap: 16px; }
.ctip__r .ctip__k { color: var(--ink-3); }
.ctip__r b { color: var(--fg-max); font-weight: 500; white-space: nowrap; }
.ctip__f {
  margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--hairline);
  color: var(--ink-3); font-size: 9px; letter-spacing: .05em;
}

/* ══════════ STATION PLAN ══════════ */
.pback {
  appearance: none; cursor: pointer; display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--hairline-2); border-radius: 6px; background: var(--seg-bg);
  color: var(--ink-3); font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  padding: 5px 9px; margin-right: 2px; flex: none;
  transition: color .16s, border-color .16s, background .16s;
}
.pback:hover { color: var(--fg-max); border-color: var(--accent); background: var(--tint-2); }

.planfoot {
  display: flex; align-items: center; gap: 14px; flex: none;
  padding: 6px 13px 8px; border-top: 1px solid var(--hairline);
  font-family: var(--mono); font-size: 9px; letter-spacing: .05em; color: var(--ink-3);
}
.planfoot__k { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.pk {
  width: 11px; height: 8px; border-radius: 2px; display: inline-block;
  border: 1.5px solid var(--line); background: var(--surface-3);
}
.pk--warn     { border-color: var(--warn);     background: color-mix(in srgb, var(--warn) 11%, transparent); }
.pk--serious  { border-color: var(--serious);  background: color-mix(in srgb, var(--serious) 14%, transparent); }
.pk--critical { border-color: var(--critical); background: color-mix(in srgb, var(--critical) 18%, transparent); }
.planfoot__src {
  margin-left: auto; text-align: right; opacity: .8;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* A flagged unit should find the eye from across a control room. */
@keyframes planpulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
.facmap [data-item] rect[fill^="color-mix"] { animation: none; }
.facmap [data-item] { transition: opacity .18s; }
.facmap [data-item]:hover { opacity: .82; }

/* ══════════ BRUSH SELECTION ══════════
   While a brush is active the ranked list stops being per-system, so
   each row has to carry the system it belongs to. */
.qrow__sys { color: var(--ink-2); }
.facmap, .str__svg { user-select: none; -webkit-user-select: none; }

/* ══════════ COMPARE MODE ══════════
   The slot colour in the list and the curve colour on the chart are
   the same fact, so they must not drift apart. */
.qrow.is-cmp { box-shadow: inset 2px 0 0 var(--accent); }
.qrow.is-cmp.cmp0 { box-shadow: inset 2px 0 0 var(--accent); }
.qrow.is-cmp.cmp1 { box-shadow: inset 2px 0 0 var(--serious); }
.qrow.is-cmp.cmp2 { box-shadow: inset 2px 0 0 var(--ok); }
.qrow.is-cmp.cmp3 { box-shadow: inset 2px 0 0 var(--warn); }
.qrow.is-cmp .qrow__id::after {
  content: "◆"; font-size: 7px; margin-left: 5px; vertical-align: 1px; opacity: .8;
}
.qrow.is-cmp.cmp0 .qrow__id::after { color: var(--accent); }
.qrow.is-cmp.cmp1 .qrow__id::after { color: var(--serious); }
.qrow.is-cmp.cmp2 .qrow__id::after { color: var(--ok); }
.qrow.is-cmp.cmp3 .qrow__id::after { color: var(--warn); }

/* ══════════ REPLAY ══════════
   An operations display showing a past state must say so unmissably —
   stale data read as live is the failure mode that matters. */
.replay {
  margin: 0 0 9px; padding: 7px 10px; border-radius: 7px;
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  background: color-mix(in srgb, var(--warn) 11%, transparent);
}
.replay__t {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em;
  color: var(--warn); font-weight: 600;
}
.replay__s {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .05em;
  color: var(--ink-3); margin-top: 3px; line-height: 1.4;
}
.pnow {
  appearance: none; cursor: pointer; float: right;
  border: 1px solid color-mix(in srgb, var(--warn) 50%, transparent);
  background: color-mix(in srgb, var(--warn) 14%, transparent);
  color: var(--warn); font-family: var(--mono); font-size: 8.5px;
  letter-spacing: .1em; padding: 2px 7px; border-radius: 4px;
  transition: background .16s, color .16s;
}
.pnow:hover { background: var(--warn); color: var(--bg); }

/* A tint on the whole board, so the state is legible from across a room. */
body.is-replay .panel::before,
body.is-replay .panel::after { border-color: color-mix(in srgb, var(--warn) 50%, transparent); }
body.is-replay .hdr { box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--warn) 55%, transparent); }
.hero__spark svg { cursor: ew-resize; }

/* ══════════ REPORT ══════════
   Categorical ramp for system-group identity. Validated with the
   palette checker against BOTH surfaces this display uses — lightness
   band, chroma floor, adjacent CVD separation, normal-vision floor and
   contrast. Light mode warns under 3:1 on four slots, which is why the
   donut carries direct counts and the detail table is always present.
   Status colours are NOT drawn from here; they stay reserved. */
:root {
  --cat-1:#3987e5; --cat-2:#d95926; --cat-3:#199e70; --cat-4:#c98500;
  --cat-5:#d55181; --cat-6:#008300; --cat-7:#9085e9; --cat-8:#e66767;
}
:root[data-theme="light"] {
  --cat-1:#2a78d6; --cat-2:#eb6834; --cat-3:#1baf7a; --cat-4:#eda100;
  --cat-5:#e87ba4; --cat-6:#008300; --cat-7:#4a3aa7; --cat-8:#e34948;
}
.c-crit { color: var(--critical); }

/* facets */
.rsec__h {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3); margin: 11px 0 5px;
}
.rfacets { display: flex; flex-direction: column; gap: 3px; }
.rfacet {
  appearance: none; cursor: pointer; display: flex; align-items: center; gap: 7px;
  width: 100%; text-align: left; padding: 5px 8px; border-radius: 5px;
  border: 1px solid var(--line); background: var(--surface-2);
  color: var(--ink-3); font-size: 10.5px; opacity: .45; transition: opacity .14s, border-color .14s;
}
.rfacet.is-on { opacity: 1; border-color: var(--hairline-2); color: var(--ink); }
.rfacet:hover { border-color: var(--accent); }
.rfacet i { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.rfacet__n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rfacet__c { font-family: var(--mono); font-size: 9.5px; color: var(--ink-3); }

.rkpi { display: flex; flex-direction: column; gap: 2px; }
.rkpi__row {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  font-size: 10.5px; color: var(--ink-2); padding: 3px 0;
}
.rkpi__row b { font-family: var(--mono); color: var(--fg-max); font-weight: 500; }
.rkpi__row--tot { border-top: 1px solid var(--line); margin-top: 3px; padding-top: 6px; }
.rnote {
  font-size: 8.5px; line-height: 1.45; color: var(--ink-3);
  margin-top: 10px; padding-top: 7px; border-top: 1px solid var(--line);
}

/* chart shells */
.rsplit { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; flex: 1; min-height: 0; padding: 6px; }
.rsplit__c { min-width: 0; min-height: 0; }
.rsplit__c svg { width: 100%; height: 100%; display: block; }
.rboxwrap { flex: 1; min-height: 0; padding: 4px 6px 2px; }
.rboxwrap svg { width: 100%; height: 100%; display: block; }

/* table */
.rtwrap { flex: 1; min-height: 0; overflow: auto; }
table.rt { width: 100%; border-collapse: collapse; font-size: 10.5px; }
table.rt thead th {
  position: sticky; top: 0; z-index: 2; background: var(--surface-3);
  text-align: left; padding: 6px 9px; font-family: var(--mono); font-size: 8.5px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
  border-bottom: 1px solid var(--hairline-2); cursor: pointer; white-space: nowrap;
}
table.rt thead th:hover { color: var(--ink); }
table.rt thead th.is-sort { color: var(--accent); }
table.rt td { padding: 4px 9px; border-bottom: 1px solid var(--hairline); color: var(--ink-2); white-space: nowrap; }
table.rt tbody tr:hover td { background: var(--tint-2); }
table.rt .rt--r { text-align: right; font-family: var(--mono); }
table.rt .rt__id { font-family: var(--mono); color: var(--ink); }
table.rt .rt__wo { font-family: var(--mono); color: var(--ink-3); font-size: 9.5px; }
table.rt tfoot td {
  position: sticky; bottom: 0; background: var(--surface-3);
  border-top: 1px solid var(--hairline-2); border-bottom: 0;
  color: var(--ink); font-size: 10px; padding: 6px 9px;
}
.rdot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; vertical-align: 0; }

/* where-the-work-is bars */
.rbars { display: flex; flex-direction: column; gap: 4px; }
.rbar { display: grid; grid-template-columns: 84px 1fr 22px; align-items: center; gap: 7px; }
.rbar__l { font-size: 10px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rbar__t { height: 7px; border-radius: 4px; background: var(--surface-3); overflow: hidden; }
.rbar__t i { display: block; height: 100%; background: var(--accent); border-radius: 4px; }
.rbar__v { font-family: var(--mono); font-size: 9.5px; color: var(--fg-max); text-align: right; }

/* Report re-grids the board. A report is read top-down and its centre
   of gravity is the table, so the composition strip is capped and the
   table takes the space the live charts used. The box plot moves
   alongside the table where its long system names have room. */
body.is-report .app {
  grid-template-columns: 244px minmax(0,1fr) 400px 300px;
  grid-template-rows: 58px 290px minmax(160px,1fr) 150px;
  grid-template-areas:
    "hdr  hdr  hdr  hdr"
    "rail map  map  detail"
    "rail trk  stn  detail"
    "rail str  str  detail";
}
body.is-report .panel--stn .panel__t { font-size: 10px; }
body.is-report .rail, body.is-report .detail { overflow-y: auto; }

/* ══════════ REPORT — responsive ══════════
   The base grid hides .panel--stn below 1450px, which is right for the
   live board (platform density is the least critical panel there) and
   wrong here — that slot holds the range chart. Report therefore
   restates its own arrangement at every breakpoint rather than
   inheriting one built for a different set of panels. */
@media (max-width: 1600px) {
  body.is-report .app {
    grid-template-columns: 224px minmax(0,1fr) 300px;
    grid-template-rows: 58px 268px minmax(150px,1fr) 140px;
    grid-template-areas:
      "hdr  hdr  hdr"
      "rail map  detail"
      "rail trk  detail"
      "rail str  stn";
  }
  /* The base grid hides this panel below 1450px; report needs it, so
     the rule is restated rather than inherited. It shares the bottom
     row with the daily chart and sheds rows to fit — see ranges(). */
  body.is-report .panel--stn { display: flex; }
}
@media (max-width: 1150px) {
  body.is-report .app {
    height: auto; grid-template-columns: 1fr; grid-template-rows: auto;
    grid-template-areas: "hdr" "rail" "map" "trk" "stn" "str" "detail";
  }
  body.is-report .panel--stn { display: flex; min-height: 300px; }
  body.is-report .panel--map { min-height: 380px; }
  body.is-report .panel--trk { min-height: 420px; }
  body.is-report .panel--str { min-height: 180px; }
  body.is-report .detail { min-height: 280px; }
  body.is-report .rail { min-height: auto; }
}
/* The table is the point of this view; it may scroll sideways rather
   than drop columns, and its own wrapper owns that scroll. */
body.is-report .panel--trk { min-width: 0; }
.rtwrap { overflow: auto; -webkit-overflow-scrolling: touch; }

/* ══════════ HEADER — stop the title and status colliding ══════════
   Every child was flex:none, so once the control cluster grew past the
   available width the row overflowed instead of yielding. The identity
   block is the one thing that can afford to shrink. */
.hdr__id { min-width: 0; flex: 0 1 auto; }
.hdr__titles { min-width: 0; }
.hdr__title { overflow: hidden; text-overflow: ellipsis; }
.hdr__status { flex: 0 0 auto; }
@media (max-width: 1500px) {
  .hdr__status { margin-left: auto; padding: 5px 10px; font-size: 9.5px; }
  .hdr__ctl { gap: 5px; }
  .seg__b { padding: 6px 8px; }
  .btn { padding: 7px 10px; }
}
@media (max-width: 1320px) {
  /* the incident control belongs to the live board, not the report */
  body.is-report #btnIncident,
  body.is-report .seg[aria-label="Simulation rate"],
  body.is-report .seg[aria-label="Network view"] { display: none; }
  .hdr__clock { display: none; }
}

/* ══════════ SHORT VIEWPORTS ══════════
   The grid is built from fixed pixel rows against height:100vh, so on
   a short window — or, far more commonly, a zoomed browser, which
   shrinks the CSS viewport — the rows sum to more than the space and
   the bottom panels are simply cut off with no way to reach them.

   Rows are compressed in two steps first, because a control-room
   display should stay one screen. Below that, correctness beats the
   single-screen rule and the page is allowed to scroll. */
@media (max-height: 820px) and (min-width: 1151px) {
  .app { gap: 7px; padding: 7px; grid-template-rows: 54px minmax(150px,1fr) 126px 150px; }
  body.is-report .app { grid-template-rows: 54px 244px minmax(130px,1fr) 124px; }
  .hero__val { font-size: 32px; }
  .tile__lab { min-height: 0; }
}
@media (max-height: 700px) and (min-width: 1151px) {
  .app { gap: 6px; padding: 6px; grid-template-rows: 50px minmax(120px,1fr) 106px 122px; }
  body.is-report .app { grid-template-rows: 50px 208px minmax(110px,1fr) 106px; }
  .hdr__sub, .clock__meta { display: none; }
  .hero__val { font-size: 27px; }
  .clock__time { font-size: 17px; }
  .panel__hd { padding: 6px 11px 5px; }
}
/* The safety net. Nothing may be unreachable, so once compression runs
   out the display stops pretending to be one screen. */
@media (max-height: 600px) {
  html, body { overflow-y: auto; height: auto; min-height: 100%; }
}
@media (max-height: 600px) and (min-width: 1151px) {
  .app { height: auto; min-height: 100vh; grid-template-rows: 50px 300px 200px 180px; }
  body.is-report .app { grid-template-rows: 50px 240px 420px 180px; }
  body.is-report .panel--trk { min-height: 380px; }
  .toasts { position: fixed; }
}

/* ═══ FLOW — passenger flow view ═══════════════════════════════════ */
.flow__privacy{
  margin:.5rem .75rem .75rem; padding:.45rem .7rem; border-radius:6px;
  font-size:.72rem; letter-spacing:.02em;
  color:var(--fg-max); background:color-mix(in srgb, var(--good) 12%, transparent);
  border:1px solid color-mix(in srgb, var(--good) 38%, transparent);
}
.flow__meta{ display:flex; gap:.4rem; padding:.35rem .25rem 0; font-size:.72rem; opacity:.7 }
.flow__bar{ display:flex; align-items:center; gap:.6rem; margin:.18rem 0 }
.flow__bark{ width:1.2rem; font-weight:700; font-size:.8rem }
.flow__bart{ flex:1; height:.55rem; border-radius:99px;
  background:color-mix(in srgb, var(--fg-max) 10%, transparent); overflow:hidden }
.flow__bart i{ display:block; height:100%; background:var(--accent) }
.flow__barv{ width:2.6rem; text-align:right; font-variant-numeric:tabular-nums; font-size:.78rem }
.ls{ margin:0; padding-left:1.1rem; font-size:.78rem; line-height:1.55 }
.flow__svg{ width:100%; height:auto; max-height:52vh; display:block }
.panel--trk .panel__bd{ overflow-y:auto }
.flow__blind{
  margin:.4rem .75rem 0; padding:.45rem .7rem; border-radius:6px; font-size:.74rem;
  color:var(--fg-max); background:color-mix(in srgb, var(--critical) 14%, transparent);
  border:1px solid color-mix(in srgb, var(--critical) 45%, transparent);
}
.flow__disrupt{
  margin:.4rem .75rem 0; padding:.45rem .7rem; border-radius:6px; font-size:.74rem;
  color:var(--fg-max); background:color-mix(in srgb, var(--warn) 20%, transparent);
  border:1px solid color-mix(in srgb, var(--warn) 55%, transparent);
}
.flow__legend{ display:flex; flex-wrap:wrap; gap:.15rem 1rem; padding:.5rem .25rem .1rem; font-size:.7rem; opacity:.8 }
.flow__legend span{ display:inline-flex; align-items:center; gap:.35rem }
.lg{ width:.6rem; height:.6rem; border-radius:99px; display:inline-block }
.lg--cam{ background:color-mix(in srgb, var(--fg-max) 42%, transparent) }
.lg--camout{ background:var(--critical); box-shadow:0 0 0 2px color-mix(in srgb, var(--critical) 40%, transparent) }
.lg--blind{ border-radius:2px; background:repeating-linear-gradient(45deg, color-mix(in srgb, var(--critical) 45%, transparent) 0 2px, transparent 2px 4px); outline:1px solid color-mix(in srgb, var(--critical) 60%, transparent) }
.lg--busy{ border-radius:2px; background:color-mix(in srgb, var(--warn) 46%, transparent) }
.seg__lab{ align-self:center; padding:0 .45rem 0 .3rem; font-size:.6rem; letter-spacing:.08em; opacity:.6; white-space:nowrap }

/* ═══ FLOW layout robustness ═══════════════════════════════════════
   The wall is ultrawide; laptops and scaled displays are not. Below
   full width the zone table lost its LOS column with no way to scroll
   to it, the level switch clipped B2, and the banners under the plan
   were cut off by a fixed-height panel. Content must degrade by
   scrolling or wrapping, never by silently disappearing. */
.panel--stn .panel__bd{ overflow:auto }
.panel--stn .tbl{ width:100%; table-layout:auto }
.panel--stn .tbl th:last-child,
.panel--stn .tbl td:last-child{ white-space:nowrap }
/* the level switch must never be the thing that gets squeezed */
.panel--map .panel__hd .seg{ flex:0 0 auto }
.panel--map .panel__hd{ flex-wrap:wrap; row-gap:.25rem }
/* leave room under the plan for the disruption / blind-spot banners */
.flow__svg{ max-height:38vh }
.panel--map{ overflow:auto }
