/*
 * One stylesheet, shared by both build targets, no framework.
 *
 * The visual hierarchy is the product argument: a rejection is the loudest thing
 * on the page, provenance sits above the rows rather than below them, and the
 * gates that make every row uncallable are rendered as content rather than as a
 * dismissible banner. A caveat you can dismiss is a caveat that gets dismissed.
 */

:root {
  --ink: #14171a;
  --muted: #5b6570;
  --rule: #d8dde2;
  --paper: #fbfcfd;
  --no: #8c1c13;
  --no-bg: #fdf1f0;
  --measure: #6a4a00;
  --measure-bg: #fdf8ec;
  --neutral-bg: #f2f5f7;
  /* The colour a panel sits on. A VARIABLE rather than five literal `#fff`s
   * because the public site overrides this palette wholesale (`site.css`), and
   * a hardcoded white panel under a dark page is white text on white. */
  --panel: #fff;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 1.5rem clamp(1rem, 4vw, 3rem) 4rem;
  background: var(--paper);
  color: var(--ink);
  font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

h1 { font-size: 1.5rem; margin: 0 0 0.25rem; letter-spacing: -0.01em; }
h2 { font-size: 1rem; margin: 0 0 0.5rem; text-transform: uppercase; letter-spacing: 0.06em; }

.standfirst { margin: 0 0 0.5rem; font-size: 1.05rem; }
/* `.posture` was removed 2026-08-19 with the block it styled (OWNER-SHAPE (c)).
   No element carries the class now, so the rule went with it. */

/* ─────────────────────────────────────────────────────────────────────────────
 * THE TWO COLUMNS (session 19).
 *
 * A sticky rail holds what a reader SETS and what qualifies the screen; the
 * main column holds what a reader READS. The rail is first in the DOM, which is
 * also the mobile reading order — controls, then status, then rows.
 *
 * ⚠️ THE ONE RULE IN THIS FILE THAT IS A RULING RATHER THAN A CHOICE:
 * `.price-clock` lives inside `.screen`, above `.rows`, and no media query
 * moves it. PRICE-CLOCK (f) requires the staleness strip above the rows on
 * EVERY layout including the mobile one. In the rail it would be beside the
 * rows on a desktop, which is not above them, and the phone layout would hide
 * that from anyone testing on a phone.
 * ───────────────────────────────────────────────────────────────────────────*/
.cockpit-columns { display: grid; grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); gap: 1.5rem; align-items: start; }
.rail { position: sticky; top: 1rem; align-self: start; max-height: calc(100vh - 2rem); overflow-y: auto; }
.screen { min-width: 0; }

@media (max-width: 60rem) {
  /* The rail collapses to a top strip. It is still FIRST, and the price clock
   * is still the first thing in the column below it. */
  .cockpit-columns { grid-template-columns: minmax(0, 1fr); }
  .rail { position: static; max-height: none; overflow-y: visible; }
}

/* Disclosure controls. Used by the provenance expander, the gates and every
 * row's receipt — everything session 19 moved one click deep rather than
 * deleting. The summary is always a sentence, never a bare arrow. */
.disclosure-summary { cursor: pointer; font-weight: 600; }
.disclosure-body { padding-top: 0.5rem; }

.status-strip { border: 1px solid var(--rule); background: var(--panel); padding: 0.7rem 0.9rem; margin-bottom: 1rem; }
.status-line { margin: 0 0 0.4rem; font-weight: 600; }
.provenance-details .provenance, .provenance-details .live, .provenance-details .depth { margin-bottom: 0.75rem; }

/* Provenance sits ABOVE the data. Reading order is the argument. */
.provenance {
  border: 1px solid var(--rule);
  border-left: 4px solid var(--ink);
  background: var(--panel);
  padding: 0.85rem 1rem;
  margin-bottom: 1.25rem;
}
.provenance p { margin: 0 0 0.5rem; max-width: 80ch; }
.provenance p:last-child { margin-bottom: 0; }
.provenance .band { font-weight: 600; }
.provenance .bound { color: var(--no); }

