/* LinkFlow — control room.
   A source rail on the left, a program output in the middle, a tally lamp on every row.
   Depth comes from surface lightness and hairlines, not from drop shadows; groups are
   separated by unlit voids rather than borders. */

:root {
  /* Unlit rack through raised panel. */
  --ground:   #0b0d10;
  --panel:    #14181d;
  --panel-hi: #1a2027;
  --hair:     #232a32;
  --hair-hi:  #303945;

  --ink:   #e6ebf0;
  --ink-2: #97a3b1;
  --ink-3: #828e9c;

  /* Tally triad. Each reserved by law; none of the three is ever decoration.
     live  = traffic is flowing / healthy
     fault = disabled or failing
     est   = this number is an Analytics Engine estimate, not an exact count */
  --live:  #35d07f;
  --fault: #ff453a;
  --est:   #f5a524;

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

  --r: 6px;
  --r-sm: 4px;
  --rail-w: 244px;
  --ease: cubic-bezier(.16, 1, .3, 1);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }

body {
  background: var(--ground);
  color: var(--ink);
  font: 14px/1.5 var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Every figure in this interface is a measurement; they must align in columns. */
  font-variant-numeric: tabular-nums;
  caret-color: var(--ink);
  overflow: hidden;
}

[hidden] { display: none !important; }

/* Boot state machine.
   Neither panel carries `hidden` any more: every visibility decision is here, so the
   worst case when app.js never executes at all - a stalled request, a 404, a parse
   error, a CSP block, a renamed element that aborts the script - is a visible login
   form rather than a black rectangle with no explanation.
     pending  markup default, app.js has not run yet
     probing  app.js is alive and asking who the visitor is
     login    no session      app  signed in      fault  broken, with a reason */
#login, #app { display: none; }
[data-boot="pending"] #login,
[data-boot="probing"] #login,
[data-boot="login"] #login,
[data-boot="fault"] #login { display: grid; }
[data-boot="app"] #app { display: grid; }

/* Laid out but unpainted while the session probe is in flight, so the real reveal
   costs no reflow and a healthy boot never flashes the login form. */
[data-boot="pending"] #login,
[data-boot="probing"] #login { visibility: hidden; }

/* The one watchdog that survives app.js never running at all, and therefore the one
   that cannot be written in JavaScript. A healthy boot leaves `pending` in its first
   statement, so this only ever fires when nothing is running. */
@keyframes lf-reveal { to { visibility: visible; } }
[data-boot="pending"] #login { animation: lf-reveal 1ms linear 1400ms forwards; }

/* Reachable only when the probe outruns the watchdog. A line of text is the honest
   answer there: something is still in flight. The login form stays unpainted, because
   showing it to an operator who turns out to be signed in would be its own small lie. */
.msg-wait { display: none; }
[data-boot="probing"][data-slow] .msg-wait {
  display: grid;
  position: fixed;
  inset: 0;
  place-content: center;
  margin: 0;
  padding: 24px;
  font: 500 11px/1.6 var(--mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ink-3);
  text-align: center;
}

.msg-fault {
  margin: 0; padding: 10px 12px; border-radius: var(--r-sm); font-size: 12.5px;
  color: var(--est);
  border: 1px solid color-mix(in srgb, var(--est) 35%, transparent);
  background: color-mix(in srgb, var(--est) 9%, transparent);
}

