/* triage-web styling. Static asset, no build step (§13.1).
 *
 * The palette, type and density are taken from the Claude Design bundle in design/ — those
 * files are the reference for layout, structure, spacing and states, and this is the
 * stylesheet that carries them. Tokens are named for their role so a view never reaches for
 * a raw oklch() value. */

:root {
  color-scheme: dark;

  /* ground */
  --bg: oklch(0.17 0.008 60);
  --bg-sunken: oklch(0.145 0.008 60);
  --surface: oklch(0.195 0.008 60);
  --surface-raised: oklch(0.235 0.008 60);

  /* rules, lightest to heaviest */
  --rule: oklch(0.27 0.008 60);
  --rule-mid: oklch(0.30 0.008 60);
  --rule-strong: oklch(0.40 0.008 60);

  /* ink, brightest to faintest */
  --ink-bright: oklch(0.95 0.006 85);
  --ink: oklch(0.92 0.006 85);
  --ink-soft: oklch(0.84 0.006 85);
  --ink-mid: oklch(0.72 0.008 70);
  --ink-dim: oklch(0.62 0.008 70);
  --ink-faint: oklch(0.55 0.008 70);

  --link: oklch(0.80 0.09 220);
  --link-hover: oklch(0.88 0.10 220);

  /* semantic: the four states a cell can be in, and the two alarms */
  --ok: oklch(0.84 0.11 150);
  --ok-dim: oklch(0.74 0.10 150);
  --ok-bg: oklch(0.28 0.045 150);
  --ok-border: oklch(0.40 0.05 150);

  --warn: oklch(0.86 0.11 78);
  --warn-strong: oklch(0.82 0.13 75);
  --warn-bg: oklch(0.30 0.07 75);
  --warn-border: oklch(0.50 0.09 75);

  --alarm: oklch(0.86 0.15 25);
  --alarm-bg: oklch(0.32 0.09 25);
  --alarm-border: oklch(0.34 0.10 25);

  --info-bg: oklch(0.28 0.05 245);
  --info-border: oklch(0.42 0.06 240);

  --sans: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 13px/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
}

::selection {
  background: oklch(0.36 0.09 75);
  color: oklch(0.97 0.006 85);
}

a {
  color: var(--link);
  text-decoration: none;
  border-bottom: 1px solid oklch(0.80 0.09 220 / 0.35);
}
a:hover {
  color: var(--link-hover);
  border-bottom-color: var(--link-hover);
}

code {
  font: 400 0.92em/1.4 var(--mono);
  color: var(--ink-soft);
}

/* ---- shell ---------------------------------------------------------------- */

.masthead {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  padding: 0 20px;
  height: 46px;
  border-bottom: 1px solid var(--rule);
  background: var(--bg-sunken);
  overflow-x: auto;
  scrollbar-width: none;
}
.masthead::-webkit-scrollbar {
  display: none;
}

.wordmark {
  font: 600 14px/1 var(--sans);
  color: var(--ink-bright);
  border-bottom: none;
  flex: none;
}
.wordmark:hover {
  color: var(--ink-bright);
}

.masthead nav {
  display: flex;
  align-items: center;
  gap: 1rem;
  white-space: nowrap;
}
.masthead nav a,
.masthead nav .unbuilt {
  font: 400 11.5px/1 var(--mono);
  border-bottom: none;
  color: var(--ink-dim);
}
.masthead nav a:hover {
  color: var(--ink-bright);
}
.masthead nav a[aria-current="page"] {
  color: var(--ink-bright);
}
.masthead nav .unbuilt {
  color: oklch(0.40 0.008 60);
  text-decoration: line-through;
  cursor: not-allowed;
}
.nav-primary {
  color: var(--warn) !important;
}

main {
  padding: 26px 32px 40px;
  /* No cap. The cost and decision tables were filling a 1500px column while the runs and
     work pages sat narrower, which read as three different layouts. Prose keeps its own
     measure below (.lede, .footnote) — a 2000px paragraph is not consistency, it is worse. */
  max-width: none;
}

h1 {
  margin: 0 0 7px;
  font: 600 19px/1.3 var(--sans);
  letter-spacing: 0.005em;
  color: var(--ink-bright);
}

