/* Ledger UI.
   Flat, ruled and square: hairline rules separate things instead of boxes
   with rounded corners and shadows. Colour follows a 70/20/10 split —
   neutral surfaces, ink text and rules, and one accent for things you can
   act on. Health colours are the only other colours, and they are used
   where something is wrong, so a healthy page is quiet and a problem stands
   out without competing with decoration. */

@font-face {
  font-family: "Atkinson Hyperlegible Next";
  src: url("/static/fonts/AtkinsonHyperlegibleNext.ttf") format("truetype");
  font-weight: 200 800;
  font-display: swap;
}
@font-face {
  font-family: "Atkinson Hyperlegible Mono";
  src: url("/static/fonts/AtkinsonHyperlegibleMono.ttf") format("truetype");
  font-weight: 200 800;
  font-display: swap;
}

:root {
  /* Atkinson Hyperlegible was drawn for low-vision readers: every glyph that
     is easy to confuse (1/l/I, 0/O, 5/S) is made distinct, which is exactly
     the failure mode of a page full of percentages and circuit IDs. The mono
     cut is reserved for identifiers. */
  --font-sans: "Atkinson Hyperlegible Next", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Atkinson Hyperlegible Mono", ui-monospace, Menlo, Consolas, monospace;

  /* Dark: graphite and warm paper-white. */
  --bg:       #16181b;
  --panel:    #1c1f23;
  --border:   #2d3137;
  --rule-strong: #4a4f57;
  --unk:      #626870;
  --text:     #e7e4dc;
  --muted:    #9b9993;
  --accent:   #86abcc;
  --green:    #5f9f73;
  --red:      #e2574e;
  --yellow:   #d4a53d;
  --hover:    #202429;
  --sel:      #233142;
  /* Kept for code that still names --blue: it is the accent, not a hue. */
  --blue:     var(--accent);
  --pop-name: var(--text);
  --router-name: var(--text);
  --up-track: #3a4a3f;
  /* Amber text needs to be darker than amber fills to read on light
     surfaces; dark mode uses one amber for both. */
  --yellow-text: var(--yellow);
  --nodata:   #6a7078;
  --backdrop: rgba(10,11,13,.72);
}
[data-theme="light"] {
  /* Light: printed page. Tuned for washed-out panels as well as good ones:
     every distinction that matters is carried by a clear step in lightness,
     not by a faint tint near white, because cheap or badly calibrated
     displays flatten the top of the range first. */
  --bg:       #f6f4ef;
  --panel:    #ffffff;
  --border:   #b8b3a7;
  --rule-strong: #4f4c46;
  --unk:      #8a867c;
  --text:     #111315;
  --muted:    #4a4d51;
  --accent:   #174a78;
  /* Green is dark and amber is light, so the two stay apart in lightness
     even when a display loses saturation. */
  --green:    #1f6b3a;
  --red:      #b3261e;
  --yellow:   #b87400;
  --yellow-text: #7d5000;
  --hover:    #e7e3d9;
  --sel:      #cddcec;
  --up-track: #a3c7ac;
  --nodata:   #6f6b62;
  --backdrop: rgba(17,19,21,.45);
}
/* Row tints for a sub-100% POP need real strength on a light surface to
   survive a washed-out display; dark mode keeps the subtler default. */
[data-theme="light"] .pl-row.health-u        { background: color-mix(in srgb, var(--yellow) 22%, transparent); }
[data-theme="light"] .pl-row.health-ou       { background: color-mix(in srgb, var(--red) 20%, transparent); }
[data-theme="light"] .pl-row.health-u:hover  { background: color-mix(in srgb, var(--yellow) 30%, transparent); }
[data-theme="light"] .pl-row.health-ou:hover { background: color-mix(in srgb, var(--red) 28%, transparent); }
[data-theme="light"] .pl-row.pgcard-expanded { background: var(--sel); }

* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  font-family: var(--font-sans);
  font-size: 13.5px;
  line-height: 1.45;
  background: var(--bg);
  color: var(--text);
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  font-variant-numeric: tabular-nums;
}
code { font-family: var(--font-mono); font-size: .92em; }
/* No bold anywhere: hierarchy comes from size, ink versus muted grey, rules,
   and the tab underline. This also cancels browser-default bold. */