/* Browser surfaces belong to the design system too. */
::selection { background: rgba(53, 208, 127, .28); color: #fff; }
* { scrollbar-width: thin; scrollbar-color: var(--hair-hi) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--hair-hi); border-radius: 99px; border: 3px solid var(--ground); }
*::-webkit-scrollbar-thumb:hover { background: #3d4855; }

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

h1 { margin: 0; font-size: 19px; font-weight: 600; letter-spacing: -.01em; }

/* Engraved panel label. Small, tracked, mono — the placard under a gauge. */
.placard {
  font: 500 11px/1 var(--mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}

.note { font-size: 12px; color: var(--ink-3); }

/* The one reserved-by-law colour: this figure is sampled, not counted. */
.est {
  font: 500 11px/1 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--est);
  border: 1px solid color-mix(in srgb, var(--est) 40%, transparent);
  border-radius: 99px;
  padding: 3px 7px;
}

/* ── controls ─────────────────────────────────────────────────────────── */

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

input[type="email"], input[type="password"], input[type="url"], input[type="text"],
input[type="search"], select, textarea {
  background: var(--ground);
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  padding: 9px 11px;
  width: 100%;
  color: var(--ink);
  transition: border-color .12s var(--ease), background .12s var(--ease);
}
input::placeholder { color: var(--ink-3); }
input:hover, select:hover { border-color: var(--hair-hi); }
input:focus, select:focus, textarea:focus { border-color: var(--ink-3); background: #0e1216; }
select {
  appearance: none;
  padding-right: 30px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%),
                    linear-gradient(135deg, var(--ink-3) 50%, transparent 50%);
  background-position: right 13px center, right 8px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}

button { cursor: pointer; border: 1px solid transparent; border-radius: var(--r-sm); }
button:disabled { opacity: .45; cursor: not-allowed; }

.btn-primary {
  background: var(--ink);
  color: #0a0d11;
  font-weight: 600;
  padding: 9px 16px;
  display: inline-flex; align-items: center; gap: 7px;
  transition: background .12s var(--ease), transform .12s var(--ease);
}
.btn-primary:hover { background: #fff; }
.btn-primary:active { transform: translateY(1px); }

.btn-ghost {
  background: transparent;
  border-color: var(--hair);
  color: var(--ink-2);
  padding: 8px 14px;
  transition: border-color .12s var(--ease), color .12s var(--ease);
}
.btn-ghost:hover { border-color: var(--hair-hi); color: var(--ink); }
.btn-sm { padding: 6px 11px; font-size: 13px; }
.btn-wide { width: 100%; margin-top: 10px; }

.icon-btn {
  background: transparent; border-color: transparent; color: var(--ink-3);
  width: 30px; height: 30px; display: grid; place-items: center; flex: none;
  transition: color .12s var(--ease), background .12s var(--ease);
}
.icon-btn:hover { color: var(--ink); background: var(--panel-hi); }

.ico { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; flex: none; }
#i-overview path { fill: currentColor; stroke: none; }

.switch { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--ink-2); cursor: pointer; white-space: nowrap; }
.switch input { width: auto; accent-color: var(--live); cursor: pointer; }

/* Tally lamp. Green while traffic flows, red when a link is withdrawn. */
.tally { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--ink-3); }
.tally[data-state="live"] { background: var(--live); box-shadow: 0 0 0 3px color-mix(in srgb, var(--live) 16%, transparent); animation: breathe 3.2s ease-in-out infinite; }
.tally[data-state="fault"] { background: var(--fault); box-shadow: 0 0 0 3px color-mix(in srgb, var(--fault) 16%, transparent); }
@keyframes breathe { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }
@media (prefers-reduced-motion: reduce) { .tally[data-state="live"] { animation: none } }

/* ── brand mark ───────────────────────────────────────────────────────── */
.mark {
  display: flex; align-items: center; gap: 9px;
  font: 600 12px/1 var(--mono); letter-spacing: .18em; color: var(--ink);
}
.mark-lamp { width: 7px; height: 7px; border-radius: 50%; background: var(--live); box-shadow: 0 0 0 3px color-mix(in srgb, var(--live) 16%, transparent); }