h2 {
  margin: 26px 0 12px;
  font: 500 10px/1.4 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.lede {
  margin: 0 0 22px;
  font: 400 11.5px/1.5 var(--mono);
  color: var(--ink-dim);
  max-width: 860px;
  text-wrap: pretty;
}

.colophon {
  margin: 40px 32px 24px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
  display: flex;
  gap: 0.6rem;
  font: 10.5px/1.5 var(--mono);
  color: var(--ink-faint);
}

.footnote {
  font: 10.5px/1.55 var(--mono);
  color: var(--ink-faint);
  max-width: 860px;
  text-wrap: pretty;
}

.empty {
  color: oklch(0.44 0.008 60);
}

/* ---- shared: notices ------------------------------------------------------ */

.notice,
.error,
.ok {
  border-radius: 3px;
  padding: 12px 15px;
  margin: 0 0 16px;
  font: 11.5px/1.55 var(--mono);
}
.notice {
  border: 1px solid var(--info-border);
  background: var(--info-bg);
  color: var(--ink-soft);
}
.error {
  border: 1px solid var(--alarm-border);
  background: var(--alarm-bg);
  color: var(--alarm);
}
.ok {
  border: 1px solid var(--ok-border);
  background: var(--ok-bg);
  color: var(--ok);
}

/* ---- shared: tables ------------------------------------------------------- */

table {
  width: 100%;
  border-collapse: collapse;
  font: 11.5px/1.5 var(--mono);
}
thead th {
  text-align: left;
  padding: 0 10px 7px;
  font: 500 9.5px/1.4 var(--mono);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border-bottom: 1px solid var(--rule-mid);
  white-space: nowrap;
}
tbody td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--rule);
  color: var(--ink-soft);
  vertical-align: top;
}
tbody tr:hover td {
  background: oklch(0.20 0.008 60);
}
td.num,
th.num {
  font-variant-numeric: tabular-nums;
}

/* Every column but the first is centred, header and body together.
   The first column stays left: it is the identity of the row — run id, ticket, model, cluster
   — and a ragged left edge is what makes a column of identifiers scannable. Specificity beats
   `td.num` and `thead th` on its own (0,1,2 against 0,1,1 and 0,0,2), so this holds wherever
   it sits in the file. */
thead th:not(:first-child),
tbody td:not(:first-child) {
  text-align: center;
}

/* ---- shared: badges and the four cell states ------------------------------ */

.badge {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 2px;
  border: 1px solid var(--rule-strong);
  font: 500 9.5px/1.6 var(--mono);
  letter-spacing: 0.06em;
  color: var(--ink-mid);
  white-space: nowrap;
}
.badge-ok { color: var(--ok); border-color: var(--ok-border); background: var(--ok-bg); }
.badge-warn { color: var(--warn); border-color: var(--warn-border); background: var(--warn-bg); }
.badge-alarm { color: var(--alarm); border-color: var(--alarm-border); background: var(--alarm-bg); }
.badge-info { color: var(--link); border-color: var(--info-border); background: var(--info-bg); }

/* §5 agent_stages vocabulary. done / failed / skipped_by_policy / not_reached are four
 * distinct facts and never collapse into one another. */
.cell { display: inline-flex; align-items: center; justify-content: center;
  min-width: 84px; padding: 4px 8px; border-radius: 2px;
  font: 500 9.5px/1.5 var(--mono); letter-spacing: 0.05em; }
.cell-done { color: var(--ok); background: var(--ok-bg); border: 1px solid var(--ok-border); }
.cell-failed { color: var(--alarm); background: var(--alarm-bg); border: 1px solid var(--alarm-border); }
.cell-skipped_by_policy { color: var(--ink-mid); background: oklch(0.235 0.008 60); border: 1px solid var(--rule-strong); }
.cell-not_reached { color: oklch(0.44 0.008 60); background: transparent; border: 1px dashed var(--rule-strong); }
.cell-running { color: var(--warn); background: var(--warn-bg); border: 1px solid var(--warn-border); }

