/* DRISHTI console styles — AndPayments re-skin + three-tier hierarchy.
 *
 * Two things are going on in this sheet and it is worth knowing which is which.
 *
 * 1. TOKENS. Every colour is a custom property on :root (NAVY) with a LIGHT
 *    override under [data-theme="light"]. The old dark-teal names (--bg, --panel,
 *    --warn, --fault …) are kept as aliases pointing at the new ones, because
 *    templates build colours by name at render time — wall.html writes
 *    var(--{{ 'ok' if … else 'fault' }}) — and a rename there is a silent
 *    breakage, not a compile error.
 *
 * 2. THE THREE TIERS. Tier 1 (.t1*) says what is true right now, in a sentence.
 *    Tier 2 (.needs, .rail) is anything waiting on a person, and is the only
 *    place orange appears. Tier 3 (tables, .log, .chip) is evidence and is quiet
 *    on purpose. If orange leaks into tier 1 or tier 3 the hierarchy stops
 *    working, so --d-accent is used deliberately and rarely.
 *
 * The .view/.view.on show-hide rules are kept because HTMX swaps whole views
 * into #main; nav state is server-rendered.
 */

/* ── Fonts. Self-hosted: the console has to work at a venue with no internet,
      so no CDN and no <link> to Google Fonts. ─────────────────────────────── */
@font-face{font-family:'Montserrat';font-style:normal;font-weight:600;font-display:swap;
  src:url('fonts/montserrat-latin-600-normal.woff2') format('woff2')}