h1, h2, h3, strong, b, th { font-weight: 400; }
.muted { color: var(--muted); }
abbr[data-tip] { text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ── Header ────────────────────────────────────────────────── */
#perf-banner {
  background: var(--red);
  color: #fff;
  padding: 7px 28px;
  font-size: 13px;
  font-weight: 400;
  flex-shrink: 0;
}
#perf-banner[hidden] { display: none; }
/* Logo, headline figure, and links share one baseline grid: every child
   aligns to the bottom edge, so nothing is nudged into place by eye. */
/* The header is kept short so the POP ledger below it can show every POP
   on one screen. */
#hdr {
  background: var(--bg);
  padding: 12px 28px 8px;
  display: flex;
  align-items: flex-end;
  gap: 28px;
  flex-shrink: 0;
}
/* Two versions of the logo, both with transparent backgrounds: the dark
   wordmark for the light theme and the reversed (white) wordmark for the dark
   theme, so neither needs a backing box. Both files are cropped tight to
   their artwork, so the same height renders the same visible size. */
.brand-logo-wrap {
  flex: 0 0 auto;
  align-self: center;
  display: flex;
  align-items: center;
}
.brand-logo { display: block; height: 40px; width: auto; }
.brand-logo.on-light { display: none; }
[data-theme="light"] .brand-logo.on-light { display: block; }
[data-theme="light"] .brand-logo.on-dark  { display: none; }
.brand-title { line-height: 1; }
.brand-app {
  color: var(--muted);
  font-size: 12.5px;
  margin-bottom: 4px;
}
/* The headline figure is always ink: a big number in amber or red reads as
   muddy, especially on the light theme. Its health is carried by the same
   round status mark the ledger uses, set in front of the number. */
.bb-pct {
  font-size: 34px;
  font-weight: 400;
  letter-spacing: -.02em;
  cursor: default;
  min-height: 34px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.bb-pct.ok, .bb-pct.u, .bb-pct.ou { color: var(--text); }
.bb-pct:empty::before { display: none; }
.bb-pct::before {
  content: "";
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--unk);
  flex: 0 0 auto;
}
.bb-pct.ok::before { background: var(--green); }
.bb-pct.u::before  { background: var(--yellow); }
.bb-pct.ou::before { background: var(--red); }
.hdr-side {
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}
.hdr-links {
  display: flex;
  gap: 20px;
  align-items: baseline;
}
.link-btn {
  background: none;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  font: inherit;
  font-size: 12.5px;
  text-decoration: underline;
  text-decoration-color: var(--border);
  text-underline-offset: 3px;
}
.link-btn:hover { color: var(--text); text-decoration-color: currentColor; }

/* ── Status bar ────────────────────────────────────────────── */
#statusBar {
  display: flex;
  gap: 18px;
  font-size: 11.5px;
  color: var(--muted);
}
#statusBar span { white-space: nowrap; }

/* ── Navigation ────────────────────────────────────────────── */
#fbar {
  background: var(--bg);
  border-bottom: 1px solid var(--rule-strong);
  padding: 0 28px;
  display: flex;
  align-items: flex-end;
  gap: 22px;
  flex-shrink: 0;
}
#fbar .btn[data-v] {
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--muted);
  font-size: 13.5px;
  padding: 6px 0 5px;
  margin-bottom: -1px;
}
#fbar .btn[data-v]:hover  { color: var(--text); background: transparent; }
#fbar .btn[data-v].active { border-bottom-color: var(--text); color: var(--text); font-weight: 400; background: transparent; }

/* Window selector: one segmented control. The active segment is the only
   filled accent on the page. */
.window-controls, .tl-windows {
  display: flex;
  margin-left: auto;
  margin-bottom: 6px;
}
.tl-windows { margin: 0; }
.btn[data-window] {
  border: 1px solid var(--border);
  border-left-width: 0;
  color: var(--muted);
  padding: 3px 10px;
  font-size: 12px;
}
.btn[data-window]:first-child { border-left-width: 1px; }
.btn[data-window].active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
  font-weight: 400;
}

#reviewBar {
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  padding: 10px 28px;
  display: none;
  flex-direction: column;
  gap: 8px;
  flex-shrink: 0;
}
.review-summary-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}
.review-title { color: var(--muted); font-size: 12.5px; }
#stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 16px;
  margin-left: auto;
}
.stat-pill { color: var(--muted); font-size: 12.5px; }
.stat-pill strong { color: var(--text); font-weight: 400; }
.stat-pill.s-r strong { color: var(--red); }
.stat-pill.s-y strong { color: var(--yellow-text); }
#reviewControls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}
#reviewControls .btn[data-f] { border-left-width: 0; }
#reviewControls .btn[data-f]:first-child { border-left-width: 1px; }