/* ---- shared: metric cards ------------------------------------------------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 9px;
  margin: 18px 0 24px;
}
.card {
  border: 1px solid var(--rule);
  background: var(--surface);
  border-radius: 3px;
  padding: 13px 15px 14px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}
.card h3 {
  margin: 0;
  font: 500 9px/1.3 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.card-value {
  margin: 0;
  font: 500 25px/1.1 var(--mono);
  letter-spacing: -0.01em;
  color: var(--ink);
  display: flex;
  align-items: baseline;
  gap: 9px;
}
.card-aside { font-size: 10px; font-weight: 400; color: oklch(0.52 0.008 70); }
.card-who {
  margin: 0;
  font: 10px/1.45 var(--mono);
  color: oklch(0.64 0.008 70);
  overflow-wrap: anywhere;
}
.card-note { margin: 0; font: 10px/1.45 var(--mono); color: var(--ink-faint); }
.card-basis {
  margin: 3px 0 0;
  padding-top: 7px;
  border-top: 1px solid var(--rule);
  font: 9.5px/1.5 var(--mono);
  color: oklch(0.48 0.008 60);
  overflow-wrap: anywhere;
}
.card-alarm { border-color: var(--warn-border); }
.card-alarm .card-value { color: var(--warn-strong); }
.card-quiet .card-value { font-size: 15px; color: var(--ink-faint); }
.card-unsourced { border-style: dashed; }
.card-unsourced .card-value { font-size: 15px; color: oklch(0.48 0.008 60); }

/* ---- shared: panels ------------------------------------------------------- */

.panel {
  border-radius: 3px;
  padding: 15px 17px 16px;
  margin: 0 0 20px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.panel h2 { margin: 0; font-size: 12.5px; letter-spacing: 0; text-transform: none; }
.panel p { margin: 0; font: 12.5px/1.55 var(--sans); color: var(--ink-soft); max-width: 860px; }
.panel-quiet { border: 1px solid var(--ok-border); background: var(--ok-bg); }
.panel-quiet h2 { color: var(--ok); font-weight: 600; }
.panel-unmeasured { border: 1px dashed var(--rule-strong); background: var(--surface); }
.panel-unmeasured h2 { color: var(--ink-mid); font-weight: 600; }

.facts { display: flex; flex-wrap: wrap; gap: 6px 20px; margin: 0; font: 10.5px/1.5 var(--mono); }
.facts div { display: flex; gap: 8px; align-items: baseline; }
.facts dt { color: var(--ink-faint); }
.facts dd { margin: 0; color: var(--ink-mid); }

/* ---- shared: bars --------------------------------------------------------- */

.bar-row { display: grid; grid-template-columns: 190px 1fr 52px; gap: 12px; align-items: center;
  padding: 4px 0; font: 10.5px/1.5 var(--mono); }
.bar-label { color: var(--ink-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The track must read as empty when the fill is zero. It was light enough that a w-0 bar
 * looked like a full one, so every row in the step ledger appeared identical — a chart that
 * encodes nothing while looking like it does. */
.bar-track {
  /* Sunken well, clearly outlined. The outline was oklch(0.245) — barely above the panel it
   * sits on, so a short bar and an empty one both read as "nothing there" and the row lost
   * its baseline. `--rule-strong` gives the track an edge you can see, which is what makes a
   * 4% bar legible as 4% rather than as absent. */
  background: var(--bg-sunken);
  box-shadow: inset 0 0 0 1px var(--rule-strong);
  border-radius: 2px;
  height: 11px;
  overflow: hidden;
}
/* `display: block` is load-bearing.
 *
 * The fill is a <span>, and `width` does not apply to an inline box — so every bar in every
 * chart rendered at the track's full width regardless of its `w-*` class. The widths were
 * computed correctly and thrown away by the layout, which is the same failure as the inline
 * `style="width:…"` the CSP dropped: a chart that looks like it encodes something and does
 * not. `npm run views:check` catches the class being missing; it cannot catch the box being
 * the wrong kind, which is what the tests below the fold now assert. */
.bar-fill {
  display: block;
  height: 100%;
  background: var(--warn-strong);
}
.bar-fill-ok { background: var(--ok-border); }
.bar-fill-alarm { background: var(--alarm-border); }
.bar-num { text-align: right; color: var(--ink-mid); font-variant-numeric: tabular-nums; }

/* ---- view 1: queue health ------------------------------------------------- */

.stages { display: grid; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); gap: 9px; margin: 18px 0 24px; }

/* ---- the demo path: /work ------------------------------------------------- */

.work-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 20px 0 8px; max-width: 760px; }
.work-form label { flex: 1 0 100%; font: 500 9px/1.4 var(--mono); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-faint); }
.work-form input {
  flex: 1 1 430px; min-width: 0; padding: 9px 11px;
  font: 12px/1.4 var(--mono); color: var(--ink);
  background: var(--bg-sunken); border: 1px solid var(--rule-strong); border-radius: 3px;
}
.work-form input::placeholder { color: oklch(0.44 0.008 60); }
.work-form input:focus-visible { outline: none; border-color: var(--warn-border); }
.work-form button {
  padding: 9px 18px; font: 500 11.5px/1.4 var(--mono); letter-spacing: 0.04em;
  color: oklch(0.17 0.008 60); background: var(--warn-strong);
  border: 1px solid var(--warn-strong); border-radius: 3px; cursor: pointer;
}
.work-form button:hover { background: var(--warn); border-color: var(--warn); }