@font-face{font-family:'Montserrat';font-style:normal;font-weight:700;font-display:swap;
  src:url('fonts/montserrat-latin-700-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;
  src:url('fonts/inter-latin-400-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;
  src:url('fonts/inter-latin-500-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;
  src:url('fonts/inter-latin-600-normal.woff2') format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url('fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:500;font-display:swap;
  src:url('fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:600;font-display:swap;
  src:url('fonts/jetbrains-mono-latin-600-normal.woff2') format('woff2')}

/* ── Tokens ─────────────────────────────────────────────────────────────── */
:root,[data-theme="navy"]{
  --d-bg:#04162A;--d-panel:#08243E;--d-panel-2:#0E3458;--d-panel-3:#0A2A47;--d-video:#05101C;
  --d-chip-bg:#154771;--d-chip-fg:#CFE3F2;--d-line-soft:#10314C;--d-line:#17405F;--d-line-strong:#2E73AC;
  --d-holding-chip:#F6C083;--d-on-accent:#08243E;
  --d-t1:#FFFFFF;--d-t2:#DCE7F0;--d-t3:#B8C9DA;--d-t4:#9DB3C7;--d-t5:#9DB3C7;--d-t6:#8AA3B8;
  --d-video-fg:#3E5C79;--d-video-fg2:#2E4A63;--d-dot-off:#33506B;
  --d-accent:#EE9528;--d-accent-hover:#D27F1C;--d-link:#F2AB55;--d-accent-ink:#EE9528;--d-on-danger:#08243E;
  --d-ok:#34C08A;--d-ok-border:#1F7A5B;--d-bad:#F0654F;--d-info:#5A93C5;
  --d-focus:rgba(46,115,172,.30);
}
[data-theme="light"]{
  --d-bg:#F2F6FA;--d-panel:#FFFFFF;--d-panel-2:#F6F6F6;--d-panel-3:#F2F6FA;--d-video:#08243E;
  --d-chip-bg:#E2ECF4;--d-chip-fg:#08243E;--d-line-soft:#ECECEC;--d-line:#ECECEC;--d-line-strong:#DDDDDD;
  --d-holding-chip:#FCEAD7;--d-on-accent:#08243E;
  --d-t1:#08243E;--d-t2:#232323;--d-t3:#3D3D3D;--d-t4:#5C5C5C;--d-t5:#5C5C5C;--d-t6:#616161;
  --d-video-fg:#8DB5D6;--d-video-fg2:#5A93C5;--d-dot-off:#C4C4C4;
  --d-accent:#EE9528;--d-accent-hover:#D27F1C;--d-link:#9A5C0F;--d-accent-ink:#9A5C0F;--d-on-danger:#FFFFFF;
  --d-ok:#14704A;--d-ok-border:#14704A;--d-bad:#C0392B;--d-info:#2E73AC;
  --d-focus:rgba(238,149,40,.32);
}

/* ── Map palette ─────────────────────────────────────────────────────────
   The map has its own colours and does NOT reuse the panel tokens.

   It did at first, and the result was a map that rendered perfectly and was
   invisible: in the light theme --d-bg and --d-panel-3 are both #F2F6FA, so
   the sea and the land were painted the same colour, and --d-line at #ECECEC
   put the district outlines and urban areas within a hair of both. Nothing
   was broken; every layer drew exactly as instructed onto a flat rectangle.

   Chrome tokens are chosen to sit FLAT against each other -- that is what
   makes a panel read as one surface. Cartography wants the opposite: every
   adjacent pair has to separate. The two jobs cannot share a palette, so
   these seven are the only colours the map reads.
   ──────────────────────────────────────────────────────────────────────── */
:root,[data-theme="navy"]{
  --map-sea:#03101F;--map-land:#0B2A45;--map-urban:#14395C;
  --map-water:#14496F;--map-road:#35618A;--map-border:#2E73AC;
  --map-halo:#03101F;
}
[data-theme="light"]{
  --map-sea:#D7E3EF;--map-land:#FFFFFF;--map-urban:#EAF0F6;
  --map-water:#9FC2E0;--map-road:#AFC3D5;--map-border:#7FA3C4;
  --map-halo:#FFFFFF;
}

/* Legacy aliases. Templates name these at render time; keep them defined.
   --warn maps to the accent because everything the old sheet painted amber is,
   by the tier rule, something waiting on a person. */
:root,[data-theme]{
  --bg:var(--d-bg);--panel:var(--d-panel);--p2:var(--d-panel-2);--p3:var(--d-panel-3);
  --line:var(--d-line);--line2:var(--d-line-strong);
  --text:var(--d-t2);--fg:var(--d-t1);--fg2:var(--d-t3);--dim:var(--d-t3);--dim2:var(--d-t6);--muted:var(--d-t6);
  --ok:var(--d-ok);--warn:var(--d-accent);--fault:var(--d-bad);--info:var(--d-info);--off:var(--d-dot-off);
  --f-head:'Montserrat',system-ui,sans-serif;
  --f-sans:'Inter',system-ui,sans-serif;
  --f-mono:'JetBrains Mono','IBM Plex Mono',ui-monospace,monospace;
  --hdr:60px;--navw:218px;
  --ease:cubic-bezier(0.2,0.6,0.2,1);
}

*{box-sizing:border-box}
@keyframes drishti-pulse{0%,100%{opacity:1}50%{opacity:.35}}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
body{margin:0;background:var(--d-bg);color:var(--d-t2);font-family:var(--f-sans);
  font-size:13.5px;line-height:1.6;-webkit-font-smoothing:antialiased;overflow:hidden}
.mono,code{font-family:var(--f-mono)}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
:focus-visible{outline:none;box-shadow:0 0 0 3px var(--d-focus);border-radius:4px}
a{color:var(--d-link);text-decoration:none}
a:hover{color:var(--d-accent-ink);text-decoration:underline}
::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:var(--d-bg)}
::-webkit-scrollbar-thumb{background:var(--d-line);border-radius:999px}

/* ── Header (60px) ──────────────────────────────────────────────────────── */
header{height:var(--hdr);flex:0 0 auto;border-bottom:1px solid var(--d-line);background:var(--d-panel);
  display:flex;align-items:center;gap:18px;padding:0 18px;position:relative;z-index:20}
.brand{display:flex;align-items:center;gap:10px}
.brand .mark{width:26px;height:26px;border-radius:999px;background:var(--d-panel-2);
  border:1px solid var(--d-line-strong);position:relative;flex:0 0 26px}
.brand .mark::after{content:"";position:absolute;inset:6px;border-radius:999px;
  border:2px solid var(--d-accent);border-left-color:transparent;border-bottom-color:transparent;
  transform:rotate(20deg)}
.brand .wm{display:flex;flex-direction:column;gap:1px}
.brand b{font-family:var(--f-head);font-weight:700;font-size:15px;letter-spacing:.16em;line-height:1;
  color:var(--d-t1)}
.brand span{font-family:var(--f-mono);font-size:8.5px;letter-spacing:.14em;color:var(--d-t4);
  white-space:nowrap}
.brand{flex:0 0 auto}

.prof{display:flex;align-items:center;gap:8px;padding-left:18px;border-left:1px solid var(--d-line);
  font-family:var(--f-mono);font-size:9px;letter-spacing:.12em;color:var(--d-t4);
  white-space:nowrap;flex:0 0 auto}
.prof b{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.1em;font-weight:600;
  color:var(--d-on-accent);background:var(--d-accent);padding:3px 8px;border-radius:999px}
.prof.plain{border-left:0;padding-left:0;font-size:9.5px;letter-spacing:.06em;color:var(--d-t3)}
.prof .mono{font-size:9.5px;letter-spacing:.06em;color:var(--d-t3)}

.hcluster{margin-left:auto;display:flex;align-items:center;gap:16px;min-width:0}
.corehealth{display:flex;align-items:center;gap:7px;font-family:var(--f-mono);font-size:10px;
  letter-spacing:.08em;color:var(--d-t3);white-space:nowrap}
.corehealth .pip{width:7px;height:7px;border-radius:999px;flex:0 0 7px;background:var(--d-ok);
  animation:drishti-pulse 2.4s infinite}
.corehealth.down .pip{background:var(--d-bad)}

/* The other header figures. Kept — the redesign demotes them, it does not
   delete them: five numbers that used to compete with the headline now read as
   one quiet mono strip. */
.hstats{display:flex;align-items:center;gap:18px;min-width:0;flex:0 1 auto;overflow:hidden}
.hs{display:flex;align-items:center;gap:0;min-width:0;overflow:hidden}
.hs div{padding:0 11px;display:flex;flex-direction:column;justify-content:center;gap:2px;
  border-left:1px solid var(--d-line);min-width:62px;flex:0 0 auto}
.hs div:first-child{border-left:0}
.hs i{font-family:var(--f-mono);font-size:8.5px;letter-spacing:.13em;color:var(--d-t6);
  text-transform:uppercase;font-style:normal}
.hs b{font-family:var(--f-mono);font-size:12px;font-weight:600;color:var(--d-t2);line-height:1}
.hs b.ok{color:var(--d-ok)}.hs b.warn{color:var(--d-accent-ink)}.hs b.fault{color:var(--d-bad)}

.seg{display:flex;align-items:center;gap:2px;background:var(--d-panel-2);border:1px solid var(--d-line);
  border-radius:8px;padding:2px}
.seg button{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.1em;padding:5px 10px;
  border:0;border-radius:6px;color:var(--d-t3);background:transparent;transition:background .12s var(--ease),color .12s var(--ease)}
.seg button:hover{color:var(--d-t1)}
.seg button.on{background:var(--d-accent);color:var(--d-on-accent);font-weight:600}
.hrefresh{flex:0 0 auto}

/* ── Nav (218px) ────────────────────────────────────────────────────────── */
.body{display:flex;height:calc(100vh - var(--hdr));min-height:0}
nav{flex:0 0 var(--navw);border-right:1px solid var(--d-line);background:var(--d-panel);
  overflow-y:auto;padding:8px 0 28px}
.ng{font-family:var(--f-mono);font-size:8.5px;letter-spacing:.16em;color:var(--d-t6);
  text-transform:uppercase;padding:16px 16px 6px}
nav a,nav button{display:flex;align-items:center;gap:9px;width:100%;text-align:left;padding:7px 16px;
  color:var(--d-t3);font-family:var(--f-sans);font-size:12.5px;text-decoration:none;
  border-left:2px solid transparent;transition:background .12s var(--ease),color .12s var(--ease)}
nav a:hover,nav button:hover{background:var(--d-panel-2);color:var(--d-t1);text-decoration:none}
nav a.on,nav button.on{background:var(--d-panel-2);color:var(--d-t1);
  border-left-color:var(--d-accent);font-weight:600}

/* Tier-2 counts, surfaced in the chrome so the queue is visible from any screen. */
nav .bd{margin-left:auto;font-family:var(--f-mono);font-size:9px;font-weight:600;
  border-radius:999px;padding:1px 7px;background:var(--d-accent);color:var(--d-on-accent)}
nav .bd.bad{background:var(--d-bad);color:#fff}
nav .bd.ok{background:transparent;color:var(--d-ok);border:1px solid var(--d-ok-border);
  font-size:8.5px;letter-spacing:.08em}

main{flex:1;overflow-y:auto;min-width:0;padding:20px 24px 60px}
main.wall{zoom:1.22}          /* WALL density. zoom reflows; scale would overflow. */
.view{display:block}.view.on{display:block}

/* ── Tier 1 — state. What is true right now. ────────────────────────────── */
.t1{background:var(--d-panel);border:1px solid var(--d-line);border-radius:12px;
  padding:20px 24px;margin-bottom:14px;display:flex;gap:28px;align-items:center;flex-wrap:wrap}
.t1-b{flex:1;min-width:300px}
.t1-eyebrow{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.16em;color:var(--d-accent-ink);
  margin:0 0 10px;text-transform:uppercase}
.t1 h1{font-family:var(--f-head);font-weight:700;font-size:26px;line-height:1.2;letter-spacing:-.02em;
  margin:0;color:var(--d-t1)}
.t1.big h1{font-size:30px;line-height:1.18;max-width:22ch}
.t1-sub{font-family:var(--f-sans);font-size:13.5px;line-height:1.6;color:var(--d-t3);
  margin:12px 0 0;max-width:66ch}
.t1-actions{display:flex;gap:10px;margin-top:18px;flex-wrap:wrap}

/* At most three. Three is the cap that makes them rank; six ranked none. */
.figs{display:flex;gap:0;border:1px solid var(--d-line);border-radius:12px;overflow:hidden;
  background:var(--d-panel-2);flex-wrap:wrap}
.fig{padding:16px 22px;min-width:132px;border-right:1px solid var(--d-line)}
.fig:last-child{border-right:0}
.fig i{display:block;font-family:var(--f-mono);font-size:8.5px;letter-spacing:.13em;color:var(--d-t4);
  font-style:normal;margin-bottom:6px;text-transform:uppercase}
.fig b{display:block;font-family:var(--f-mono);font-size:28px;font-weight:600;line-height:1;
  font-variant-numeric:tabular-nums;
  letter-spacing:-.02em;color:var(--d-t1)}
.t1.big .fig b{font-size:30px}
.fig b.ok{color:var(--d-ok)}.fig b.warn{color:var(--d-accent-ink)}.fig b.fault{color:var(--d-bad)}
.fig b u{text-decoration:none;font-size:13px;color:var(--d-t4);margin-left:4px}
.fig u{display:block;text-decoration:none;font-family:var(--f-mono);font-size:10px;color:var(--d-t4);
  margin-top:6px}

/* Health pills — the wall's version of hero figures. */
.hpills{display:flex;gap:8px;flex-wrap:wrap}
.hpill{display:flex;align-items:center;gap:7px;background:var(--d-panel-2);border-radius:999px;
  padding:6px 12px;font-family:var(--f-mono);font-size:10.5px;color:var(--d-t3)}
.hpill .dot{width:7px;height:7px;flex:0 0 7px}
.hpill.ok{color:var(--d-ok)}.hpill.warn{color:var(--d-accent-ink)}.hpill.fault{color:var(--d-bad)}

/* Small figures on a rule — used where a panel has more measured terms than the
   banner's three-figure cap allows. Quiet by design. */
.sfigs{display:flex;gap:28px;margin-top:22px;padding-top:18px;border-top:1px solid var(--d-line);
  flex-wrap:wrap}
.sfig i{display:block;font-family:var(--f-mono);font-size:8.5px;letter-spacing:.13em;color:var(--d-t6);
  font-style:normal;margin-bottom:5px;text-transform:uppercase}
.sfig b{font-family:var(--f-mono);font-size:19px;font-weight:600;color:var(--d-t1);
  font-variant-numeric:tabular-nums}
.sfig b.ok{color:var(--d-ok)}.sfig b.warn{color:var(--d-accent-ink)}.sfig b.fault{color:var(--d-bad)}

/* ── Panels ─────────────────────────────────────────────────────────────── */
.panel{background:var(--d-panel);border:1px solid var(--d-line);border-radius:12px;margin-bottom:14px;
  overflow:hidden}
.pt{display:flex;align-items:center;gap:9px;padding:13px 18px;border-bottom:1px solid var(--d-line);
  font-family:var(--f-head);font-weight:600;font-size:13px;letter-spacing:.01em;color:var(--d-t1);
  text-transform:none}
.pt .r{margin-left:auto;font-family:var(--f-mono);font-size:9px;letter-spacing:.06em;
  color:var(--d-t6);font-weight:400}
.pb{padding:16px 18px}

/* Tier 2 — needs a person. The orange rail, and nowhere else. */
.needs{border-left:3px solid var(--d-accent)}
.needs .pt{color:var(--d-t1)}
.needs .pt .count{margin-left:0;font-family:var(--f-mono);font-size:9px;font-weight:600;
  letter-spacing:.1em;background:var(--d-accent);color:var(--d-on-accent);border-radius:999px;
  padding:2px 8px}
.railcard{display:flex;background:var(--d-panel);border:1px solid var(--d-line);border-radius:12px;
  overflow:hidden}
.railcard>.rail{flex:0 0 4px;background:var(--d-line-strong)}
.railcard.sev1>.rail{background:var(--d-bad)}
.railcard.sev2>.rail{background:var(--d-accent)}
.railcard.breached{border-color:var(--d-bad)}
.railcard>.rb{flex:1;min-width:0;padding:14px 16px}

/* ── Tier 3 — evidence. Quiet on purpose. ───────────────────────────────── */
.tscroll{overflow-x:auto}
table{border-collapse:collapse;width:100%;font-family:var(--f-mono);font-size:11px}
th{background:transparent;font-family:var(--f-mono);font-size:8.5px;font-weight:600;letter-spacing:.13em;
  text-transform:uppercase;color:var(--d-t6);text-align:left;padding:8px 12px;
  border-bottom:1px solid var(--d-line);white-space:nowrap;position:sticky;top:0;z-index:2}
th:first-child,td:first-child{padding-left:18px}
th:last-child,td:last-child{padding-right:18px}
td{padding:8px 12px;border-bottom:1px solid var(--d-line-soft);white-space:nowrap;color:var(--d-t3)}
tbody tr:hover,table tr:hover{background:var(--d-panel-2)}
thead tr:hover,tr:has(th):hover{background:transparent}
td.id{font-family:var(--f-mono);font-size:11px;color:var(--d-t2)}
td.n{font-family:var(--f-mono);text-align:right;font-variant-numeric:tabular-nums}
td.w{white-space:normal;color:var(--d-t5);min-width:220px;font-family:var(--f-sans);font-size:12.5px}

.log{font-family:var(--f-mono);font-size:10.5px;line-height:1.85;padding:12px 18px;
  max-height:230px;overflow-y:auto;color:var(--d-t3)}
.log div{white-space:pre-wrap;display:flex;gap:8px;align-items:baseline}
.log .t{color:var(--d-t6);flex:0 0 auto}
.log .k{flex:0 0 84px;font-weight:500}
.log .k.g,.log .g{color:var(--d-ok)}
.log .k.y,.log .y{color:var(--d-accent-ink)}
.log .k.r,.log .r{color:var(--d-bad)}
.log .k.b{color:var(--d-info)}
.log .body{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--d-t5)}

/* ── Pills, chips, dots ─────────────────────────────────────────────────── */
.pill{font-family:var(--f-mono);font-size:9px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;
  padding:2px 8px;border:1px solid;border-radius:999px;display:inline-block;line-height:1.5}
.pill.ok{color:var(--d-ok);border-color:var(--d-ok-border)}
.pill.deg,.pill.warn{color:var(--d-accent-ink);border-color:var(--d-accent)}
.pill.fault{color:var(--d-bad);border-color:var(--d-bad)}
.pill.info{color:var(--d-info);border-color:var(--d-info)}
.pill.off{color:var(--d-t6);border-color:var(--d-line)}
.pill.solid{border-color:transparent;background:var(--d-accent);color:var(--d-on-accent);font-weight:600}
.pill.solid.fault{background:var(--d-bad);color:var(--d-on-danger)}

.chip{font-family:var(--f-mono);font-size:8.5px;letter-spacing:.02em;padding:2px 6px;border-radius:4px;
  background:var(--d-chip-bg);color:var(--d-chip-fg);transition:background .2s var(--ease)}
.chip.ok{background:var(--d-chip-bg);color:var(--d-chip-fg)}
.chip.pend{background:var(--d-holding-chip);color:var(--d-on-accent)}
.chip.dead{background:var(--d-bad);color:var(--d-on-danger)}
.chip.new{animation:pop .32s var(--ease)}
@keyframes pop{0%{transform:translateY(8px);opacity:0}100%{transform:none;opacity:1}}
.chips{display:flex;flex-wrap:wrap;gap:4px;min-height:44px;align-content:flex-start}

.pchip{font-family:var(--f-mono);font-size:9.5px;padding:4px 9px;border-radius:999px;
  background:var(--d-panel-2);color:var(--d-t3)}
.pchip.act{color:var(--d-t2)}
.pchip.deg{background:var(--d-accent);color:var(--d-on-accent);font-weight:600}
.plist{display:flex;flex-wrap:wrap;gap:6px}

.dot{width:8px;height:8px;border-radius:999px;flex:0 0 8px;background:var(--d-dot-off);display:inline-block}
.dot.ok{background:var(--d-ok)}.dot.warn{background:var(--d-accent)}
.dot.fault{background:var(--d-bad)}.dot.off{background:var(--d-dot-off)}
.dot.pulse{animation:drishti-pulse 2s infinite}
.dot.pulse.fast{animation-duration:1.4s}

/* ── Buttons ────────────────────────────────────────────────────────────── */
.btn{font-family:var(--f-sans);font-size:12.5px;font-weight:500;color:var(--d-t1);background:transparent;
  border:1px solid var(--d-line-strong);border-radius:8px;padding:8px 14px;
  transition:background .12s var(--ease),color .12s var(--ease),border-color .12s var(--ease)}
.btn:hover{background:var(--d-panel-2)}
/* Primary is orange fill and hover DARKENS. Never lighten — a lightening hover
   reads as a disabled state on this ground. */
.btn.pri{background:var(--d-accent);color:var(--d-on-accent);border-color:transparent;font-weight:600;
  padding:10px 16px}
.btn.pri:hover{background:var(--d-accent-hover);color:var(--d-on-accent)}
.btn.dgr{border-color:var(--d-bad);color:var(--d-bad)}
.btn.dgr:hover{background:var(--d-bad);color:var(--d-on-danger)}
.btn.wrn{border-color:var(--d-accent);color:var(--d-accent-ink)}
.btn.wrn:hover{background:var(--d-accent);color:var(--d-on-accent)}
.btn.mono{font-family:var(--f-mono);font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  padding:6px 12px}
.btn.micro{font-size:11.5px;padding:3px 8px;border-radius:6px}
.btn:disabled{opacity:.4;cursor:default}
.btn:disabled:hover{background:transparent}

/* ── Layout helpers ─────────────────────────────────────────────────────── */
.two{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:14px}
.split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,420px);gap:14px;align-items:start}
.split.narrow{grid-template-columns:minmax(0,1fr) minmax(0,340px)}
.split.wide{grid-template-columns:minmax(0,1.35fr) minmax(0,1fr)}
@media(max-width:1100px){
  .two,.split,.split.narrow,.split.wide{grid-template-columns:minmax(0,1fr)}
}
.stack{display:flex;flex-direction:column;gap:14px}
.stack.tight{gap:10px}
.row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.grow{flex:1;min-width:0}
.right{margin-left:auto}
.small{font-size:12.5px}
.mt{margin-top:12px}
.dim{color:var(--d-t6)}

/* ── Node / lease board ─────────────────────────────────────────────────── */
.board{display:grid;gap:12px;padding:16px 18px;grid-template-columns:repeat(auto-fit,minmax(232px,1fr))}
.board.big{grid-template-columns:repeat(auto-fit,minmax(268px,1fr))}
.nd{border:1px solid var(--d-line);border-radius:8px;background:var(--d-panel-3);padding:16px 18px;
  transition:opacity .32s var(--ease),border-color .32s var(--ease)}
.nd.draining{border-color:var(--d-accent)}
.nd.dead{opacity:.68;border-color:var(--d-bad)}
.nd-h{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.nd-h b{font-family:var(--f-mono);font-size:13px;font-weight:600;color:var(--d-t1)}
.nd-h .pill{margin-left:auto}
.nd-m{font-family:var(--f-mono);font-size:10px;color:var(--d-t4);margin-bottom:8px}
.nd-cu{display:flex;align-items:baseline;gap:6px;margin:10px 0 8px}
.nd-cu b{font-family:var(--f-mono);font-size:24px;font-weight:600;line-height:1;color:var(--d-t1);
  font-variant-numeric:tabular-nums}
.nd-cu span{font-family:var(--f-mono);font-size:11px;color:var(--d-t4)}
.nd-cu .right{font-family:var(--f-mono);font-size:11px;color:var(--d-t4)}
.cu{height:5px;background:var(--d-panel-2);border-radius:999px;margin-bottom:12px;overflow:hidden}
.cu i{display:block;height:100%;background:var(--d-info);transition:width .32s var(--ease)}
.cu i.hot{background:var(--d-accent)}.cu i.crit{background:var(--d-bad)}
.nd-lbl{font-family:var(--f-mono);font-size:8.5px;letter-spacing:.13em;color:var(--d-t6);
  text-transform:uppercase;margin-bottom:6px}

/* The holding pen is transient state, so it is the one sanctioned dashed
   border in the console. */
.holding{border:1px dashed var(--d-accent);border-radius:12px;background:transparent;padding:16px 18px;
  grid-column:1/-1;margin-bottom:14px}
.holding .nd-h b{color:var(--d-accent-ink);font-family:var(--f-head);font-size:14px;letter-spacing:0}
.holding .chips{min-height:0}

/* ── Queue rows (alerts, approvals, intercepts) ─────────────────────────── */
.q{border-bottom:1px solid var(--d-line-soft);padding:13px 18px;display:flex;gap:14px;
  align-items:flex-start;transition:background .12s var(--ease)}
.q:last-child{border-bottom:0}
.q:hover{background:var(--d-panel-2)}
.q-b{flex:1;min-width:0}
.q-h{display:flex;align-items:center;gap:8px;margin-bottom:4px;flex-wrap:wrap}
.q-h b{font-family:var(--f-head);font-weight:600;font-size:15px;color:var(--d-t1)}
.q-m{font-family:var(--f-mono);font-size:10px;color:var(--d-t4)}
.q-d{font-size:12.5px;color:var(--d-t3);margin-top:6px;max-width:80ch;line-height:1.6}
.q-a{display:flex;flex-direction:column;gap:7px;align-items:stretch;flex:0 0 auto}
.q-age{font-family:var(--f-mono);font-size:11px;color:var(--d-t5);margin-left:auto}
.q-age.breach{color:var(--d-bad);font-weight:600}
.q.done{opacity:.5}
.reason{font-size:12.5px;color:var(--d-t3);background:var(--d-panel-2);
  border-left:2px solid var(--d-accent);padding:8px 11px;margin-top:8px;border-radius:0 6px 6px 0}

.spi{border:1px solid var(--d-line);border-radius:8px;background:var(--d-panel-3);padding:13px 16px;
  margin-bottom:10px}
.spi-h{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.spi-h b{font-family:var(--f-head);font-weight:600;font-size:14px;color:var(--d-t1)}
.spi-h code{font-family:var(--f-mono);font-size:9.5px;color:var(--d-t6)}
.spi-h .pill{margin-left:auto}

/* ── Timeline (investigation) ───────────────────────────────────────────── */
.tl{position:relative;padding:4px 0 4px 0;display:flex;flex-direction:column;gap:14px}
.tl::before{content:"";position:absolute;left:7px;top:8px;bottom:8px;width:1px;background:var(--d-line)}
.tl-e{display:flex;gap:14px;align-items:baseline;position:relative}
.tl-e .tdot{flex:0 0 15px;width:15px;height:15px;border-radius:999px;border:2px solid var(--d-accent);
  background:var(--d-panel-3);position:relative;z-index:1;align-self:flex-start}
.tl-e .tdot.last{background:var(--d-accent)}
.tl-e .tdot.low{border-color:var(--d-dot-off)}
.tl-t{flex:0 0 62px;font-family:var(--f-mono);font-size:11px;color:var(--d-t3)}
.tl-c{flex:0 0 90px;font-family:var(--f-mono);font-size:11px;color:var(--d-t2)}
.tl-p{flex:1;min-width:160px;font-size:12.5px;color:var(--d-t3)}
.tl-n{font-family:var(--f-mono);font-size:11px;color:var(--d-t4)}

/* ── Bars (probability, occupancy, thresholds) ──────────────────────────── */
.bar{height:4px;background:var(--d-panel-2);border-radius:999px;overflow:hidden;flex:1;min-width:60px}
.bar i{display:block;height:100%;background:var(--d-accent);transition:width .32s var(--ease)}
.bar i.info{background:var(--d-info)}
.bar i.ok{background:var(--d-ok)}
.rank{flex:0 0 18px;width:18px;height:18px;border-radius:999px;display:flex;align-items:center;
  justify-content:center;font-family:var(--f-mono);font-size:9.5px;font-weight:600;
  background:var(--d-info);color:var(--d-on-danger)}
.rank.top{background:var(--d-accent);color:var(--d-on-accent)}

/* ── Notes, empties, errors ─────────────────────────────────────────────── */
 /* The rule spans the panel; the prose does not. Padding, rather than
    max-width, keeps the measure near 88ch without the border stopping short of
    the panel edge and reading as a rendering fault. */
.note{font-family:var(--f-sans);font-size:12.5px;color:var(--d-t5);line-height:1.6;
  padding:13px 18px;padding-right:max(18px, calc(100% - 88ch));border-top:1px solid var(--d-line)}
.note code{font-family:var(--f-mono);font-size:11px;color:var(--d-t4)}
.gov{border-left:2px solid var(--d-accent);background:var(--d-panel-2);padding:10px 12px;
  font-size:12.5px;color:var(--d-t3);line-height:1.6;border-radius:0 6px 6px 0}
.empty{padding:22px 18px;color:var(--d-t5);font-size:12.5px;line-height:1.7}
.empty b{display:block;color:var(--d-t2);font-weight:500;margin-bottom:2px}
.err{padding:13px 16px;border:1px solid var(--d-bad);border-radius:12px;color:var(--d-t2);
  background:var(--d-panel);font-size:12.5px;line-height:1.6;margin-bottom:14px;
  border-left:3px solid var(--d-bad)}
.synthetic{color:var(--d-accent-ink);font-family:var(--f-mono);font-size:8.5px;
  border:1px solid var(--d-accent);border-radius:999px;padding:1px 6px;margin-left:6px}
a.plain{color:var(--d-link)}
a.plain:hover{text-decoration:underline}
form.inline{display:inline}
.htmx-request .pt .r::after{content:" · refreshing";color:var(--d-accent-ink)}

/* ── Fields ─────────────────────────────────────────────────────────────── */
input,select,textarea{background:var(--d-panel-3);border:1px solid var(--d-line);border-radius:8px;
  color:var(--d-t2);font-family:var(--f-mono);font-size:11px;padding:8px 10px;
  transition:border-color .12s var(--ease)}
input:focus,select:focus,textarea:focus{border-color:var(--d-line-strong)}
input.active,select.active{border-color:var(--d-line-strong)}
label{display:block;font-family:var(--f-mono);font-size:9px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--d-t6);margin:12px 0 4px}
.qrow{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;margin-bottom:14px}
.qrow label{margin:0 0 4px}
.qrow input{min-width:280px}
.qrow .w{min-width:150px}

/* ── The old flat KPI strip. Kept for any view that still uses it, restyled
      to read as tier 3 rather than as a headline. ────────────────────────── */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:14px;
  background:var(--d-panel);border:1px solid var(--d-line);border-radius:12px;
  padding:16px 18px;margin-bottom:14px}
.kpi i{display:block;font-family:var(--f-mono);font-size:8.5px;letter-spacing:.13em;color:var(--d-t6);
  text-transform:uppercase;font-style:normal;margin-bottom:6px}
.kpi b{font-family:var(--f-mono);font-size:26px;font-weight:600;display:block;line-height:1;
  color:var(--d-t1)}
.kpi b.ok{color:var(--d-ok)}.kpi b.warn{color:var(--d-accent-ink)}.kpi b.fault{color:var(--d-bad)}
.kpi u{text-decoration:none;display:block;font-family:var(--f-mono);font-size:10px;color:var(--d-t4);
  margin-top:6px}
.kpi b u{display:inline;font-size:13px;margin-left:4px}

/* ── Map / scatter panel ────────────────────────────────────────────────── */
.mapwrap{position:relative;height:340px;border-radius:8px;border:1px solid var(--d-line);
  background:var(--d-panel-3);overflow:hidden}
.mapwrap .cam{position:absolute;width:8px;height:8px;border-radius:999px}
.legend{display:flex;gap:14px;flex-wrap:wrap;padding:10px 18px;border-top:1px solid var(--d-line);
  font-family:var(--f-mono);font-size:9.5px;letter-spacing:.06em;color:var(--d-t5)}
.legend span{display:flex;align-items:center;gap:6px}
.legend .dot{width:7px;height:7px;flex:0 0 7px}

/* ── The projector (deployment profiles) ────────────────────────────────── */
.proj{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:0}
@media(max-width:1100px){.proj{grid-template-columns:minmax(0,1fr)}}
.proj-in{padding:16px 18px;border-right:1px solid var(--d-line)}
.proj-out{padding:16px 18px;background:var(--d-panel-2)}
.tog{display:flex;justify-content:space-between;align-items:center;padding:9px 0;
  border-bottom:1px solid var(--d-line-soft);font-size:12.5px;color:var(--d-t3)}
.tog:last-of-type{border-bottom:0}
.tog span.cu-v{font-family:var(--f-mono);font-size:10px;color:var(--d-t6);margin-left:7px}
.sw{width:34px;height:18px;border-radius:999px;background:var(--d-panel-3);
  border:1px solid var(--d-line);position:relative;flex:0 0 34px}
.sw i{position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:999px;
  background:var(--d-dot-off);transition:left .2s var(--ease),background .2s var(--ease)}
.sw.on{border-color:var(--d-ok-border)}.sw.on i{left:18px;background:var(--d-ok)}
.chain{font-family:var(--f-mono);font-size:11px;line-height:2.1;color:var(--d-t4)}
.chain b{color:var(--d-t1);font-weight:600}
.chain .big{font-size:26px;color:var(--d-accent-ink);font-weight:600;letter-spacing:-.02em}
.chain hr{border:0;border-top:1px solid var(--d-line);margin:10px 0}

/* ── CIA — monitoring & command ─────────────────────────────────────────── */
.ciasplit{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,380px);gap:14px;align-items:start}
@media (max-width:1180px){.ciasplit{grid-template-columns:minmax(0,1fr)}}
.ciagrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(224px,1fr));gap:12px}