/* ── login ────────────────────────────────────────────────────────────── */
.login { height: 100dvh; display: grid; place-items: center; padding: 24px; overflow: auto;
  background: radial-gradient(120% 90% at 50% 0%, #10151a 0%, var(--ground) 62%); }
.login-panel {
  width: min(360px, 100%);
  display: grid; gap: 14px;
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r);
  padding: 28px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
.login-panel h1 { margin-bottom: 2px; }
.login-panel label { display: grid; gap: 6px; font-size: 12.5px; color: var(--ink-2); }
.login-panel .btn-primary { justify-content: center; margin-top: 4px; }
.login-foot { text-align: center; margin: 2px 0 0; }
.msg-error { margin: 0; color: var(--fault); font-size: 13px; }

/* ── shell ────────────────────────────────────────────────────────────── */
.shell { display: grid; grid-template-columns: var(--rail-w) 1fr; height: 100dvh; }

/* ── source rail ──────────────────────────────────────────────────────── */
.rail {
  background: var(--panel);
  border-right: 1px solid var(--hair);
  display: flex; flex-direction: column;
  min-height: 0;
}
.rail-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 16px 14px; border-bottom: 1px solid var(--hair); }
.rail-close { display: none; }

.rail-nav { padding: 10px 8px; display: grid; gap: 2px; }

/* Every row keeps its icon and its status dot in the same column, so the rail scans
   as a column of states rather than a ragged list. */
.nav-row {
  display: grid;
  grid-template-columns: 17px 1fr auto;
  align-items: center; gap: 10px;
  background: transparent; color: var(--ink-2);
  padding: 8px 10px; width: 100%; text-align: left;
  border-radius: var(--r-sm);
  transition: background .12s var(--ease), color .12s var(--ease);
}
.nav-row:hover { background: var(--panel-hi); color: var(--ink); }
/* Selection is material, not hue: the panel lifts and grows a white edge. The tally
   colours stay reserved for state. */
.nav-row[aria-current="true"] {
  background: var(--panel-hi);
  color: var(--ink);
  box-shadow: inset 2px 0 0 var(--ink);
}
.nav-count { font: 500 11px/1 var(--mono); color: var(--ink-3); }

.rail-section { display: flex; align-items: center; justify-content: space-between; padding: 16px 16px 8px; }
.rail-add { width: 24px; height: 24px; }

.rail-projects { flex: 1; overflow-y: auto; padding: 0 8px 8px; display: grid; gap: 2px; align-content: start; min-height: 0; }

.proj {
  display: grid;
  grid-template-columns: 8px 1fr auto 7px;
  align-items: center; gap: 10px;
  background: transparent; color: var(--ink-2);
  padding: 8px 10px; width: 100%; text-align: left;
  border-radius: var(--r-sm);
  transition: background .12s var(--ease), color .12s var(--ease);
}
.proj:hover { background: var(--panel-hi); color: var(--ink); }
.proj[aria-current="true"] { background: var(--panel-hi); color: var(--ink); box-shadow: inset 2px 0 0 var(--ink); }
.proj-chip { width: 8px; height: 8px; border-radius: 2px; }
.proj-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proj-n { font: 500 11px/1 var(--mono); color: var(--ink-3); }

.rail-foot { border-top: 1px solid var(--hair); padding: 10px 12px; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.health { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-3); min-width: 0; }
.health span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── command bar ──────────────────────────────────────────────────────── */
.stage { display: flex; flex-direction: column; min-width: 0; min-height: 0; }

.cmd {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--hair);
  background: var(--panel);
  flex: none;
}
.rail-open { display: none; }

.cmd-form { flex: 1; display: flex; align-items: center; gap: 8px; min-width: 0; position: relative; }
.cmd-ico { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--ink-3); pointer-events: none; }
#cmd-input { padding-left: 36px; }
#cmd-project { width: auto; min-width: 130px; flex: none; }
.cmd-go { flex: none; }
.cmd-range { display: flex; align-items: center; gap: 12px; flex: none; }
#range { width: auto; }

.banner, .flash {
  margin: 12px 20px 0; padding: 10px 14px; border-radius: var(--r-sm); font-size: 13px;
  border: 1px solid;
}
.banner { color: var(--fault); border-color: color-mix(in srgb, var(--fault) 35%, transparent); background: color-mix(in srgb, var(--fault) 9%, transparent); }
.flash { color: var(--live); border-color: color-mix(in srgb, var(--live) 35%, transparent); background: color-mix(in srgb, var(--live) 9%, transparent); display: flex; align-items: center; gap: 10px; }
.flash code { flex: 1; }

.stage-body { flex: 1; overflow-y: auto; padding: 20px; min-height: 0; }