.hops { list-style: none; margin: 22px 0; padding: 0; max-width: none; }
.hop { display: grid; grid-template-columns: 14px 165px auto; gap: 3px 12px; align-items: baseline;
  padding: 9px 0; border-bottom: 1px solid var(--rule); }
.hop-dot { width: 8px; height: 8px; border-radius: 50%; border: 1px solid var(--rule-strong); align-self: center; }
.hop-label { font: 500 12px/1.4 var(--sans); color: var(--ink-soft); }
.hop-state { font: 9.5px/1.5 var(--mono); letter-spacing: 0.05em; color: var(--ink-faint); }
.hop-detail { grid-column: 3; font: 10.5px/1.5 var(--mono); color: var(--ink-dim); overflow-wrap: anywhere; }
.hop-done .hop-dot { background: var(--ok); border-color: var(--ok); }
.hop-done .hop-state { color: var(--ok); }
.hop-done .hop-label { color: var(--ink-bright); }
.hop-failed .hop-dot { background: var(--alarm); border-color: var(--alarm); }
.hop-failed .hop-state, .hop-failed .hop-detail { color: var(--alarm); }
.hop-skipped_by_policy .hop-dot { background: var(--ink-faint); border-color: var(--ink-faint); }
.hop-not_reached .hop-dot { background: transparent; border-style: dashed; }
.hop-not_reached .hop-label { color: oklch(0.48 0.008 60); }
.hop-running .hop-dot { background: var(--warn); border-color: var(--warn); }
.hop-running .hop-state { color: var(--warn); }

.pr-landing { border: 1px solid var(--ok-border); background: var(--ok-bg); border-radius: 3px;
  padding: 15px 17px; margin: 20px 0; }
.pr-landing h2 { margin: 0 0 6px; font-size: 12.5px; letter-spacing: 0; text-transform: none;
  color: var(--ok); font-weight: 600; }
.pr-landing p { margin: 0; font: 12.5px/1.5 var(--mono); overflow-wrap: anywhere; }

.req-status { font: 10px/1.5 var(--mono); padding: 1px 6px; border-radius: 2px; border: 1px solid var(--rule-strong); }
.req-rejected { color: var(--alarm); border-color: var(--alarm-border); background: var(--alarm-bg); }
.req-done { color: var(--ok); border-color: var(--ok-border); background: var(--ok-bg); }
.req-claimed { color: var(--warn); border-color: var(--warn-border); background: var(--warn-bg); }

/* ---- view 11: switches ---------------------------------------------------- */

.switch-control { display: flex; gap: 6px; align-items: center; }
.switch-control input[type="text"] {
  width: 150px; padding: 4px 7px; font: 10.5px/1.4 var(--mono);
  color: var(--ink); background: var(--bg-sunken);
  border: 1px solid var(--rule-strong); border-radius: 2px;
}
.switch-control button {
  padding: 4px 11px; font: 500 10px/1.4 var(--mono);
  color: var(--ink-soft); background: var(--surface-raised);
  border: 1px solid var(--rule-strong); border-radius: 2px; cursor: pointer;
}
.switch-control button:hover { border-color: var(--ink-faint); color: var(--ink-bright); }
.switch-control button.danger { color: var(--alarm); border-color: var(--alarm-border); }
.effect { display: block; font-size: 9.5px; color: var(--ink-faint); margin-top: 2px; }
.state-on { color: var(--alarm); }
.state-off { color: var(--ok-dim); }