.ciatile{border:1px solid var(--d-line);border-radius:8px;background:var(--d-panel-3);
  display:flex;flex-direction:column;overflow:hidden;transition:border-color .2s var(--ease)}
.ciatile.live{border-color:var(--d-ok-border)}
.ciatile.hot{border-color:var(--d-accent)}
.ciatile.down{border-color:var(--d-bad)}
.ciatile-h{display:flex;align-items:center;gap:7px;padding:8px 10px;border-bottom:1px solid var(--d-line);
  font-family:var(--f-mono);font-size:10.5px;color:var(--d-t3);overflow:hidden;white-space:nowrap}
.ciatile-h b{overflow:hidden;text-overflow:ellipsis;font-weight:500;color:var(--d-t2)}
.ciatile-f{display:flex;align-items:center;gap:7px;padding:7px 10px;border-top:1px solid var(--d-line);
  font-family:var(--f-mono);font-size:9.5px;color:var(--d-t5)}
.ciatile-f .right{margin-left:auto}
.ciavid{width:100%;aspect-ratio:16/9;background:var(--d-video);display:block;object-fit:contain}

.ciafocus{border:1px solid var(--d-line-strong);border-radius:12px;background:var(--d-panel);
  margin-bottom:14px;overflow:hidden}
.ciafocus-h{display:flex;align-items:center;gap:9px;padding:12px 16px;border-bottom:1px solid var(--d-line);
  font-family:var(--f-mono);font-size:11px;color:var(--d-t3)}