/* The one authored moment: switching source or section reads as a program transition. */
.view { display: grid; gap: 16px; animation: take .32s var(--ease) both; }
@keyframes take { from { opacity: 0; transform: translateY(6px); filter: blur(3px); } }
@media (prefers-reduced-motion: reduce) { .view { animation: none } }

/* ── panels ───────────────────────────────────────────────────────────── */
/* Groups are separated by unlit ground showing through the gaps. No dividers. */
.panel {
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r);
  padding: 16px;
  min-width: 0;
  /* A single hairline of light along the top edge — the machined edge of a rack panel. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035);
}
.panel-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.panel-head .placard { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.panel-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; align-items: start; }

.filter { max-width: 260px; padding: 6px 10px; font-size: 13px; }

/* ── live tap ─────────────────────────────────────────────────────────── */
/* A ticker, not a chart. Newest on top, one row per click, hairline-separated so it reads
   as a running log rather than a table - the panel is watched, not scanned. */
.panel-live .panel-head { margin-bottom: 8px; }
.live-state {
  display: flex; align-items: center; gap: 7px;
  font: 500 11px/1 var(--mono); letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-3);
}
.live-total { font: 600 12px/1 var(--mono); color: var(--ink-2); }

.live-rows { max-height: 260px; overflow-y: auto; overflow-x: hidden; }
/* A detail sheet must not have to be read through a seven-row window. While one is open
   the list is allowed to grow; it snaps back the moment it is closed. */
.live-rows:has(.live-entry[data-open="1"]) { max-height: 560px; }
.live-empty {
  margin: 0; padding: 20px 2px;
  font: 500 11px/1 var(--mono); letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-3);
}

.live-entry { border-top: 1px solid var(--hair); }
.live-entry:first-child { border-top: 0; }
/* Expansion is expressed by material, like every other selection in this interface:
   the raised surface and the white edge, never a hue. */
.live-entry[data-open="1"] {
  background: var(--panel-hi);
  box-shadow: inset 2px 0 0 var(--ink);
}

.live-row {
  /* A real button, reset back to a row. Fixed tracks, not max-content: each row is its
     own grid, so an intrinsic width would size per row and the columns would go ragged
     down the panel. The referrer is the only value with no natural length, so it is the
     one that absorbs the slack. */
  display: grid;
  grid-template-columns: 66px 104px 30px 118px minmax(0, 1fr) 72px;
  align-items: center; gap: 12px;
  width: 100%;
  padding: 6px 2px;
  background: transparent;
  border: 0;
  border-radius: 0;
  text-align: left;
  font: 12px/1.35 var(--mono);
  color: var(--ink-2);
  white-space: nowrap;
  transition: color .12s var(--ease);
}
.live-row:hover { color: var(--ink); }
.live-row > * { overflow: hidden; text-overflow: ellipsis; }
.live-row .lr-slug { color: var(--ink); }
.live-row .lr-time { color: var(--ink-3); }
/* Anchored to the panel edge so the column reads as a right-hand margin of metadata
   rather than a sixth ragged field. */
.live-row .lr-dev { color: var(--ink-3); text-align: right; }
/* A bot click is still a click and stays on the record, but it recedes: the operator is
   watching for people. */
.live-entry[data-bot="1"] .live-row,
.live-entry[data-bot="1"] .live-row .lr-slug { color: var(--ink-3); }

/* The whole record, opened on demand. Auto-fill rather than a fixed column count, so it
   reflows to one column on a phone without a second rule. */
.live-detail {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 12px 22px;
  padding: 4px 2px 16px;
}
.ld-item { display: grid; gap: 4px; min-width: 0; }
/* The user agent is the one field with no useful upper bound, so it takes the full width
   and is allowed to wrap where nothing else may. */
.ld-wide { grid-column: 1 / -1; }
.ld-val {
  font: 12px/1.45 var(--mono);
  color: var(--ink);
  overflow-wrap: anywhere;
}

/* The panel's one authored moment: a row arrives lit by the live tally colour and settles
   into the surface, so an arrival is caught peripherally without anything moving. */
@keyframes lr-arrive {
  from { background: color-mix(in srgb, var(--live) 15%, transparent); }
  to { background: transparent; }
}
.live-row { animation: lr-arrive 1400ms ease-out; }
@media (prefers-reduced-motion: reduce) { .live-row { animation: none; } }