/* ---- view 2: cluster page ------------------------------------------------- */

.stage-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(108px, 1fr)); gap: 6px; margin: 12px 0 22px; }
.stage-cell { border-radius: 3px; padding: 10px; display: flex; flex-direction: column; gap: 5px; }
.stage-cell h4 { margin: 0; font: 500 9px/1.3 var(--mono); letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-faint); }

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { border-left: 2px solid var(--rule-mid); padding: 0 0 16px 15px; margin-left: 4px; position: relative; }
.timeline li::before { content: ""; position: absolute; left: -5px; top: 4px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--rule-strong); }
.timeline .t-head { display: flex; gap: 9px; align-items: baseline; flex-wrap: wrap;
  font: 11.5px/1.5 var(--mono); color: var(--ink-soft); }
.timeline .t-when { color: var(--ink-faint); font-size: 10px; }
.timeline .t-body { margin: 4px 0 0; font: 10.5px/1.55 var(--mono); color: var(--ink-dim); }

.cf { margin: 5px 0 0; padding: 7px 10px; border-left: 2px solid var(--warn-border);
  background: oklch(0.205 0.012 62); border-radius: 0 2px 2px 0;
  font: 10.5px/1.6 var(--mono); color: var(--ink-mid); }
.cf strong { color: var(--warn); font-weight: 500; }

.kv { display: grid; grid-template-columns: 165px 1fr; gap: 5px 14px; margin: 0 0 22px;
  font: 11.5px/1.6 var(--mono); }
.kv dt { color: var(--ink-faint); }
.kv dd { margin: 0; color: var(--ink-soft); overflow-wrap: anywhere; }

/* ---- filter bars (views 3, 6) --------------------------------------------- */

.filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 16px;
  padding: 11px 13px; border: 1px solid var(--rule); background: var(--surface); border-radius: 3px; }
.filters label { font: 500 9px/1.4 var(--mono); letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-faint); }
.filters select, .filters input {
  padding: 5px 8px; font: 10.5px/1.4 var(--mono); color: var(--ink);
  background: var(--bg-sunken); border: 1px solid var(--rule-strong); border-radius: 2px;
}
.filters .count { margin-left: auto; font: 10.5px/1.4 var(--mono); color: var(--ink-faint); }

/* ---- the not-built notice ------------------------------------------------- */

.unbuilt-note { border: 1px dashed var(--rule-strong); background: var(--surface);
  border-radius: 3px; padding: 14px 16px; margin: 0 0 20px;
  font: 11.5px/1.6 var(--mono); color: var(--ink-dim); max-width: 860px; }
.unbuilt-note strong { color: var(--warn); font-weight: 500; }

/* ---- bar widths, bucketed to 5% ------------------------------------------- */
/* Inline `style="width:…"` is blocked by the CSP above, and was rendering every bar
 * at full width — a chart that looked right and said nothing. The exact figure is
 * printed beside each bar, so 5% granularity in the bar itself loses nothing. */
.w-0 { width: 0%; }
.w-5 { width: 5%; }
.w-10 { width: 10%; }
.w-15 { width: 15%; }
.w-20 { width: 20%; }
.w-25 { width: 25%; }
.w-30 { width: 30%; }
.w-35 { width: 35%; }
.w-40 { width: 40%; }
.w-45 { width: 45%; }
.w-50 { width: 50%; }
.w-55 { width: 55%; }
.w-60 { width: 60%; }
.w-65 { width: 65%; }
.w-70 { width: 70%; }
.w-75 { width: 75%; }
.w-80 { width: 80%; }
.w-85 { width: 85%; }
.w-90 { width: 90%; }
.w-95 { width: 95%; }
.w-100 { width: 100%; }

/* The cluster key under its title. A class, not an inline style — the CSP has no
 * 'unsafe-inline' and an inline rule is silently dropped, not warned about. */
.subkey {
  margin: 2px 0 0;
  font: 9.5px/1.5 var(--mono);
  color: oklch(0.48 0.008 60);
}

/* ---- in-flight indication -------------------------------------------------- */

/* The hop the pipeline is currently on. Distinct from `done` (finished),
 * `not_reached` (nothing is running) and `skipped_by_policy` (decided against) — four states
 * that must stay four, plus this fifth for "happening now". */