.ciafocus-h .right{margin-left:auto}
.ciafocus .ciavid{aspect-ratio:16/9;max-height:44vh}
.ciafocus-f{display:flex;align-items:center;gap:9px;padding:10px 16px;border-top:1px solid var(--d-line);
  font-family:var(--f-mono);font-size:10px;color:var(--d-t5)}
.ciafocus-f .right{margin-left:auto}
.ciaerr{padding:8px 16px;font-family:var(--f-mono);font-size:10.5px;color:var(--d-accent-ink);
  border-top:1px solid var(--d-line)}

/* Detection boxes over the video surface. */
.detbox{position:absolute;border:2px solid var(--d-accent);border-radius:2px}
.detbox .lbl{position:absolute;top:-16px;left:-2px;background:var(--d-accent);color:var(--d-on-accent);
  font-family:var(--f-mono);font-size:9.5px;padding:1px 5px;white-space:nowrap}

/* The detection popup. Fixed, bottom-right: an alert must be visible without
   stealing focus from a feed the operator is already watching. */
.ciapop{position:fixed;right:18px;bottom:18px;width:380px;max-width:calc(100vw - 36px);
        z-index:60;background:var(--d-panel);border:1px solid var(--d-bad);border-radius:12px;
        overflow:hidden}
.ciapop-h{display:flex;align-items:center;gap:8px;padding:11px 14px;border-bottom:1px solid var(--d-line);
          background:var(--d-panel-2);font-family:var(--f-head);font-weight:600;font-size:13px;
          color:var(--d-t1)}