/* ── Buttons and fields ────────────────────────────────────── */
.btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  padding: 4px 11px;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 12.5px;
}
.btn:hover        { background: var(--hover); }
.btn.active       { background: var(--sel); color: var(--text); font-weight: 400; }
.btn.sm           { padding: 2px 8px; font-size: 12px; }
.btn.danger       { border-color: var(--red); color: var(--red); }
.btn.danger:hover { background: var(--red); color: #fff; }
.btn.accent       { border-color: var(--accent); color: var(--accent); }
.btn.accent:hover { background: var(--accent); color: var(--bg); }
.btn.save         { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 400; }
.btn.save:hover   { filter: brightness(1.08); }
.btn:disabled     { opacity: .45; cursor: not-allowed; }

#qsearch, #lsinput, select, textarea {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 4px 8px;
  font-family: var(--font-sans);
  font-size: 12.5px;
}
#qsearch { margin-left: auto; width: 220px; }
#lsinput { width: 100%; margin-bottom: 6px; }
select   { width: 100%; padding: 5px 8px; }
textarea { width: 100%; padding: 6px 8px; resize: vertical; min-height: 56px; }
#qsearch:focus, #lsinput:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); }
/* Read-only role: review fields stay visible so the values can be read, but
   are clearly inert rather than looking like controls that failed. */
select:disabled, textarea:disabled {
  color: var(--muted);
  background: transparent;
  cursor: default;
  opacity: 1;
  -webkit-text-fill-color: var(--muted);
}
@media (max-width: 720px) {
  .review-summary-row { flex-direction: column; gap: 6px; }
  #stats { justify-content: flex-start; margin-left: 0; }
  #qsearch { margin-left: 0; width: 100%; }
}

/* ── About modal ──────────────────────────────────────────── */
#about-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: var(--backdrop);
  align-items: center;
  justify-content: center;
}
#about-overlay.open { display: flex; }
#about-modal {
  background: var(--bg);
  border: 1px solid var(--rule-strong);
  max-width: 640px;
  width: calc(100% - 40px);
  max-height: calc(100vh - 80px);
  overflow-y: auto;
  padding: 26px 32px 24px;
  position: relative;
}
#about-modal h2 { font-size: 18px; margin-bottom: 16px; padding-right: 60px; }
#about-modal h3 {
  font-size: 13.5px;
  margin: 20px 0 5px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
#about-modal h3:first-of-type { margin-top: 0; }
#about-modal p, #about-modal ul { font-size: 13px; line-height: 1.6; margin-bottom: 6px; }
#about-modal ul { margin-left: 18px; }
#about-modal .about-swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-right: 5px;
  vertical-align: middle;
}
#about-close, .drawer-close, .flyout-close {
  position: absolute;
  background: transparent;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  font: inherit;
  font-size: 12.5px;
  text-decoration: underline;
  text-underline-offset: 3px;
}
#about-close { top: 28px; right: 32px; }
#about-close:hover, .drawer-close:hover, .flyout-close:hover { color: var(--text); }

/* ── Main layout ───────────────────────────────────────────── */
#main { display: flex; flex: 1; overflow: hidden; }
#routerView { flex: 1; overflow: hidden; display: none; flex-direction: column; }
.router-grid-scroll { flex: 1; overflow-y: auto; padding: 0 28px 12px; display: flex; flex-direction: column; }