.hop-running .hop-dot {
  background: var(--warn);
  border-color: var(--warn);
  animation: pulse 1.4s ease-in-out infinite;
}
.hop-running .hop-label {
  color: var(--ink-bright);
}
.hop-running .hop-state {
  color: var(--warn);
}

/* A thin travelling bar under the active hop: the one place on the page where motion is
 * information rather than decoration. */
.hop-running {
  position: relative;
  overflow: hidden;
}
.hop-running::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 1px;
  width: 35%;
  background: linear-gradient(90deg, transparent, var(--warn), transparent);
  animation: sweep 1.8s ease-in-out infinite;
}

@keyframes pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.35;
    transform: scale(0.7);
  }
}

@keyframes sweep {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(386%);
  }
}

.working {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 18px 0;
  font: 10.5px/1.55 var(--mono);
  color: var(--ink-dim);
}

.spinner {
  flex: none;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 1.5px solid var(--rule-strong);
  border-top-color: var(--warn);
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* Motion is information here, so it is not removed for reduced-motion — it is replaced with a
 * static, still-legible marker rather than leaving the reader unable to tell a live page from
 * a stalled one. */
@media (prefers-reduced-motion: reduce) {
  .hop-running .hop-dot,
  .spinner,
  .hop-running::after {
    animation: none;
  }
  .spinner {
    border-top-color: var(--warn);
    border-right-color: var(--warn);
  }
  .hop-running::after {
    width: 100%;
    background: var(--warn-border);
  }
}

/* The model picker sits inline with the ticket field. */
.work-form .inline-label {
  flex: none;
  margin-left: 0.5rem;
}
.work-form select {
  flex: none;
  padding: 9px 10px;
  font: 11.5px/1.4 var(--mono);
  color: var(--ink);
  background: var(--bg-sunken);
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
}

/* ---- masthead nav ---------------------------------------------------------- */

.nav-item {
  position: relative;
  padding: 15px 0;
}
.nav-active {
  color: var(--ink-bright) !important;
}
/* The design marks the current view with a rule beneath it, not a background. */
.nav-active::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--warn-strong);
}
.masthead nav a:first-child {
  color: var(--warn);
}
.masthead nav a:first-child.nav-active {
  color: var(--warn) !important;
}

/* ---- view 7: runs ---------------------------------------------------------- */

.runs-table td {
  vertical-align: top;
}
.run-mark {
  color: var(--ink-faint);
  margin-right: 5px;
}
.run-sub {
  margin-top: 3px;
  font: 9.5px/1.5 var(--mono);
  color: var(--ink-faint);
}
.run-degraded {
  margin-top: 3px;
  font: 9.5px/1.5 var(--mono);
  color: var(--warn);
}

/* The step strip: eight chips, one per §4 Workflow step. */
.steps {
  display: inline-flex;
  gap: 2px;
  flex-wrap: nowrap;
}
.step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  padding: 3px 5px;
  border-radius: 2px;
  font: 500 9px/1.4 var(--mono);
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.step-done { background: oklch(0.30 0.048 150); color: oklch(0.84 0.11 150); }
.step-resumed { background: oklch(0.32 0.055 245); color: oklch(0.84 0.09 245); }
.step-failed { background: oklch(0.34 0.10 25); color: oklch(0.82 0.17 25); }
.step-paused { background: oklch(0.36 0.09 75); color: oklch(0.90 0.13 78); }
/* Finished without needing it — grey, but present. */
.step-skipped { background: oklch(0.22 0.008 60); color: oklch(0.52 0.008 70); }
/* Never got there — darkest, and outlined so it reads as absent rather than dim. */
.step-not_reached {
  background: oklch(0.195 0.008 60);
  color: oklch(0.40 0.008 60);
  box-shadow: inset 0 0 0 1px oklch(0.24 0.008 60);
}

/* runs.status, the closed set from §5.1 plus §4.0's two preflight outcomes. */
.out {
  display: inline-block;
  padding: 2px 7px;
  border-radius: 2px;
  font: 500 9.5px/1.5 var(--mono);
  letter-spacing: 0.05em;
}
.out-complete { color: oklch(0.84 0.11 150); background: oklch(0.28 0.045 150); }
.out-partial { color: oklch(0.88 0.11 78); background: oklch(0.30 0.07 75); }
.out-failed { color: oklch(0.86 0.15 25); background: oklch(0.32 0.09 25); }
.out-paused { color: oklch(0.88 0.10 78); background: oklch(0.28 0.055 75); }
.out-running { color: oklch(0.84 0.09 245); background: oklch(0.28 0.05 245); }
.out-skipped { color: oklch(0.80 0.006 85); background: oklch(0.245 0.008 60); }