.ciapop-h .right{margin-left:auto;font-family:var(--f-mono);font-size:10px;font-weight:400;
  color:var(--d-t5)}
/* The live-detection pip. Drawn in CSS rather than in the popup's markup so
   cia.js keeps rendering exactly the HTML it renders today. */
.ciapop-h::before{content:"";width:7px;height:7px;border-radius:999px;flex:0 0 7px;
  background:var(--d-bad);animation:drishti-pulse 1.4s infinite}
.ciapop-t{width:100%;border-collapse:collapse;font-family:var(--f-mono);font-size:11px}
.ciapop-t th{position:static;text-align:left;width:88px;color:var(--d-t5);font-weight:400;
  letter-spacing:.06em;text-transform:none;font-size:10px;padding:4px 14px;vertical-align:top;
  border:0;background:transparent}
.ciapop-t td{padding:4px 14px;word-break:break-word;white-space:normal;border:0;color:var(--d-t2)}
.ciapop-t tr:hover{background:transparent}
.ciapop-caveat{margin:8px 14px 0;padding:10px 12px;border-left:2px solid var(--d-accent);
               background:var(--d-panel-2);font-size:12.5px;color:var(--d-t3);line-height:1.6;
               border-radius:0 6px 6px 0}
.ciapop-f{display:flex;align-items:center;gap:8px;padding:12px 14px}
.ciapop-f .right{margin-left:auto}
.ciasplit label{display:block;font-family:var(--f-mono);font-size:9px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--d-t6);margin:12px 0 4px}
.ciasplit label input,.ciasplit label select{width:100%}
.ciasplit input[type=file]{padding:6px;font-size:11px}