/* ── ISIS review list ──────────────────────────────────────── */
#lpanel { width: 56%; overflow-y: auto; border-right: 1px solid var(--border); }
table { width: 100%; border-collapse: collapse; }
thead th {
  position: sticky; top: 0;
  background: var(--bg);
  border-bottom: 1px solid var(--rule-strong);
  padding: 8px 10px 6px;
  text-align: left;
  font-size: 12px;
  color: var(--muted);
  font-weight: 400;
  white-space: nowrap;
}
tbody tr { border-bottom: 1px solid var(--border); cursor: pointer; }
tbody tr:hover    { background: var(--hover); }
tbody tr.selected { background: var(--sel); }
td { padding: 6px 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.c-st  { width: 24px; text-align: center; }
.c-chk { width: 24px; text-align: center; }
.c-chk input { cursor: pointer; accent-color: var(--accent); }
tr.bulk-checked td { background: var(--sel); }
#bulkBar {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  background: var(--panel);
  border-bottom: 1px solid var(--rule-strong);
}
#bulkBar[hidden] { display: none; }
#bulkBar .bulk-count { font-weight: 400; margin-right: 4px; }
#bulkBar #bulkNote { flex: 1; min-width: 160px; }
.c-cid { max-width: 280px; font-family: var(--font-mono); font-size: 12.5px; }
.c-t, .c-d { color: var(--muted); }
.c-s   { text-align: center; color: var(--muted); }
.u  { color: var(--yellow-text); }
.nr { color: var(--muted); }
.ok { color: var(--green); }
.ou { color: var(--red); }
.ob { color: var(--yellow-text); font-size: 11.5px; }
thead th.sortable { cursor: pointer; user-select: none; }
thead th.sortable:hover { color: var(--text); }
.si { color: var(--text); }

/* ── Review detail panel ───────────────────────────────────── */
#rpanel { width: 44%; overflow-y: auto; padding: 18px 22px; }
.empty  { color: var(--muted); text-align: center; margin-top: 48px; }
.dc     { font-size: 15px; font-weight: 400; margin-bottom: 6px; word-break: break-all; font-family: var(--font-mono); }
.dt     { color: var(--muted); font-size: 12.5px; line-height: 1.9; margin-bottom: 4px; }
/* Section labels are headings over a rule, not coloured caps. */
.slbl {
  display: block;
  font-size: 13px;
  font-weight: 400;
  color: var(--text);
  margin: 20px 0 8px;
  padding: 0 0 4px;
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  background: transparent;
  width: 100%;
  text-align: left;
  font-family: var(--font-sans);
}
.slbl.major { margin-top: 26px; }
.rgrp { display: flex; margin-bottom: 10px; }
.ropt {
  display: flex; align-items: center;
  cursor: pointer; padding: 4px 11px;
  border: 1px solid var(--border);
  font-size: 12.5px;
}
.ropt + .ropt { border-left-width: 0; }
.ropt:hover { background: var(--hover); }
.ropt:has(input:checked) { background: var(--sel); font-weight: 400; }
.ropt input { display: none; }
.review-card { padding: 4px 0 12px; margin-bottom: 4px; border-bottom: 1px solid var(--border); }
.review-card .notes-lbl { font-size: 12px; font-weight: 400; color: var(--muted); margin: 10px 0 5px; }
.review-card .save-row { margin-top: 8px; display: flex; justify-content: flex-end; }
.review-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.field label { display: block; font-size: 12px; font-weight: 400; margin-bottom: 5px; }
.derived-value { font-size: 12px; margin-top: 3px; color: var(--muted); }
.derived-value.nines-count  { color: var(--red); }
.derived-value.nines-review { color: var(--yellow-text); }
@media (max-width: 920px) {
  .review-grid { grid-template-columns: 1fr; }
}