/* ---- runs: clickable steps ------------------------------------------------- */

button.step {
  border: 0;
  cursor: pointer;
  font-family: var(--mono);
}
button.step:hover {
  outline: 1px solid var(--ink-faint);
}
button.step.step-open {
  outline: 1px solid var(--warn);
}

.step-detail td {
  background: var(--bg-sunken);
  padding: 14px 12px 16px;
}
.panel-step {
  margin-bottom: 12px;
}
.panel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 9px;
  font: 11.5px/1.5 var(--mono);
}
.panel-timing {
  color: var(--ink-faint);
  font-size: 10px;
}
.ledger {
  border-top: 1px solid var(--rule);
  padding-top: 11px;
}
.ledger-head {
  font: 500 9.5px/1.4 var(--mono);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 8px;
}

.stage-run {
  font: 9px/1.4 var(--mono);
  color: var(--ink-faint);
}
.stage-reason {
  font: 9px/1.45 var(--mono);
  color: var(--alarm);
  overflow-wrap: anywhere;
}

/* A pull request another run opened is context, not this page's achievement. */
.pr-elsewhere {
  border-color: var(--rule-strong);
  background: var(--surface);
}
.pr-elsewhere h2 {
  color: var(--ink-mid);
}

/* A run that considered a cluster and declined. Amber, because it is not an error and not
 * nothing — it is a decision someone may want to read. */
.run-skipped {
  margin-top: 4px;
  font: 9.5px/1.5 var(--mono);
  color: var(--warn);
  text-align: left;
  max-width: 22rem;
  margin-left: auto;
  overflow-wrap: anywhere;
}

/* ---- a run arrived at by link (cost page -> /runs?run=…) ------------------- */

/* The row is in the table but may be far down it, or appended past the newest 50. Marking it
   is what makes the link land somewhere visible rather than somewhere true but unfindable. */
.runs-table tr.run-focus > td {
  background: var(--focus-wash, oklch(0.28 0.03 250 / 0.35));
  box-shadow: inset 0 0 0 1px var(--rule);
}
.runs-table tr.run-focus > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--accent, currentColor), inset 0 0 0 1px var(--rule);
}

/* ---- runs table column widths --------------------------------------------
   Every column but `steps` is pinned, so `steps` absorbs whatever the viewport gives —
   the chips are the point of this page and were being squeezed by columns that had no
   need to grow. Widths are the design's where it has an equivalent (status 126, clusters
   86, wall 96); `decisions` has no counterpart in the bundle and is sized to its badges. */
.runs-table th:nth-child(1), .runs-table td:nth-child(1) { width: 260px; }
.runs-table th:nth-child(2), .runs-table td:nth-child(2) { width: auto; }
.runs-table th:nth-child(3), .runs-table td:nth-child(3) { width: 126px; }
.runs-table th:nth-child(4), .runs-table td:nth-child(4) { width: 86px; }
.runs-table th:nth-child(5), .runs-table td:nth-child(5) { width: 210px; }
.runs-table th:nth-child(6), .runs-table td:nth-child(6) { width: 96px; }

/* The chips get the room, and stop being 40px minimums in a 900px column. */
.runs-table .steps { display: flex; justify-content: center; gap: 3px; }
.runs-table .step { flex: 1 1 auto; min-width: 44px; max-width: 92px; }

/* Decisions: one badge per kind, count first. A bare total above a run of "CANDIDATE 1 ·
   SKIP 2" said the same thing twice and left the column reading as an accident. */