/* ── Officer block, login ───────────────────────────────────────────────── */
.officer{display:flex;align-items:center;gap:8px;font-size:12px;border:1px solid var(--d-line);
  border-radius:8px;padding:5px 10px;color:var(--d-t2);white-space:nowrap;flex:0 0 auto}
.officer b{font-size:12px;font-weight:600;color:var(--d-t1)}
.officer span{font-family:var(--f-mono);font-size:9.5px;color:var(--d-t5);white-space:nowrap}
.officer .btn{padding:3px 8px;font-size:11px}

body.login-page{overflow:auto;display:flex;align-items:center;justify-content:center;min-height:100vh;
  padding:24px}
.login{width:min(420px, calc(100vw - 32px))}
.login input{width:100%}
.login .pt b{font-family:var(--f-head);letter-spacing:.16em}

/* ── Responsive. Two real targets: the wall and a ~1440px laptop. ───────── */
.menu{display:none;font-size:18px;padding:0 3px;color:var(--d-t3)}
@media(max-width:900px){
  nav{position:fixed;left:0;top:var(--hdr);bottom:0;width:var(--navw);transform:translateX(-100%);
    transition:transform .2s var(--ease);z-index:30}
  nav.open{transform:none}.menu{display:block}
  .hs{display:none}
  header{gap:12px;padding:0 12px}
  .view{padding:16px 14px 60px}
}
/* The header carries more than the design's does, because the five figures the
   old strip held are still on it. They give way from the least urgent inwards
   as the window narrows, rather than pushing the page into a horizontal
   scrollbar. */
