/* ════════════════════════════════════════════════════════════════════════════
   Pipeline Runs tab (2026-07-22). Standalone, namespaced `pr-*`; it draws with the
   app's theme tokens (every palette x mode for free), the shared radius scale
   (--r-xs..--r-lg) and the shared SURFACE language in surface.css.

   The page is a stack of discrete CARDS on the tinted ground — the header, the run
   picker, the selected run's identity, each model's verdict, and the batch that fed
   them — rather than one hairline-divided sheet. Card geometry (surface, hairline,
   radius, shadow) now comes from `.card` / `.card--pad`, added to those wrappers in
   js/pipeline-runs.js and mirrored in its skeleton builder. What survives in this
   file is only what is specific to THIS page: density, the two-column split, the
   verdict-cell grid, and the semantic colours.

   Two columns (run list + per-model detail) collapsing to a stack at 760px.
   ════════════════════════════════════════════════════════════════════════════ */

/* The old `#view-pipeline-runs { padding: 0 }` reset is deliberately gone: `.view`
   in surface.css supplies the column flow, the gap BETWEEN cards and the top
   padding, and an id-specificity `padding: 0` silently cancelled all three.
   The page-local `.mono` rule is gone for the same reason — app.css and surface.css
   already own that class, and a third definition of it was drift waiting to happen. */

/* The skeleton is painted inside reveal.js's own `.g10-sk` wrapper, which is a plain
   block — so without this the placeholder cards would touch while the real ones sit a
   gap apart, and the swap would shift the page. Scoped to this view; the wrapper is
   shared, the rhythm is the page's. */

.pr-empty {
  padding: 40px 24px; color: var(--text-muted); font-size: 14px; text-align: center;
  /* Every state this view can land in is a card on the ground, the empty and loading
     ones included — a lone sentence floating on the tint reads as a broken page.
     Declared here rather than class-tagged at the six call sites that emit it. */
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1);
}
.pr-faint { color: var(--text-faint); }

/* ── controls — the page header card (`.card .card--pad` in the renderer) ───── */
.pr-controls {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  flex-wrap: wrap;
}
/* Headlines are the serif, and only headlines. */
.pr-title { font: 600 20px/1.25 var(--font-display); letter-spacing: -.015em; color: var(--text); }
/* The gloss beside the headline is plain language, so it drops out of the serif into
   the UI face — the .sec-head / .sec-note pairing, inline. */
.pr-controls .pr-faint { font: 400 12px/1.5 var(--font-sans); color: var(--text-muted); }

/* ── two-column layout ─────────────────────────────────────────────────────── */
/* The gutter matches `.view`'s own card gap, so the two columns read as one grid of
   cards rather than as two stacks keeping a different rhythm. */
.pr-layout { display: flex; gap: clamp(14px, 1.8vw, 22px); align-items: flex-start; }
.pr-list-col { flex: 0 0 360px; max-width: 360px; }
.pr-detail-col {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: clamp(14px, 1.8vw, 22px);
}

/* ── gate pill ─────────────────────────────────────────────────────────────── */
.pr-gate {
  display: inline-block; font: 500 9.5px/1.4 var(--font-mono);
  letter-spacing: .1em; text-transform: uppercase;
  padding: 2px 8px; border-radius: var(--r-sm);
  border: 1px solid var(--line); color: var(--text-2); white-space: nowrap;
}
/* `escalated` is a decision class beside intact/scheduled/manual, so it takes the
   informational rung. It used to be --accent, which is the interactive colour (links,
   focus rings, the active run) — a gate badge is a data status, never a control. */
.pr-gate--escalated { color: var(--info-text); border-color: var(--info-edge); }
.pr-gate--intact { color: var(--text-muted); border-color: var(--line); }
.pr-gate--scheduled { color: var(--bull-text); border-color: var(--bull-edge); }
.pr-gate--manual { color: var(--text-faint); border-color: var(--line); }

/* ── run list — grouped by UTC day (`.card .card--pad` in the renderer) ─────── */
/* The design's signature label: uppercase mono at wide tracking in the quietest
   tier, so a group can be introduced without a heading that competes with it. */
.pr-picker-h {
  font: 500 10.5px/1.4 var(--font-mono); letter-spacing: .16em; text-transform: uppercase;
  color: var(--colhead); margin-bottom: 10px;
}
.pr-day { margin-bottom: 14px; }
.pr-day:last-child { margin-bottom: 0; }
/* A date is a figure: mono and tabular, so the day headings line up down the column.
   The rule under it divides two run groups INSIDE one card, which is a different
   thing from the full-bleed sheet the card language replaced. */