.run-decisions { text-align: center; }
.kinds { display: inline-flex; flex-wrap: wrap; gap: 4px; justify-content: center; }
.kinds .badge { display: inline-flex; gap: 4px; align-items: baseline; }
.kinds b { font-weight: 600; font-variant-numeric: tabular-nums; }
.run-skipped { margin-top: 5px; font: 10px/1.4 var(--mono); color: var(--ink-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- runs: the expanded step panel (design/Runs.dc.html) -------------------
   Sizes and colours are the bundle's: run id 12.5px/600, headline and workflow instance 10px,
   the focus card bordered by the step's own state, its body 11.5px at 1.65 with pre-wrap. */

.panel-run {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
  margin-bottom: 12px;
}
.panel-run-id > code { font: 600 12.5px/1.4 var(--mono); color: var(--ink-bright); }
.panel-run-headline { margin-top: 4px; font: 10px/1.5 var(--mono); color: var(--ink-faint); text-wrap: pretty; }
.panel-run-wf { margin-top: 4px; font: 10px/1.5 var(--mono); color: var(--ink-dim); }
.panel-close, .all-steps {
  flex: none; align-self: flex-start; cursor: pointer;
  font: 10.5px/1.4 var(--mono); color: var(--ink-dim);
  background: transparent; border: 1px solid var(--rule-mid); border-radius: 3px;
  padding: 5px 11px;
}
.panel-close:hover, .all-steps:hover { color: var(--ink-bright); border-color: var(--ink-faint); }
.all-steps { margin-top: 12px; }
.all-steps.is-open { color: var(--ink-bright); border-color: var(--ink-faint); }

/* The amber rule the design puts beside a degraded run — a reason you read, not a field. */
.panel-degraded {
  border-left: 2px solid var(--warn-border);
  padding: 8px 0 8px 12px; margin-bottom: 12px;
  font: 11px/1.55 var(--mono); color: var(--ink-mid);
}

.panel-step {
  border: 1px solid var(--rule-mid);
  background: var(--panel-raise, oklch(0.185 0.008 60));
  border-radius: 3px;
  padding: 14px 16px 16px;
  margin-bottom: 12px;
  text-align: left;
}
.panel-step.focus-done { border-color: var(--ok-border); }
.panel-step.focus-failed { border-color: var(--alarm-border); }
.panel-step.focus-paused { border-color: var(--warn-border); }

.panel-step-name { font: 600 12.5px/1.4 var(--mono); color: var(--ink-bright); }
.panel-body {
  margin: 10px 0 14px;
  font: 11.5px/1.65 var(--mono); color: var(--ink-mid);
  white-space: pre-wrap; text-wrap: pretty;
  border-left: 2px solid var(--rule-mid); padding-left: 12px;
}
/* The design's metric rows: a fixed label gutter, value taking the rest. */
.panel-step .facts { display: flex; flex-direction: column; gap: 6px; font: 11px/1.5 var(--mono); }
.panel-step .facts div { display: flex; gap: 14px; align-items: baseline; }
.panel-step .facts dt { width: 170px; flex: none; color: var(--ink-faint); }
.panel-step .facts dd { flex: 1; min-width: 0; margin: 0; color: var(--ink-soft); text-wrap: pretty; }

/* ---- the step currently executing ----------------------------------------
   Two signals, because one is not enough: a pulsing ring says "this is happening now", and a
   sweep across the chip says "and it has not stalled". A static highlight cannot distinguish
   a step running from a step that stopped while running, which is the case the page exists to
   show. Both are switched off under prefers-reduced-motion, where the ring alone carries it. */

@keyframes step-pulse {
  0%, 100% { box-shadow: 0 0 0 1px var(--link, oklch(0.72 0.13 235)); }
  50%      { box-shadow: 0 0 0 2px var(--link, oklch(0.72 0.13 235)), 0 0 10px -1px var(--link, oklch(0.72 0.13 235)); }
}
@keyframes step-sweep {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

.step-running {
  position: relative;
  overflow: hidden;
  background: oklch(0.28 0.06 235);
  color: oklch(0.88 0.11 235);
  animation: step-pulse 1.4s ease-in-out infinite;
}
.step-running::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, oklch(0.88 0.11 235 / 0.28), transparent);
  animation: step-sweep 1.25s linear infinite;
}

/* The run's own row, so you can find the live one without reading every chip. */
.runs-table tr:has(.step-running) > td:first-child { box-shadow: inset 3px 0 0 0 var(--link, oklch(0.72 0.13 235)); }

@media (prefers-reduced-motion: reduce) {
  .step-running { animation: none; box-shadow: 0 0 0 2px var(--link, oklch(0.72 0.13 235)); }
  .step-running::after { display: none; }
}