.gates { border: 1px solid var(--rule); background: var(--neutral-bg); padding: 0.85rem 1rem; margin-bottom: 1.25rem; }
.gates .lede { margin: 0 0 0.75rem; max-width: 80ch; color: var(--muted); }
.gates dt { font-weight: 650; margin-top: 0.6rem; }
.gates dd { margin: 0.2rem 0 0.6rem 0; max-width: 80ch; }
.gates .evidence { margin: 0 0 0.2rem; }
.gates .lifts { margin: 0; color: var(--muted); font-style: italic; }

.threshold {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--rule);
  background: var(--panel);
  margin-bottom: 1.25rem;
}
.threshold label { flex: 1 1 100%; font-weight: 600; }
.threshold input { padding: 0.35rem 0.5rem; border: 1px solid var(--rule); font: inherit; width: 8rem; }
.threshold button { padding: 0.35rem 0.9rem; font: inherit; cursor: pointer; }
.threshold-error:empty { display: none; }
.threshold-error { flex: 1 1 100%; margin: 0; color: var(--no); }
.threshold-note { flex: 1 1 100%; margin: 0; color: var(--muted); max-width: 80ch; }

.summary { margin-bottom: 1.25rem; }
.summary p { margin: 0 0 0.4rem; max-width: 80ch; }
.verdict-summary { font-weight: 600; }
.counterpart-summary { color: var(--muted); }

.rows { list-style: none; margin: 0; padding: 0; }

.row { border: 1px solid var(--rule); border-top-width: 0; padding: 0.7rem 0.9rem; background: var(--panel); }
.row:first-child { border-top-width: 1px; }
.row-rejected { background: var(--no-bg); border-left: 4px solid var(--no); }
.row-no-two-sided-quote { background: var(--measure-bg); border-left: 4px solid var(--measure); }
.row-not-rejected { border-left: 4px solid var(--rule); }

.row-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
/* THE FACE: the three figures a reader scans a list on, on one line where the
 * width allows. Everything qualifying them is behind `.row-detail`. */
.row-face { display: flex; flex-wrap: wrap; gap: 0.2rem 1rem; margin-top: 0.3rem; font-size: 0.9rem; color: var(--muted); }
.row-face .optimism { font-weight: 600; color: var(--ink); }
.row-face .pm-fee-short { font-variant-numeric: tabular-nums; }
.row-detail { margin-top: 0.4rem; }
.row-detail > .disclosure-summary { font-weight: 500; font-size: 0.85rem; color: var(--muted); }
.row-boilerplate { border: 1px solid var(--rule); background: var(--neutral-bg); padding: 0.7rem 0.9rem; margin-bottom: 0.75rem; }
.row-boilerplate p { margin: 0 0 0.4rem; max-width: 80ch; color: var(--muted); font-size: 0.9rem; }
.row-boilerplate p:last-child { margin-bottom: 0; }
.band-withheld { color: var(--measure); }
.verdict {
  font-weight: 700;
  letter-spacing: 0.05em;
  font-size: 0.8rem;
  padding: 0.1rem 0.4rem;
  border: 1px solid currentColor;
}
.row-rejected .verdict { color: var(--no); }
.row-no-two-sided-quote .verdict { color: var(--measure); }
.row-not-rejected .verdict { color: var(--muted); }
.title { font-weight: 600; }
.outcome { color: var(--muted); }

.row-figures { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; margin-top: 0.35rem; color: var(--muted); font-size: 0.9rem; }
.row-figures .optimism { font-weight: 600; color: var(--ink); }

.line { margin: 0.4rem 0 0; max-width: 80ch; }

.no-input { border: 1px solid var(--rule); background: var(--panel); padding: 1rem; max-width: 80ch; }
.no-input .reason { color: var(--no); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9rem; }
.empty { border: 1px solid var(--rule); background: var(--panel); padding: 1rem; }

/* ─────────────────────────────────────────────────────────────────────────────
 * THE PRICE CLOCK (session 18, PRICE-CLOCK (f)).
 *
 * It is the first block on the screen and it is styled to be read first. The
 * capture state uses the same red the rejection rows use, on purpose: this
 * screen already teaches that red means "a number here does not hold", and a
 * stale price is exactly that fact about every number below it.
 * ───────────────────────────────────────────────────────────────────────────*/