.pr-day-h {
  display: flex; align-items: baseline; gap: 8px;
  font: 500 11px/1.4 var(--font-mono); letter-spacing: .04em; color: var(--text);
  font-variant-numeric: tabular-nums;
  padding: 2px 2px 6px;
  border-bottom: 1px solid var(--line); margin-bottom: 8px;
}
.pr-day-n { font: 400 10px/1.4 var(--font-sans); color: var(--text-faint); }
.pr-runs { display: flex; flex-direction: column; gap: 6px; }
/* A run row is a surface nested inside the picker card, so it steps DOWN a rung:
   --r-md, the sunken tier, no shadow of its own. */
.pr-run {
  display: block; width: 100%; cursor: pointer; text-align: left;
  padding: 10px 12px; border-radius: var(--r-md);
  border: 1px solid var(--line); background: var(--surface-sunken);
  color: var(--text-2);
  transition: background-color var(--dur-micro) var(--ease-out),
              border-color var(--dur-micro) var(--ease-out);
}
.pr-run:hover { border-color: var(--accent-edge); background: var(--surface-row-active); }
.pr-run--active { border-color: var(--accent); }
.pr-run-top { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.pr-run-ts {
  font: 600 11px/1.4 var(--font-mono); color: var(--text);
  font-variant-numeric: tabular-nums;
}
.pr-run-counts {
  font: 400 10px/1.4 var(--font-mono); color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.pr-run-reason { font-size: 11px; color: var(--text-faint); line-height: 1.35; margin-top: 6px; }

/* ── per-model badge strip ─────────────────────────────────────────────────── */
.pr-strip { display: flex; gap: 4px; flex-wrap: wrap; }
.pr-cell {
  display: inline-flex; flex-direction: column; gap: 1px; align-items: flex-start;
  /* square on purpose: this is a verdict CELL, scanned down a column against its
     siblings, so it follows the data-table rule rather than the chip radius. */
  padding: 3px 7px; border-radius: 0; border: 1px solid var(--line);
  min-width: 62px;
}
.pr-cell-m {
  font: 500 8.5px/1.4 var(--font-mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-faint);
}
.pr-cell-o { font: 500 10px/1.4 var(--font-sans); letter-spacing: .02em; }
/* Thesis size + pair coverage, under each model's outcome in the run strip. Muted by
   default — it is a background number you scan down a column, not a status. It turns
   amber only when that lineage is carrying fewer pair sections than the active universe,
   which is the condition that went unseen for weeks. Tabular, because the whole point
   is that the column lines up. */
.pr-cell-shape { font: 400 9px/1.4 var(--font-sans); color: var(--text-faint); }
.pr-cell-shape { font-variant-numeric: tabular-nums; }
.pr-cell-shape--short { color: var(--warn-text); font-weight: 600; }
.pr-mtag--warn { color: var(--warn-text); border-color: var(--warn-edge); }

/* outcome colors (shared by the strip cells + detail badges) */
.pr-out--recompute { color: var(--bull-text); border-color: var(--bull-edge); }
.pr-out--intact { color: var(--text-muted); border-color: var(--line); }
.pr-out--hold { color: var(--warn-text); border-color: var(--warn-edge); }
.pr-out--aborted { color: var(--bear-text); border-color: var(--bear-edge); }
.pr-out--none { color: var(--text-faint); border-color: var(--line); }

/* ── detail: which run this is (`.pr-detail-card` = `.card .card--pad`) ─────── */
/* The heading and its caption are one object, so they share one card. The rule that
   used to divide them is gone — the card edge already does that job. */
.pr-detail-h { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.pr-detail-type { font: 500 15px/1.25 var(--font-display); letter-spacing: -.015em; color: var(--text); }
.pr-caption { font: 400 12px/1.5 var(--font-sans); margin: 8px 0 0; }

/* ── the batch that fed the run (`.card .card--pad` in the renderer) ────────── */
/* "What fed the run" is its own card now. It used to be a recessed well inside the
   detail column, drawn as a 4%-alpha blue wash of the retired accent: off-palette in
   every theme, and a cool cast over the warm light grounds. */
.pr-batch-h {
  font: 500 10.5px/1.4 var(--font-mono); letter-spacing: .16em; text-transform: uppercase;
  color: var(--colhead); margin-bottom: 10px;
}
.pr-b-grp { margin-bottom: 12px; }
.pr-b-grp:last-child { margin-bottom: 0; }
/* One rung under the card label: still mono, but sentence case and less tracking, so
   two stacked labels do not read as the same level. */
.pr-b-h { font: 500 11px/1.4 var(--font-sans); letter-spacing: .06em; color: var(--text-2); margin-bottom: 6px; }
/* The table's own frame rounds and clips; the CELLS stay square. */
.pr-b-tblwrap {
  overflow-x: auto;
  border: 1px solid var(--line); border-radius: var(--r-md);
}
.pr-b-tbl { border-collapse: collapse; width: 100%; font-size: 11px; }
.pr-b-tbl { font-variant-numeric: tabular-nums; }
/* Mono tracked capitals on the sunken tier, so the header row reads as chrome rather
   than as data. The bespoke 6%-alpha row rule this table used to draw is retired in
   favour of the hairline token every other table here now uses — it tracks the palette
   and carries the same weight per unit alpha, which was the reason for the old tuning. */
.pr-b-tbl th {
  font: 500 9.5px/1 var(--font-mono); letter-spacing: .14em; text-transform: uppercase;
  color: var(--colhead); text-align: left; background: var(--surface-sunken);
  padding: 9px 12px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.pr-b-tbl td {
  padding: 8px 12px; color: var(--text-2);
  border-bottom: 1px solid var(--line); vertical-align: top;
}
.pr-b-tbl tbody tr:last-child td { border-bottom: 0; }
.pr-b-tbl td:first-child { color: var(--text); }
/* The article list is the same object in list form, so it takes the same frame. */
.pr-b-list {
  list-style: none; margin: 0; padding: 0;
  border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden;
}
.pr-b-list li {
  font-size: 11px; color: var(--text-2); padding: 7px 12px; line-height: 1.4;
  border-bottom: 1px solid var(--line);
}
.pr-b-list li:last-child { border-bottom: 0; }
.pr-b-src { color: var(--text); font-weight: 500; }
.pr-trig { color: var(--accent); font-size: 10px; }

/* ── per-model cards (each `.pr-model` is a `.card` in the renderer) ────────── */
.pr-models-h {
  font: 500 10.5px/1.4 var(--font-mono); letter-spacing: .16em; text-transform: uppercase;
  color: var(--colhead); margin-bottom: 10px;
}
.pr-model { padding: 14px 16px; margin-bottom: 12px; }
.pr-model:last-child { margin-bottom: 0; }
.pr-model-h { display: flex; align-items: baseline; gap: 10px; justify-content: space-between; margin-bottom: 8px; }
.pr-model-t { font: 500 15px/1.25 var(--font-display); letter-spacing: -.015em; color: var(--text); }
.pr-badge {
  display: inline-block; font: 500 10.5px/1.4 var(--font-sans); letter-spacing: .06em;
  padding: 3px 9px; border-radius: var(--r-sm);
  border: 1px solid var(--line); white-space: nowrap;
}
.pr-model-meta { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
.pr-mtag {
  font: 500 9.5px/1.4 var(--font-sans); letter-spacing: .04em; color: var(--text-faint);
  border: 1px solid var(--line); padding: 2px 8px; border-radius: var(--r-sm);
}
.pr-why { margin: 8px 0; }
.pr-why-h {
  font: 500 9.5px/1.4 var(--font-mono); letter-spacing: .16em; text-transform: uppercase;
  color: var(--colhead); margin-bottom: 3px;
}
.pr-why-b { font-size: 12px; color: var(--text-2); line-height: 1.45; }
.pr-heads { margin: 8px 0; }
.pr-heads-h {
  font: 500 9.5px/1.4 var(--font-mono); letter-spacing: .16em; text-transform: uppercase;
  color: var(--colhead); margin-bottom: 3px;
}
.pr-heads ul { list-style: disc; margin: 0; padding-left: 18px; }
.pr-heads li { font-size: 11px; color: var(--text-2); line-height: 1.4; }
.pr-note { font-size: 11px; margin-top: 4px; }
.pr-prose { margin-top: 8px; }
.pr-prose-h {
  font: 500 10px/1.4 var(--font-sans); letter-spacing: .06em;
  color: var(--accent); cursor: pointer; user-select: none;
}
/* A raw changelog dump is a nested surface inside the model card, so it steps down to
   the sunken tier rather than sitting at the same level as the card holding it. */
.pr-prose-b {
  margin: 6px 0 0; padding: 10px 12px; max-height: 320px; overflow: auto;
  background: var(--surface-sunken); border: 1px solid var(--line);
  border-radius: var(--r-md); font-family: var(--font-sans); font-size: 11px;
  color: var(--text-2); white-space: pre-wrap; word-break: break-word;
}

@media (max-width: 760px) {
  .pr-layout { flex-direction: column; }
  .pr-list-col { flex-basis: auto; max-width: none; width: 100%; }
}