/* ── Session lists ─────────────────────────────────────────── */
.sitem, .uitem {
  border-bottom: 1px solid var(--border);
  padding: 7px 0;
  font-size: 12.5px;
}
.sitem-hd { display: flex; justify-content: space-between; align-items: center; }
.sitem-r  { font-weight: 400; font-family: var(--font-mono); font-size: 12px; }
.sitem-t  { color: var(--muted); margin-top: 2px; }
#lsearch  { margin-top: 10px; }
.uitem { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 5px 0; }
.uitem-info { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* ── POP ledger ────────────────────────────────────────────── */
/* One row per POP on a shared column template, so every figure lines up
   with the figure above it. The labels live once in the sticky header. */
/* Fit to screen: the ledger fills the view and every row shares the height
   equally (flex-grow), between a compact 21px and a comfortable 40px. With
   30 POPs on a laptop the rows compress so the whole backbone is visible
   without scrolling; on a tall display they relax. Only when even compact
   rows don't fit does the view scroll. */
.pop-ledger {
  /* Circuits gets the most flexible space: the largest POP has 31 circuits,
     and a wrapped second line of dots costs a whole row of height. */
  --pl-cols: 96px minmax(110px, .8fr) 160px minmax(140px, 1.3fr) 92px 80px 64px minmax(150px, 2fr) 64px;
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
.pl-head, .pl-row {
  display: grid;
  grid-template-columns: var(--pl-cols);
  column-gap: 16px;
  align-items: start;
  padding: 0 8px;
}
/* Every cell's first line is the same 19px line box, so text, the strip and
   the dots all centre on one line even when the circuit dots wrap. */
.pl-row > * { min-height: 19px; line-height: 19px; }
.pl-head {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg);
  border-bottom: 1px solid var(--rule-strong);
  padding-top: 8px;
  padding-bottom: 4px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.25;
}
.pl-row {
  border-bottom: 1px solid var(--border);
  padding-top: 1px;
  padding-bottom: 1px;
  cursor: pointer;
  flex: 1 0 auto;
  max-height: 40px;
  align-content: center;
}
.pl-row:hover { background: var(--hover); }
.pl-row.pgcard-expanded { background: var(--sel); }
/* In a ledger that is almost always healthy, a sub-100% POP has to be
   findable without reading every row: the whole row takes a faint tint of
   its health colour. Healthy rows stay untinted. */
.pl-row.health-u  { background: color-mix(in srgb, var(--yellow) 9%, transparent); }
.pl-row.health-ou { background: color-mix(in srgb, var(--red) 11%, transparent); }
.pl-row.health-u:hover  { background: color-mix(in srgb, var(--yellow) 15%, transparent); }
.pl-row.health-ou:hover { background: color-mix(in srgb, var(--red) 17%, transparent); }
.pl-code  { font-family: var(--font-mono); font-weight: 400; letter-spacing: .02em; }
.pl-name  { color: var(--muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-avail { display: flex; align-items: baseline; gap: 7px; white-space: nowrap; }
/* Healthy figures stay in ink; only a shortfall is coloured. */
.pl-pct   { font-size: 14px; font-weight: 400; }
.pl-pct.ok { color: var(--text); }
.pl-note  { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
.pl-note.alert { color: var(--red); font-weight: 400; }
.pl-strip { display: flex; flex-direction: column; justify-content: center; height: 19px; }
.pl-num   { text-align: right; }
.pl-none  { color: var(--muted); font-size: 12px; }
.pl-dots  { display: flex; flex-wrap: wrap; gap: 0 4px; align-items: center; align-content: flex-start; min-width: 0; }
.pl-dots > * { height: 19px; display: inline-flex; align-items: center; }
/* Ledger dots are a touch smaller than elsewhere so a 31-circuit POP fits on
   one line at laptop widths. */
.pl-dots  { column-gap: 3px; }
.pl-dots > .pg-dot { width: 7px; height: 7px; margin: 6px 0; }
.perf-metric         { white-space: nowrap; }
.perf-metric.pending { color: var(--muted); }
.perf-metric.good    { color: var(--text); }
.perf-metric.warn    { color: var(--yellow-text); }
.perf-metric.bad     { color: var(--red); font-weight: 400; }
@media (max-width: 1100px) {
  .pop-ledger { --pl-cols: 88px 160px minmax(120px, 1fr) 90px 78px 60px minmax(110px, 1fr) 60px; }
  .pl-head > :nth-child(2), .pl-name { display: none; }
}

/* Downtime strip: the selected window, left = start, right = now. The up
   portion is a quiet neutral-green track; red segments are the POP's actual
   down intervals; grey lead-in is before the POP's earliest history. */
.pg-timeline-track       { position: relative; height: 9px; background: color-mix(in srgb, var(--unk) 30%, transparent); overflow: hidden; }
.pg-timeline-track.known { background: var(--up-track); }
.pg-timeline-seg         { position: absolute; top: 0; bottom: 0; min-width: 4px; }
.pg-timeline-seg.down    { background: var(--red); }
.pg-timeline-seg.nodata  { background: var(--nodata); min-width: 0; }

/* Status dots are data marks, not decoration: round, one size, flat. */
.pg-dot     { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex-shrink: 0; cursor: default; }
.pg-dot[data-circuit-id] { cursor: pointer; }
.pg-dot.pinned { outline: 2px solid var(--text); outline-offset: 1px; }
.pg-dot.ok  { background: var(--green); }
.pg-dot.u   { background: var(--yellow); }
.pg-dot.ou  { background: var(--red); }
.pg-dot.unk { background: var(--unk); }
/* Word flags ("reboot", "unreviewed") sit on their own line under the value
   so they never push into the next column. */
.cell-flag  { display: block; color: var(--yellow-text); font-size: 11.5px; line-height: 1.2; }

#dot-tip {
  position: fixed;
  z-index: 10001;
  background: var(--text);
  color: var(--bg);
  font-size: 12px;
  padding: 4px 8px;
  pointer-events: none;
  white-space: pre-wrap;
  display: none;
  font-family: var(--font-sans);
}
#circuit-connector   { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 9995; overflow: visible; }
.circuit-line        { stroke: var(--text); stroke-width: 1.25; opacity: .5; fill: none; }
.circuit-line.pinned { stroke-width: 2; opacity: .9; }
.circuit-line.pinned.ok  { stroke: var(--green); }
.circuit-line.pinned.u   { stroke: var(--yellow); }
.circuit-line.pinned.ou  { stroke: var(--red); }
.circuit-line.pinned.unk { stroke: var(--unk); }

/* ── POP drawer ────────────────────────────────────────────── */
#drawerBackdrop {
  position: fixed;
  inset: 0;
  z-index: 9996;
  background: var(--backdrop);
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s linear;
}
#drawerBackdrop.open { opacity: 1; pointer-events: auto; }
#popDrawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(1160px, 95vw);
  z-index: 9997;
  background: var(--bg);
  border-left: 1px solid var(--rule-strong);
  display: flex;
  flex-direction: column;
  transform: translateX(101%);
  transition: transform .18s ease-out;
  visibility: hidden;
}
#popDrawer.open { transform: none; visibility: visible; }
.drawer-hd {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 18px 90px 12px 24px;
  border-bottom: 1px solid var(--rule-strong);
  flex-shrink: 0;
}
.drawer-title     { font-size: 18px; font-weight: 400; font-family: var(--font-mono); letter-spacing: .02em; }
.drawer-sub       { color: var(--muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer-avail     { margin-left: auto; display: flex; align-items: baseline; gap: 8px; white-space: nowrap; }
.drawer-avail-pct { font-size: 20px; font-weight: 400; }
.drawer-avail-pct.ok { color: var(--text); }
.drawer-avail-lbl { font-size: 12px; color: var(--muted); }
.drawer-close     { top: 22px; right: 24px; }
.drawer-body      { flex: 1; overflow-y: auto; padding: 16px 24px 28px; }

/* ── Drawer availability timeline ──────────────────────────── */
.tl { margin-bottom: 22px; }
.tl-hd {
  display: flex;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}
.tl-title  { font-size: 13.5px; font-weight: 400; }
.tl-legend { margin-left: auto; display: flex; align-items: center; gap: 5px; color: var(--muted); font-size: 12px; }
.tl-legend .tl-key { width: 10px; height: 8px; display: inline-block; }
.tl-legend .tl-key:not(:first-child) { margin-left: 10px; }
.tl-key.up     { background: var(--up-track); }
.tl-key.down   { background: var(--red); }
.tl-key.nodata { background: var(--nodata); }
/* label gutter | shared-axis track | percentage */
.tl-row, .tl-axis {
  display: grid;
  grid-template-columns: 200px 1fr 70px;
  align-items: center;
  column-gap: 14px;
}
.tl-row { padding: 3px 0; border-bottom: 1px solid var(--border); }
.tl-row:hover { background: var(--hover); }
.tl-lbl { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); }
.tl-row.pop     .tl-lbl { font-weight: 400; font-size: 13px; }
.tl-row.router  .tl-lbl { padding-left: 12px; }
/* Circuit IDs are long and their unique part is the suffix, so truncate from
   the left: direction:rtl puts the ellipsis at the start and keeps the tail. */
.tl-row.circuit .tl-lbl { color: var(--muted); padding-left: 24px; direction: rtl; text-align: left; }
.tl-track, .tl-track-axis { position: relative; height: 100%; }
.tl-track { height: 10px; overflow: hidden; background: color-mix(in srgb, var(--unk) 30%, transparent); }
.tl-row.pop .tl-track { height: 16px; }
.tl-track.known { background: var(--up-track); }
.tl-seg        { position: absolute; top: 0; bottom: 0; }
.tl-seg.down   { background: var(--red); }
.tl-seg.nodata { background: var(--nodata); }
.tl-pct     { font-size: 12px; text-align: right; }
.tl-pct.ok  { color: var(--text); }
.tl-pct.u   { color: var(--yellow-text); }
.tl-pct.ou  { color: var(--red); font-weight: 400; }
.tl-pct.unk { color: var(--muted); }
.tl-axis { height: 18px; border-bottom: 1px solid var(--rule-strong); }
.tl-track-axis { height: 18px; }
.tl-tick { position: absolute; top: 0; font-size: 11px; color: var(--muted); white-space: nowrap; }
.tl-tick.mid { transform: translateX(-50%); }
.tl-tick.end { transform: translateX(-100%); }
@media (max-width: 800px) {
  .tl-row, .tl-axis { grid-template-columns: 120px 1fr 56px; }
}

/* ── Drawer router sections ────────────────────────────────── */
.router-sec { margin-bottom: 24px; }
.router-hd {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 16px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--rule-strong);
}
.router-actions { display: flex; align-items: baseline; gap: 16px; min-width: 0; }
.router-name    { font-size: 14px; font-weight: 400; font-family: var(--font-mono); }
.router-sys-up  { font-size: 12px; font-weight: 400; color: var(--muted); font-family: var(--font-sans); }
.router-meta    { color: var(--muted); font-size: 12.5px; }
.router-collect-warn { color: var(--red); font-weight: 400; }
.window-token   { font: inherit; }
.circuit-grid {
  display: grid;
  /* The circuit ID gets the flexible width — its unique part is the suffix,
     so it wraps rather than truncates. Metric columns stay compact. */
  grid-template-columns: minmax(72px, .35fr) minmax(230px, 2fr) 90px 90px 82px 76px 62px 150px 60px;
}
.circuit-grid > div {
  padding: 6px 8px 6px 0;
  min-width: 0;
  border-bottom: 1px solid var(--border);
}
.cg-head { color: var(--muted); font-size: 12px; font-weight: 400; line-height: 1.3; white-space: nowrap; }
.mono-ell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-family: var(--font-mono); font-size: 12px; }
.circuit-link {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  color: var(--text);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.4;
  padding: 0;
}
/* Never truncate circuit IDs in the detail tables — the unique part is the
   suffix, so a cut ID is worse than a wrapped one. The map flyout keeps its
   own single-line override below. */