.price-clock { border: 1px solid var(--rule); padding: 0.75rem 1rem; margin-bottom: 1rem; }
.price-clock p { margin: 0 0 0.4rem; max-width: 80ch; }
.price-clock p:last-child { margin-bottom: 0; }
.price-clock-capture { border-left: 4px solid var(--no); background: var(--no-bg); }
.price-clock-capture .price-clock-line { font-weight: 700; color: var(--no); }
.price-clock-capture .price-clock-measured,
.price-clock-capture .price-clock-qualified { color: var(--ink); }
.price-clock-live { border-left: 4px solid var(--rule); background: var(--neutral-bg); color: var(--muted); }

/* ─────────────────────────────────────────────────────────────────────────────
 * DERIVATION RECEIPTS. Shared by the settlement cockpit and the public screen.
 *
 * The summary is the number; the body is the arithmetic. Collapsed by default
 * because a screen that expanded every receipt would be unreadable, and a
 * number nobody can expand is the thing this project keeps paying for.
 * ───────────────────────────────────────────────────────────────────────────*/
.figures { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.6rem; }
.figure { border: 1px solid var(--rule); background: var(--panel); }
.figure-summary { cursor: pointer; padding: 0.35rem 0.6rem; display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; }
.figure-label { color: var(--muted); font-size: 0.9rem; }
.figure-value { font-weight: 700; font-variant-numeric: tabular-nums; }
.derivation { padding: 0.2rem 0.9rem 0.7rem; border-top: 1px solid var(--rule); font-size: 0.9rem; }
.derivation h4 { margin: 0.6rem 0 0.15rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); }
.derivation p { margin: 0; max-width: 80ch; }
.derivation ul { margin: 0; padding-left: 1.1rem; max-width: 80ch; }
.derivation-formula { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.derivation-bound { color: var(--no); }

/* ─────────────────────────────────────────────────────────────────────────────
 * THE DENSE MARKET SCREEN (session 22, Wave 1 item 1).
 *
 * A wide table has to scroll inside its own container — the page never scrolls
 * sideways. Absences are muted but PRESENT: a labelled "not measurable" is a
 * value on this screen, not a gap, and styling it invisible would undo the
 * model's whole refusal discipline.
 * ───────────────────────────────────────────────────────────────────────────*/
.screen-clock { border: 1px solid var(--rule); border-left: 4px solid var(--rule); background: var(--neutral-bg); color: var(--muted); padding: 0.75rem 1rem; margin-bottom: 1rem; }
.screen-clock p { margin: 0 0 0.4rem; max-width: 90ch; }
.screen-clock p:last-child { margin-bottom: 0; }
.screen-clock-warning { color: var(--no); font-weight: 700; }
.screen-controls { border: 1px solid var(--rule); background: var(--panel); padding: 0.75rem 1rem; margin-bottom: 1rem; }
.screen-filters { display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; align-items: center; }
.screen-filters label { font-size: 0.85rem; color: var(--muted); }
/* `var(--panel)`, not the undefined `--bg` this rule shipped with — an
 * undefined variable falls back to transparent, which happened to look right
 * on the light theme and vanished the field on the dark one. */
.screen-filters input[type="text"], .screen-search input { padding: 0.25rem 0.4rem; border: 1px solid var(--rule); background: var(--panel); color: var(--ink); min-width: 7ch; }
.screen-filter-error { color: var(--no); margin: 0.4rem 0 0; width: 100%; }
.watchlist-note { color: var(--no); max-width: 90ch; }
.screen-summary { margin-bottom: 0.75rem; }
.screen-summary p { margin: 0 0 0.3rem; max-width: 90ch; }
.screen-truncation { color: var(--muted); }
.screen-exclusion { color: var(--muted); }
.screen-table-wrap { overflow-x: auto; border: 1px solid var(--rule); }
.screen-table { border-collapse: collapse; width: 100%; font-size: 0.85rem; }
.screen-table th, .screen-table td { padding: 0.3rem 0.5rem; border-bottom: 1px solid var(--rule); text-align: left; vertical-align: top; }
.screen-table th { position: sticky; top: 0; background: var(--panel); }
.screen-table button.sort { background: none; border: none; color: var(--ink); font: inherit; font-weight: 700; cursor: pointer; padding: 0; }
.screen-table button.watch { background: none; border: none; cursor: pointer; font-size: 1rem; color: var(--muted); }
.screen-table button.watch.watched { color: var(--accent, #765DCF); }
.cell-price, .cell-spread, .cell-mid, .cell-breakeven, .cell-fair-value, .cell-signature { font-variant-numeric: tabular-nums; white-space: nowrap; }
.cell-market .market-title { font-weight: 600; }
.cell-market .market-outcome { color: var(--muted); }
.cell-absent .absent { color: var(--muted); font-style: italic; }
.bound-interval { color: var(--muted); font-size: 0.8rem; }
.signature-direction { display: block; color: var(--muted); font-size: 0.75rem; }
.bound-receipt summary { color: var(--muted); font-size: 0.75rem; cursor: pointer; }
.bound-receipt-body { font-size: 0.8rem; max-width: 60ch; white-space: normal; }
.bound-receipt-body p { margin: 0.2rem 0; }
.screen-empty, .screen-state { border: 1px solid var(--rule); background: var(--panel); padding: 1rem; max-width: 90ch; }
.screen-failed { color: var(--no); }

/* ── THE MARKET-OVERVIEW GRID (session 24). Sequential single-hue ramp,
   lightness monotone light→dark, dark ink readable on every step; the numbers
   are text IN the cell, so color is a second encoding, never the only one.
   Absences wear the neutral tone, deliberately off the ramp. 2px gaps between
   fills via border-spacing (the data-viz spacer rule). ───────────────────── */
.overview-framing, .overview-degradation, .overview-composition, .overview-cell-key { max-width: 90ch; }
.overview-degradation { color: var(--muted); }
.overview-cap-note { color: var(--no); max-width: 90ch; font-weight: 600; }
.overview-legend { max-width: 90ch; }
.overview-swatch { display: inline-block; padding: 0.1rem 0.5rem; margin: 0 0.25rem 0.25rem 0; border: 1px solid var(--rule); font-size: 0.8rem; white-space: nowrap; }
.overview-table { border-collapse: separate; border-spacing: 2px; font-size: 0.85rem; }
.overview-table th { text-align: left; padding: 0.3rem 0.5rem; background: var(--panel); }
.overview-table td { padding: 0.3rem 0.5rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.overview-table td.cost-0, .overview-swatch.cost-0 { background: #FFF6E0; }
.overview-table td.cost-1, .overview-swatch.cost-1 { background: #FFE3A8; }
.overview-table td.cost-2, .overview-swatch.cost-2 { background: #FFC85E; }
.overview-table td.cost-3, .overview-swatch.cost-3 { background: #F0A513; }
.overview-table td.cost-4, .overview-swatch.cost-4 { background: #C77F00; }
/* The ramp fills are literal light ambers, so their ink must be literal dark
 * ink in BOTH themes: the web build re-points `--ink` light, and light ink on
 * cost-0's near-white fill is text nobody can read. Dark ink clears WCAG AA
 * on every step (5.54:1 on the darkest, #C77F00). Descendant spans inherit,
 * so the cost figure does not render amber-on-amber inside a ramp cell. */
.overview-table td.cost-0, .overview-table td.cost-1, .overview-table td.cost-2,
.overview-table td.cost-3, .overview-table td.cost-4,
.overview-swatch.cost-0, .overview-swatch.cost-1, .overview-swatch.cost-2,
.overview-swatch.cost-3, .overview-swatch.cost-4 { color: #14171a; }
td.overview-cell .overview-cost { color: inherit; }
.overview-table td.overview-absent, .overview-swatch.overview-absent { background: var(--neutral-bg); color: var(--muted); }
.overview-table td.overview-empty { color: var(--muted); text-align: center; }
.overview-cost { color: var(--measure); }
.overview-uncategorised th { font-style: italic; color: var(--muted); }

/* ─────────────────────────────────────────────────────────────────────────────
 * SHARED COMPONENTS ADDED BY THE DESIGN-SYSTEM SESSION (2026-08-12). The
 * renderers in `src/app/` emit these on both build targets; this sheet carries
 * the light-idiom defaults so the extension stays styled, and `site.css`
 * restyles them for the public dark-first system.
 * ───────────────────────────────────────────────────────────────────────────*/

/* the data-age chip: age in words, always; the dot is the second encoding */
.age-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-size: 0.7rem;
  font-weight: 600;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--muted);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 3px 9px;
  /* ── THE CHIP'S TEXT IS DATA, SO NOTHING HERE MAY ASSUME A LENGTH (CHIPWRAP)
   * This rule read `white-space: nowrap` and it was the whole defect. A chip's
   * words are chosen by which branch of `src/app/age-chip.ts` the stamp lands
   * in, and the fault branches are long: an upstream a venue has published past
   * runs to 94 characters. Under nowrap that string became the DOCUMENT's
   * width, and on 2026-08-27 three public pages scrolled sideways at 543 and
   * 568 px on a 390 px phone.
   *
   * `site.css` believed it had already fixed this. It gave the chip
   * `flex-wrap: wrap` and a comment saying the nowrap was taken out — but the
   * declaration it removed was its OWN, and this one, in the sheet every page
   * loads first, stayed. Neither sheet then declared `white-space` at a
   * winning weight, so the chip kept the value from here. `flex-wrap` never
   * had anything to wrap: the chip is a leaf and its text is ONE anonymous
   * flex item, so it can only fold if that item's own text may break.
   *
   * Both halves are kept and both are load-bearing. `flex-wrap` moves the text
   * off the dot's line; the default `white-space` breaks the text itself. The
   * dot below stays atomic on `flex: none`, and `.age-chip > *` keeps any
   * child element a later session adds unbroken.
   *
   * DO NOT RESTORE `white-space: nowrap` HERE OR IN `site.css`. The chip arm in
   * `tools/viewport-width.ts` renders every branch and measures the document,
   * so a restored nowrap is a red rather than a discovery. */
  flex-wrap: wrap;
  row-gap: 0.15em;
  vertical-align: middle;
}
.age-chip > * { white-space: nowrap; }
.age-chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--muted); flex: none; }
.age-chip[data-stale="true"] { color: var(--measure); border-color: var(--measure); background: var(--measure-bg); }
.age-chip[data-stale="true"]::before { background: var(--measure); }

/* the refusal card: the reason, then the receipt of why — never an empty state */
.refusal-card {
  background: var(--no-bg);
  border-left: 4px solid var(--no);
  padding: 0.75rem 1rem;
  max-width: 80ch;
}
.refusal-card .refusal-reason { display: block; color: var(--no); font-weight: 600; }
.refusal-card .refusal-detail { display: block; margin-top: 0.25rem; color: var(--ink); font-size: 0.9rem; }

/* receipt stage 2: the hover popover lives inside the closed summary */
.figure { position: relative; }
.receipt-pop {
  display: none;
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  z-index: 40;
  min-width: 18rem;
  max-width: 30rem;
  background: var(--panel);
  border: 1px solid var(--rule);
  padding: 0.5rem 0.75rem;
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--muted);
  white-space: normal;
}
details:not([open]) > summary:hover .receipt-pop,
details:not([open]) > summary:focus-visible .receipt-pop { display: block; }
.receipt-pop .receipt-pop-formula { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; display: block; margin-bottom: 2px; }
.receipt-pop .receipt-pop-input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; display: block; }

/* receipt stage 4: the permalink */
.receipt-permalink { font-size: 0.75rem; color: var(--muted); text-decoration: none; }

/* the screener micro-bar: length + sign color, beside the number, never instead */
.micro-bar {
  display: block;
  height: 3px;
  background: var(--rule);
  position: relative;
  overflow: hidden;
  margin-top: 4px;
  min-width: 3.5rem;
}
/* THE MICRO-BAR'S SECOND CUE IS ITS ORIGIN, and the fallbacks are the light
 * pair (DIRECTION, 2026-09-03). Both directions grew from the same edge and
 * differed in fill alone; a negative bar now grows leftward from the right.
 * The extension target loads this sheet alone, so `var(--pos)` resolves to
 * nothing there and these fallbacks are what a reader sees — they were the
 * green and red the site's sheet retired. */
.micro-bar::before { content: ""; position: absolute; left: 0; right: auto; top: 0; bottom: 0; width: calc(var(--bar, 0) * 1%); background: var(--pos, #00845d); }
.micro-bar[data-dir="neg"]::before { left: auto; right: 0; background: var(--neg, #d45000); }