@media(max-width:1700px){ .hs div:nth-child(5){display:none} }
@media(max-width:1560px){ .hs div:nth-child(2){display:none} }
@media(max-width:1420px){ .hs div:nth-child(1){display:none} }
@media(max-width:1240px){ .hs{display:none} .officer span{display:none} }
@media(max-width:1080px){ .prof .mono{display:none} }

/* ═══════════════════════════════════════════════════════════════════════════
   GIS map.

   MapLibre paints its own canvas from the style object map.js builds out of
   these same custom properties, so the only thing this sheet owns is the
   chrome around the canvas -- and overriding MapLibre's default controls and
   popup, which ship light and would otherwise be two white rectangles on a
   navy screen.
   ═══════════════════════════════════════════════════════════════════════════ */

.gis-panel { padding-bottom: 0; }

#gis-map {
  /* Tall enough to be a map rather than a strip, capped so the controls under
     it stay on screen on a laptop. */
  height: clamp(380px, 58vh, 720px);
  width: 100%;
  border-radius: 8px;
  overflow: hidden;
  background: var(--p3);
  border: 1px solid var(--line);
}

.gis-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  padding: 10px 2px 12px;
  font: 500 12px/1.2 var(--f-sans); color: var(--dim);
}
.gis-bar label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.gis-bar input[type="checkbox"] { accent-color: var(--warn); cursor: pointer; }
.gis-bar select { margin-left: 6px; }
.gis-sep { flex: 1 1 auto; }