@media (max-width: 860px) {
  .live-row { grid-template-columns: 62px minmax(0, 1fr) 30px; }
  .live-row .lr-ip, .live-row .lr-ref, .live-row .lr-dev { display: none; }
}

/* ── link focus ───────────────────────────────────────────────────────── */
/* The identity card for one link. Reads as a patched-in source on the rack: same
   panel material, but a white edge so it is unmistakably the current subject. */
.focus {
  display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap;
  background: var(--panel); border: 1px solid var(--hair); border-radius: var(--r);
  padding: 14px 16px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035), inset 2px 0 0 var(--ink);
}
.focus-back {
  display: inline-flex; align-items: center; gap: 4px;
  background: transparent; border-color: var(--hair); color: var(--ink-2);
  padding: 6px 11px 6px 7px; font-size: 12.5px; flex: none;
  transition: border-color .12s var(--ease), color .12s var(--ease);
}
.focus-back:hover { border-color: var(--hair-hi); color: var(--ink); }
.focus-body { flex: 1; min-width: 0; display: grid; gap: 6px; }
.focus-id { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.focus-id code { font-size: 14px; padding: 4px 9px; }
.focus-dest {
  color: var(--ink-2); font-size: 12.5px; text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-bottom: 1px solid transparent;
}
.focus-dest:hover { color: var(--ink); border-bottom-color: var(--hair-hi); }
.focus-meta { display: flex; gap: 18px; flex-wrap: wrap; margin: 2px 0 0; }
.focus-meta div { display: grid; gap: 2px; }
.focus-meta dt { font: 500 11px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.focus-meta dd { margin: 0; font-size: 12.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.focus-actions { display: flex; gap: 6px; flex: none; }
@media (max-width: 560px) { .focus-actions { width: 100%; } .focus-actions button { flex: 1; } }

/* ── meters ───────────────────────────────────────────────────────────── */
.meters { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; }
.meter {
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r);
  padding: 14px 16px 16px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035);
  display: grid; gap: 4px; align-content: start;
  min-width: 0;
}
.meter-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.meter-head .placard { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.meter-value { font: 600 27px/1.1 var(--mono); letter-spacing: -.02em; overflow: hidden; text-overflow: ellipsis; }
.meter-sub { font-size: 11.5px; color: var(--ink-3); }
.meter-sub b { color: var(--est); font-weight: 500; }

/* ── plots ────────────────────────────────────────────────────────────── */
.plot { position: relative; height: 268px; }
.plot-sm { height: 216px; }

/* ── bar rows ─────────────────────────────────────────────────────────── */
/* CSS rows rather than a canvas bar chart: long labels stay readable and each row is a
   real hit target for drilling down. */
.bars { display: grid; gap: 3px; }
.bar {
  position: relative; display: flex; align-items: center; gap: 12px;
  padding: 7px 10px; border-radius: var(--r-sm); overflow: hidden;
  background: transparent; border: 0; width: 100%; text-align: left; color: var(--ink-2);
  transition: color .12s var(--ease);
}
.bar:hover { color: var(--ink); }
.bar-fill { position: absolute; inset: 0 auto 0 0; background: var(--panel-hi); border-radius: var(--r-sm); }
.bar-label, .bar-value { position: relative; }
.bar-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-value { font: 500 12.5px/1 var(--mono); color: var(--ink-3); }

/* ── tables ───────────────────────────────────────────────────────────── */
.scroll-x { overflow-x: auto; margin: 0 -16px; padding: 0 16px; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { text-align: left; padding: 9px 12px; white-space: nowrap; border-bottom: 1px solid var(--hair); }
th { font: 500 11px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); padding-bottom: 10px; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:not(:first-child):hover td { background: var(--panel-hi); }
td.wrap { max-width: 46ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-2); }
td.num { font-family: var(--mono); }

code {
  font: 500 12.5px/1.4 var(--mono);
  background: var(--ground);
  border: 1px solid var(--hair);
  padding: 2px 6px; border-radius: var(--r-sm);
}

/* The short code is the way into a link's own traffic, so it has to read as a control
   rather than as a label. */
.slug-open { background: transparent; border: 0; padding: 0; cursor: pointer; }
.slug-open code { transition: border-color .12s var(--ease), color .12s var(--ease); }
.slug-open:hover code { border-color: var(--hair-hi); color: #fff; }

.row-actions { display: flex; gap: 4px; justify-content: flex-end; }
.pill { font: 500 11px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase; padding: 4px 8px; border-radius: 99px; border: 1px solid; }
.pill.off { color: var(--fault); border-color: color-mix(in srgb, var(--fault) 38%, transparent); }
.pill.pending { color: var(--est); border-color: color-mix(in srgb, var(--est) 38%, transparent); }
.pill.live { color: var(--live); border-color: color-mix(in srgb, var(--live) 32%, transparent); }

.empty { color: var(--ink-3); padding: 34px 16px; text-align: center; font-size: 13px; }

/* ── modal ────────────────────────────────────────────────────────────── */
dialog {
  border: 1px solid var(--hair); border-radius: var(--r);
  background: var(--panel); color: var(--ink);
  padding: 24px; width: min(560px, calc(100vw - 32px));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
dialog::backdrop { background: rgba(5, 7, 10, .72); }
#modal-form { display: grid; gap: 13px; }
#modal-form h1 { font-size: 17px; }
#modal-form h2 { margin: 6px 0 0; font: 500 11px/1 var(--mono); letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3); }
#modal-form label { display: grid; gap: 6px; font-size: 12.5px; color: var(--ink-2); }
#modal-form p { margin: 0; }
.modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 6px; }
.hops { display: grid; gap: 2px; }

/* ── responsive ───────────────────────────────────────────────────────── */
@media (max-width: 960px) {
  .shell { grid-template-columns: 1fr; }

  /* Closed drawer: visibility, not just transform, so its controls leave the tab order. */
  .rail {
    position: fixed; inset: 0 auto 0 0; width: var(--rail-w); z-index: 30;
    transform: translateX(-100%); visibility: hidden;
    transition: transform .26s var(--ease), visibility .26s var(--ease);
    box-shadow: 6px 0 18px -12px rgba(0, 0, 0, .95);
  }
  .shell[data-rail="open"] .rail { transform: none; visibility: visible; }
  .rail-close, .rail-open { display: grid; }
  .rail-scrim { position: fixed; inset: 0; background: rgba(5, 7, 10, .6); z-index: 20; }

  /* An explicit two-row grid. The destination field owns a full row; the project and
     the action share the next one, so nothing is ever clipped at the right edge. */
  .cmd {
    display: grid; align-items: center; gap: 10px; padding: 10px 14px;
    grid-template-columns: auto 1fr;
    grid-template-areas: "menu range" "form form";
  }
  .rail-open { grid-area: menu; }
  .cmd-range { grid-area: range; justify-content: flex-end; }
  .cmd-form {
    grid-area: form; display: grid; gap: 8px;
    grid-template-columns: 1fr auto;
    grid-template-areas: "input input" "project go";
  }
  .cmd-ico { display: none; }
  #cmd-input { grid-area: input; padding-left: 11px; }
  #cmd-project { grid-area: project; width: 100%; min-width: 0; }
  .cmd-go { grid-area: go; }

  .stage-body { padding: 14px; }
  .banner, .flash { margin: 10px 14px 0; }
  .meter-value { font-size: 23px; }
  .plot { height: 220px; }
  td.wrap { max-width: 34ch; }
}

@media (max-width: 560px) {
  .meters { grid-template-columns: 1fr 1fr; gap: 10px; }
  .meter { padding: 12px; }
  .panel { padding: 13px; }
  .scroll-x { margin: 0 -13px; padding: 0 13px; }
  .panel-head { flex-wrap: wrap; }
  .filter { max-width: none; flex: 1 1 100%; order: 3; }
  td.wrap { max-width: 26ch; }
}

/* The focus card sits above the section views, so it needs its own separation from
   whatever section is showing beneath it. */
.stage-body > .focus { margin-bottom: 16px; }