.circuit-grid .circuit-link { white-space: normal; word-break: break-all; }
.circuit-link:hover { color: var(--accent); text-decoration: underline; }
.perf-link { color: var(--accent); font-size: 12px; white-space: nowrap; text-underline-offset: 3px; }
.perf-link:hover { color: var(--text); }
.nowrap    { white-space: nowrap; color: var(--muted); }
.nowrap.ok { color: var(--text); }
.nowrap.u  { color: var(--yellow-text); }
.nowrap.ou { color: var(--red); }
@media (max-width: 800px) {
  .drawer-body { font-size: 12px; }
  .drawer-body .circuit-grid {
    grid-template-columns: minmax(56px, .35fr) minmax(150px, 2fr) 70px 74px 66px 62px 50px 110px 50px;
  }
}

/* ── Scrollbar ─────────────────────────────────────────────── */
::-webkit-scrollbar       { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); }
::-webkit-scrollbar-thumb:hover { background: var(--unk); }

/* ── Oregon POP map ────────────────────────────────────────── */
#mapView    { flex: 1; min-height: 0; }
.map-scroll { position: relative; flex: 1; min-height: 0; width: 100%; overflow: hidden; }
.map-toggle {
  position: absolute; top: 14px; right: 28px; z-index: 1;
  display: flex; align-items: center; gap: 6px;
  background: var(--bg); border: 1px solid var(--border); padding: 4px 9px;
  font-size: 12px; color: var(--muted); cursor: pointer; user-select: none;
}
.map-toggle input { cursor: pointer; accent-color: var(--accent); }
.or-map         { display: block; width: 100%; height: 100%; cursor: grab; touch-action: none; }
.or-map:active  { cursor: grabbing; }
/* non-scaling-stroke keeps outlines, dots, lines and label halos a constant
   on-screen weight at any zoom — only spacing changes as you zoom in. */