.gis-scrub {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 2px 2px;
  font: 500 12px/1.2 var(--f-sans); color: var(--dim);
}
.gis-scrub input[type="range"] { flex: 1 1 auto; accent-color: var(--warn); }
.gis-scrub-label { font-family: var(--f-mono); color: var(--fg2); min-width: 200px; }

.gis-legend { flex-wrap: wrap; }
.gis-swatch {
  display: inline-block; width: 18px; height: 0; margin-right: 6px;
  vertical-align: middle; border-top: 3px solid var(--off);
}
.gis-swatch.ok    { border-top-color: var(--ok); }
.gis-swatch.warn  { border-top-color: var(--warn); }
.gis-swatch.fault { border-top-color: var(--fault); }
.gis-swatch.dash  { border-top-style: dashed; }

/* The gap report. Deliberately not styled as an error: "nine cameras have no
   coordinates" is a fact about the registry, not a failure of the map, and
   painting it red would train people to ignore it. */
.gis-meta {
  display: flex; flex-wrap: wrap; gap: 8px 18px;
  padding: 10px 2px; border-top: 1px solid var(--line);
  font: 500 12px/1.35 var(--f-sans); color: var(--dim);
}
.gis-meta b { color: var(--fg); font-weight: 600; }
.gis-gap { color: var(--warn); }
.gis-credit { display: block; margin-top: 4px; color: var(--dim2); font-size: 11px; }

.gis-nogl {
  display: flex; flex-direction: column; justify-content: center; gap: 10px;
  height: 100%; padding: 28px; text-align: center;
  font: 500 13px/1.5 var(--f-sans); color: var(--dim);
}
.gis-nogl b { color: var(--fg); font: 600 15px/1.3 var(--f-head); }

/* Popups. */
.gp { font: 500 12px/1.45 var(--f-sans); color: var(--text); min-width: 250px; }
.gp-h {
  font: 600 13px/1.3 var(--f-head); color: var(--fg);
  padding-bottom: 6px; margin-bottom: 6px; border-bottom: 1px solid var(--line);
}
.gp-r { display: flex; justify-content: space-between; gap: 16px; padding: 2px 0; }
.gp-r span { color: var(--dim2); }
.gp-r b { color: var(--fg2); font-weight: 600; font-family: var(--f-mono); text-align: right; }

/* MapLibre's own chrome, which ships light-themed. */
.maplibregl-popup-content {
  background: var(--panel); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .32); padding: 12px 14px;
}
.maplibregl-popup-tip { display: none; }
.maplibregl-popup-close-button { color: var(--dim); font-size: 18px; padding: 2px 7px; }
.maplibregl-popup-close-button:hover { background: transparent; color: var(--fg); }
.maplibregl-ctrl-group {
  background: var(--panel); border: 1px solid var(--line); box-shadow: none;
}
.maplibregl-ctrl-group button + button { border-top: 1px solid var(--line); }
.maplibregl-ctrl-group button .maplibregl-ctrl-icon { filter: var(--gis-icon-filter, none); }
.maplibregl-ctrl-scale {
  background: transparent; border-color: var(--line); color: var(--dim);
  font: 500 11px/1.3 var(--f-mono);
}
/* The control glyphs are black PNGs. On the navy theme they need inverting;
   on light they are already correct. */
:root { --gis-icon-filter: invert(1) opacity(.75); }
:root[data-theme="light"] { --gis-icon-filter: none; }