.or-outline { fill: var(--panel); stroke: var(--rule-strong); stroke-width: 1.25; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.map-pop        { cursor: pointer; }
.map-pop:focus  { outline: none; }
.map-dot        { stroke: var(--bg); stroke-width: 2; vector-effect: non-scaling-stroke; }
.map-dot.ok     { fill: var(--green); }
.map-dot.u      { fill: var(--yellow); }
.map-dot.ou     { fill: var(--red); }
.map-dot.unk    { fill: var(--unk); }
.map-pop:hover .map-dot, .map-pop:focus .map-dot { stroke: var(--text); stroke-width: 2.5; }
.map-count { fill: var(--bg); font-weight: 400; font-family: var(--font-sans); text-anchor: middle; pointer-events: none; user-select: none; }
.map-label {
  fill: var(--muted); font-family: var(--font-sans); pointer-events: none; user-select: none;
  paint-order: stroke; stroke: var(--panel); stroke-width: 3.5px; stroke-linejoin: round; vector-effect: non-scaling-stroke;
}
.map-pop:hover .map-label, .map-pop:focus .map-label { fill: var(--text); }
.map-edge path { fill: none; stroke-linecap: round; vector-effect: non-scaling-stroke; }
/* Healthy links are drawn in ink so the map is not a web of green; only a
   degraded or down link takes a status colour. */
.map-edge path:first-child     { stroke-width: 1.25; opacity: .5; }
.map-edge-hit                  { stroke: transparent; stroke-width: 10; cursor: pointer; }
.map-edge.ok  path:first-child { stroke: var(--muted); }
.map-edge.u   path:first-child { stroke: var(--yellow); opacity: .9; stroke-width: 2; }
.map-edge.ou  path:first-child { stroke: var(--red); opacity: 1; stroke-width: 2; }
.map-edge.unk path:first-child { stroke: var(--unk); opacity: .45; stroke-dasharray: 3 3; }
.map-edge:hover path:first-child { opacity: 1; stroke-width: 2.5; }

/* ── Map flyout ────────────────────────────────────────────── */
.map-flyout {
  position: fixed; z-index: 9998; min-width: 230px; max-width: 310px; max-height: 80vh; overflow: auto;
  background: var(--bg); border: 1px solid var(--rule-strong);
  padding: 12px 14px; color: var(--text); font-size: 12.5px;
}
.map-flyout[hidden] { display: none; }
.flyout-close       { top: 11px; right: 14px; font-size: 12px; }
.flyout-divider     { height: 1px; background: var(--border); margin: 12px -14px; }
.flyout-pop-hd      { display: flex; align-items: baseline; gap: 8px; padding-right: 44px; }
.flyout-pop-name    { font-weight: 400; font-size: 14px; }
.flyout-pop-code    { color: var(--muted); font-size: 12px; font-family: var(--font-mono); }
.flyout-avail       { display: flex; align-items: baseline; gap: 6px; margin: 6px 0 2px; }
.flyout-avail-pct   { font-size: 19px; font-weight: 400; }
.flyout-avail-pct.u  { color: var(--yellow-text); }
.flyout-avail-pct.ou { color: var(--red); }
.flyout-section-lbl { color: var(--muted); font-size: 12px; font-weight: 400; margin: 10px 0 4px; border-bottom: 1px solid var(--border); padding-bottom: 2px; }
.flyout-router      { display: flex; align-items: center; gap: 6px; padding: 1px 0; }
.flyout-router-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); font-size: 12px; }
.flyout-router .muted { flex: none; }
.flyout-circuit     { padding: 2px 0; }
.flyout-circuit-row { display: flex; align-items: center; gap: 6px; }
.flyout-circuit-row .circuit-link { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flyout-circuit-ends { margin: -1px 0 0 16px; font-size: 11.5px; }
.flyout-open        { margin-top: 10px; width: 100%; }
/* Share of the POP's circuits by health, shown in the flyout. */
.circuit-bar        { display: flex; width: 100%; height: 6px; margin-top: 6px; overflow: hidden; }
.circuit-bar span   { height: 100%; }
/* Review-state mark in the ISIS and reboot lists; colour comes from the
   cell's ok/u/ou/nr class. */
.st-mark      { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: currentColor; vertical-align: middle; }
.st-mark.open { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; }
/* Ledger column headers sort on click. The label keeps the header's quiet
   styling; the active column is ink with an arrow. The arrow slot has a
   fixed width so labels don't shift when the sort moves. */
.pl-sort {
  background: none;
  border: 0;
  padding: 0;
  color: inherit;
  font: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  white-space: nowrap;
}
.pl-sort:hover, .pl-sort.active { color: var(--text); }
.pl-sort .si { display: inline-block; width: .7em; color: var(--text); }
