/* ============================================================================
   Design tokens
   Palette is cool paper + ink, with two semantic colours that carry meaning
   rather than decoration: eucalypt = confirmed, ochre = reported/unverified.
   Type: Bricolage Grotesque (display), Newsreader (body), IBM Plex Mono (data).
   ========================================================================= */
:root {
  --paper:      #EFF1EF;
  --card:       #F7F8F7;
  --ink:        #14181A;
  --muted:      #6B7377;
  --rule:       #D6DBD8;
  --confirmed:  #0F6B5C;   /* verified figures, published state */
  --reported:   #B26B00;   /* reported but unconfirmed — always visible as such */
  --rejected:   #B23A2E;   /* editorial only: killed, never public */
  --company-tint:  #ECEDFF;   /* lavender: raised — took a round */
  --investor-tint: #ECFFEC;   /* green: invested in the round on the row */
  --raised-tint:   #FFF0C2;   /* gold: closed a fund of its own — money in, from LPs */
  --person-tint:   #FFF3E4;   /* a name, not an organisation */

  --display: "Bricolage Grotesque", "Helvetica Neue", sans-serif;
  --body: "Newsreader", Georgia, serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;

  --measure: 68ch;
  --gap: 1.5rem;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.55;
  font-optical-sizing: auto;
}

a { color: inherit; text-decoration: none; }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible { outline: 2px solid var(--confirmed); outline-offset: 3px; }

/* hidden wins over any display a class sets, so a script can hide with the attribute. */
[hidden] { display: none !important; }

.wrap { max-width: 1080px; margin: 0 auto; padding: 0 1.25rem; }
.narrow { max-width: 640px; }

/* --- Masthead ------------------------------------------------------------ */
.masthead { border-bottom: 1px solid var(--rule); background: var(--paper);
  position: sticky; top: 0; z-index: 20; }
.masthead-inner { display: flex; align-items: baseline; gap: 2rem;
  padding: 1rem 0 0.9rem; flex-wrap: wrap; }
.wordmark { font-family: var(--display); font-weight: 800; font-size: 1.35rem;
  letter-spacing: -0.03em; font-stretch: 115%; }
.wordmark span { color: var(--confirmed); }
.tagline { font-family: var(--mono); font-size: 0.68rem; text-transform: uppercase;
  letter-spacing: 0.14em; color: var(--muted); }
/* The search bar from the search page, as it was, on the nav's own line at
   its left hand. */
.masthead-search { display: flex; gap: 0.6rem; align-items: center; }
.masthead-search input[type=text] { width: 260px; padding: 0.5rem; border-radius: 10px; }
.masthead-search .btn { padding: 0.5rem 1rem; border-radius: 10px; }
nav.primary { margin-left: 1rem; display: flex; gap: 1.4rem; align-items: baseline;
  font-family: var(--mono); font-size: 0.75rem; text-transform: uppercase;
  letter-spacing: 0.09em; }
nav.primary a { color: var(--muted); padding-bottom: 2px; border-bottom: 1px solid transparent; }
nav.primary a:hover, nav.primary a.active { color: var(--ink); border-color: var(--ink); }
nav.primary a.tip-link { color: var(--confirmed); }
nav.primary a.staff-link { color: var(--reported); }
/* The links' box is no box on a desktop: its anchors lay out as the nav's
   own items, beside the search. The menu button is for phone width only. */
.primary-links { display: contents; }
.menu-toggle { display: none; }
/* Wording a phone shows in place of the desktop's, e.g. "Src" for a column
   headed "Source": the two sit side by side in the markup, this one hidden
   until the phone rule swaps them. */
.phone { display: none; }

/* Backlog badge: any drafts awaiting review flag the Review link and Draft tab. */
.count-badge { display: inline-block; min-width: 1.6em; margin-left: 0.45em;
  padding: 0.05rem 0.4em; border-radius: 999px; background: var(--rejected);
  color: var(--card); font-size: 0.62rem; letter-spacing: 0; text-align: center;
  vertical-align: 0.12em; }

/* --- Section headers ----------------------------------------------------- */
.eyebrow { font-family: var(--mono); font-size: 0.68rem; text-transform: uppercase;
  letter-spacing: 0.16em; color: var(--muted); margin: 2.5rem 0 0.75rem; }
h1 { font-family: var(--display); font-weight: 800; letter-spacing: -0.035em;
  font-size: clamp(1.9rem, 4vw, 2.8rem); line-height: 1.05; margin: 0 0 0.4rem; font-stretch: 110%; }
h2 { font-family: var(--display); font-weight: 700; letter-spacing: -0.02em;
  font-size: 1.15rem; margin: 2rem 0 0.75rem; }
h3 { font-family: var(--display); font-weight: 600; font-size: 0.95rem; margin: 1.25rem 0 0.4rem; }

/* ============================================================================
   THE STAGE RAIL — the signature element.
   Every feed entry carries a marker whose horizontal position encodes round
   stage, pre-seed at the left through Series D+ at the right. Scroll the feed
   and the shape of the market becomes visible in the left margin.
   ========================================================================= */
.entry { display: grid; grid-template-columns: 132px 1fr; gap: 1.25rem;
  padding: 1.1rem 0; border-bottom: 1px solid var(--rule); }
.entry:hover { background: linear-gradient(90deg, rgba(15,107,92,0.045), transparent 45%); }

/* Three stacked bands, so a long stage name ("Undisclosed stage") never runs
   under the dot or the track: label on top, track and dot in the middle,
   amount below. */
.rail { position: relative; height: 100%; min-height: 48px; }
.rail::before { content: ""; position: absolute; left: 0; right: 0; top: 22px;
  height: 1px; background: var(--rule); }
.rail-dot { position: absolute; top: 17px; width: 11px; height: 11px; border-radius: 50%;
  background: var(--confirmed); transform: translateX(-50%);
  box-shadow: 0 0 0 3px var(--paper); }
.rail-dot.estimate { background: var(--paper); border: 2px solid var(--reported); }
.rail-amount { position: absolute; top: 33px; font-family: var(--mono); font-size: 0.7rem;
  font-weight: 500; transform: translateX(-50%); white-space: nowrap; color: var(--ink); }
.rail-stage { position: absolute; top: 0; left: 0; line-height: 1; font-family: var(--mono);
  font-size: 0.58rem; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.07em; }
/* Markers at the track's left end anchor left instead of centring on their
   position, so nothing pokes past the page's content line into the margin. */
.rail-dot.flush, .rail-amount.flush { transform: none; }
/* A fund close sits at the track's far end — the money's source, not a stage
   on the way — and anchors right for the same reason. */
.rail-dot.end, .rail-amount.end { left: auto; right: 0; transform: none; }

.rail.no-round::before { background: transparent; }
.rail-kind { font-family: var(--mono); font-size: 0.62rem; text-transform: uppercase;
  letter-spacing: 0.11em; color: var(--muted); }

.entry-body h3 { margin: 0 0 0.25rem; font-family: var(--display); font-weight: 600;
  font-size: 1.06rem; line-height: 1.3; letter-spacing: -0.01em; }
.entry-body h3 a:hover { color: var(--confirmed); }
.entry-summary { margin: 0.2rem 0 0.45rem; color: #2C3236; font-size: 0.97rem; }
.byline { font-family: var(--mono); font-size: 0.68rem; color: var(--muted);
  display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
.byline .src::after { content: "·"; margin-left: 0.6rem; color: var(--rule); }
/* The outlet name is a link when we hold a page for it, and plain text when we
   don't — underlined on hover only, so a byline of forty rows doesn't read as
   forty links competing with the headline above them. */
.byline .src a { color: var(--muted); }
.byline .src a:hover { color: var(--confirmed); border-bottom: 1px solid var(--confirmed); }
.chip { font-family: var(--mono); font-size: 0.66rem; padding: 1px 7px;
  border: 1px solid var(--rule); border-radius: 2px; color: var(--ink); background: var(--card); }
.chip:hover { border-color: var(--confirmed); color: var(--confirmed); }
/* A person's chip is tinted so a byline of five chips reads at a glance as
   "three organisations and two people" rather than as one undifferentiated
   row of names. */
.chip-person { background: var(--person-tint); }
/* The byline's money colours: lavender = got the money, green = put money in,
   plain = merely mentioned — the only thing a chip's colour ever means; the
   review queue's flip chips carry the same tint for the same reason, and say
   page type in words. The fundee is also listed first, so a funding row
   answers "who got it" before "who else is named". At chip size the darker
   edge, not the fill, is what separates a tinted chip from an ordinary
   mention. */
.chip-investee { background: var(--company-tint); border-color: #A9AEE0; }
.chip-investor { background: var(--investor-tint); border-color: #9CCF9C; }
/* A fund close is its own thing: money came in, but from LPs to a fund that
   will invest it — neither a startup's raise nor an investment. */
.chip-raised { background: var(--raised-tint); border-color: #E0C26A; }

/* The rest of the coverage of one round, under the entry that leads it. Set in
   mono at byline weight so it reads as apparatus rather than as more headlines
   — the whole point of bundling is that these are the same story. */
.also { margin: 0.35rem 0 0; font-family: var(--mono); font-size: 0.66rem;
  line-height: 1.85; color: var(--muted); }
.also-label { text-transform: uppercase; letter-spacing: 0.12em; font-size: 0.6rem;
  color: var(--muted); margin-right: 0.45rem; }
.also a { color: var(--muted); border-bottom: 1px solid var(--rule); }
.also a:hover { color: var(--confirmed); border-bottom-color: var(--confirmed); }
.also-sep { margin: 0 0.4rem; color: var(--rule); }

/* --- Data tables --------------------------------------------------------- */
table.data { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
table.data th { font-family: var(--mono); font-size: 0.63rem; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted); text-align: left; font-weight: 500;
  padding: 0.5rem 0.75rem 0.5rem 0; border-bottom: 1px solid var(--rule); }
table.data td { padding: 0.7rem 0.75rem 0.7rem 0; border-bottom: 1px solid var(--rule);
  vertical-align: top; }
/* A figure is data the row states, the same as the stage beside it, so it is
   set in the same voice: one table, one face, one size. What the column still
   needs from the data face it keeps — tabular figures, so digits line up down
   the column, and no wrapping, so a date or an amount is never broken across
   two lines. The mono face is for what is read as characters rather than as
   words — an ACN, a URL, a label — not for every cell holding a digit. */
table.data td.num { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* A heading names its column's kind, and the kind is the least width the
   column can be given: a date, an amount or a count is never crushed, and
   the slack goes to whichever column holds the long content beside them. The
   layout is automatic, so a table scales with the window and each page keeps
   its own columns; a table wider than its section scrolls inside .scroll-x.
   A column of one kind is the same on every page, because its width has one
   definition here. Two kinds have no least width, because they are the long
   content the slack is for: "text" (a description, a note) and "chips" (a
   run of names). The heading of every data table carries exactly one kind
   (core/tests_templates). */
/* A name column is 10rem, which leaves 148px for the name beside the cell's
   padding: 95% of company names fit on one line. Not ch, because a heading's
   ch is its own small mono type, and 14ch there came to 85px. */
table.data th.name { min-width: 10rem; }
table.data th.word { min-width: 7rem; }
/* A date column holds the longest date the formatter writes, "30 Sep 2025",
   on one line. The article's own wording still shows where no date could be
   derived from it, and a phrase like "across April and May this year" wraps
   in the cell rather than running into the amount beside it. */
table.data th.date { min-width: 8rem; }
table.data td.date { white-space: normal; }
/* An amount column carries a pair — "US$10m (A$14.1m)" — for every deal the
   article sized in a currency that is not ours. 23ch is the widest pair the
   compact writer can produce, and the column is that wide on every page,
   whether or not the rows on this one happen to hold a foreign figure: two
   tables of the same kind then line up, and a filter cannot make the column
   jump as rows come and go. */
table.data th.money, table.data td.money { width: 23ch; }
table.data th.count { min-width: 5ch; }
table.data th.link { min-width: 6rem; }
table.data th.tick { min-width: 4ch; }
table.data tr:hover td { background: rgba(15,107,92,0.03); }
/* A long word in a cell wraps rather than pushing the column wide. */
table.data td { overflow-wrap: anywhere; }
/* A table's Sources column (templates/_sources.html) is muted and smaller
   than the row's facts. The list is a block so that when it wraps, its lines
   are spaced for its own size rather than the cell's. */
table.data .sources { display: block; color: var(--muted); font-size: 0.8rem; }
/* A heading that sorts is a link in the heading's own dress, not a button;
   the column the table is sorted on is the one in ink, with the arrow. */
table.data th a { color: inherit; text-decoration: none; }
table.data th a:hover { color: var(--confirmed); }
table.data th.sorted { color: var(--ink); }
table.data th .sort-arrow { font-size: 0.55rem; visibility: hidden; }   /* keeps its width */
table.data th.sorted .sort-arrow { visibility: visible; }
/* A score row that unfolds: the row itself is the toggle, and the hidden row
   beneath holds its errors grouped under the column each one dents. */
table.data tr[data-errors] { cursor: pointer; }
/* The critical columns — the facts a published item cannot be wrong about —
   read as one block at the left of the score table. */
table.data th.critical { color: var(--ink); font-weight: 600; }
table.data td.critical { background: rgba(15,107,92,0.05); }
table.data tr.score-errors > td { padding: 0.2rem 0.75rem 1.1rem 1.25rem;
  background: rgba(15,107,92,0.03); }
.errors-head { font-family: var(--mono); font-size: 0.63rem; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted); margin: 0.9rem 0 0.15rem; }
.errors-list { margin: 0; padding-left: 1.1rem; font-size: 0.85rem; }
.errors-list li { margin: 0.2rem 0; }

/* --- Company profile ----------------------------------------------------- */
.profile-head { display: grid; grid-template-columns: 1fr auto;
  align-items: end; padding: 2.5rem 0 1.25rem; }
.profile-head .eyebrow { margin-top: 0; }
/* The line under the name, and the links at the head's right. */
.head-lede { max-width: var(--measure); margin: 0.4rem 0 0; }
.head-links { text-align: right; font-family: var(--mono); font-size: 0.72rem; color: var(--muted); }
.measured { max-width: var(--measure); }
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 1px; background: var(--rule); border: 1px solid var(--rule); margin: 1.5rem 0 2rem; }
.fact { background: var(--paper); padding: 0.85rem 0.9rem; }
.fact dt { font-family: var(--mono); font-size: 0.6rem; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--muted); margin-bottom: 0.3rem; }
.fact dd { margin: 0; font-family: var(--mono); font-size: 1.05rem;
  font-variant-numeric: tabular-nums; }

/* Fact tiles that are also the navigation. Same grid, same cell — the only
   additions are the affordance (hover, cursor) and the marker on the active
   one, because a tile that reads as a static counter but behaves as a link is
   the thing this replaces. */
.tabs .tab { display: block; text-decoration: none; color: var(--ink);
  border-top: 2px solid transparent; }
.tabs .tab:hover { background: var(--card); }
.tabs .tab.active { border-top-color: var(--confirmed); background: var(--card); }
.tab-label { display: block; font-family: var(--mono); font-size: 0.6rem;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted);
  margin-bottom: 0.3rem; }
.tabs .tab.active .tab-label { color: var(--confirmed); }
.tab-count { display: block; font-family: var(--mono); font-size: 1.05rem;
  font-variant-numeric: tabular-nums; }
.tab-note { margin: 0.2rem 0 1rem; color: var(--muted); font-size: 0.9rem;

  max-width: var(--measure); }
h1 .tab-note { margin-left: 0.5rem; font-weight: normal; }
/* A record's one line under its name: in a table row, and under the name of a
   search result (plans/eyebrow-line.md). */
.one-liner { display: block; color: var(--muted); font-size: 0.85rem; }

/* The profile's tab bar. Not a grid of tiles like .facts above it: a tab bar
   navigates, so its cells are sized to their words and the body below is
   whichever panel is open. Nothing but the labels and one line under the open
   one: no rule along the bar, no dividers between. The bar stops being a
   container and becomes a line of labels, which is what it is, and the space
   under it is what holds it apart from the panel (Luke, 2026-09-04). */
.tabbar { display: flex; flex-wrap: wrap; align-items: stretch;
  margin: 1.5rem 0 1.9rem; }
.tabbar .tab { display: flex; align-items: baseline; gap: 0.4rem;
  padding: 0.7rem 0.95rem 0.6rem; text-decoration: none; color: var(--ink);
  border-bottom: 2px solid transparent; }
/* Flush left: with the dividers gone there is no cell edge for the first
   tab's padding to sit inside, and an indent would put the bar out of line
   with the name above it and the table below. */
.tabbar .tab:first-child { padding-left: 0; }
.tabbar .tab:hover .tab-label { color: var(--confirmed); }
.tabbar .tab.active { border-bottom-color: var(--confirmed); }
/* Label and value on one line, "Funding: $16m". The label is the thing being
   navigated to, so it leads: display face, at reading size, in ink. The value
   is what that tab happens to hold, so it follows in the data face, smaller
   and muted. The colon is punctuation between them and lives here rather than
   in the markup. */
.tabbar .tab-label { display: inline; margin: 0; font-family: var(--display);
  font-size: 0.9rem; font-weight: 600; letter-spacing: 0; text-transform: none;
  color: var(--ink); }
.tabbar .tab-label::after { content: ":"; }
/* A tab with no figure is its label alone, and a colon introducing nothing
   is a colon that should not be there. */
.tabbar .tab-label:only-child::after { content: none; }
.tabbar .tab.active .tab-label { color: var(--confirmed); }
.tabbar .tab-count { display: inline; font-size: 0.78rem; color: var(--muted); }
/* A panel that holds more than one heading — Funds and the two tables about
   who is in them, Coverage and the names it shares — needs the eye to see
   where one ends and the next begins, so a second heading gets a clear line of
   air above it. The first takes its distance from the tab bar instead. */
.tab-panel h2 { margin-top: 3.25rem; }
.tab-panel > h2:first-child { margin-top: 0; }

/* Where it is, when it started, what it is registered as — under the name,
   because a tab bar is for navigating and these navigate nowhere. */
.head-facts { margin: 0.5rem 0 0; font-family: var(--mono); font-size: 0.68rem;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); }
.head-facts span + span::before { content: " · "; }

/* Second line inside a table cell: the description under a name, at byline
   weight so it stays subordinate to the link above it. */
.row-line { display: block; margin-top: 0.15rem; font-family: var(--mono);
  font-size: 0.63rem; color: var(--muted); }

.ladder { list-style: none; padding: 0; margin: 0; }
.ladder .byline { margin-top: 0.4rem; }
.ladder li.none { border-left-color: transparent; }
.ladder li { position: relative; padding: 0 0 1.4rem 1.75rem; border-left: 1px solid var(--rule); }
.ladder li:last-child { border-left-color: transparent; padding-bottom: 0; }
.ladder li::before { content: ""; position: absolute; left: -5px; top: 6px; width: 9px;
  height: 9px; border-radius: 50%; background: var(--confirmed); }
.ladder .stage { font-family: var(--display); font-weight: 700; font-size: 1rem; }
.ladder .amount { font-family: var(--mono); font-size: 1.15rem; font-variant-numeric: tabular-nums; }
.ladder .meta { font-family: var(--mono); font-size: 0.7rem; color: var(--muted); }

/* Attribution for anything reported rather than confirmed. */
.reported { color: var(--reported); border-bottom: 1px dotted var(--reported); cursor: help; }
.reported-note { font-family: var(--mono); font-size: 0.68rem; color: var(--reported);
  background: rgba(178,107,0,0.07); border-left: 2px solid var(--reported);
  padding: 0.5rem 0.7rem; margin: 0.6rem 0; }

/* --- Forms --------------------------------------------------------------- */
form.stack { display: grid; gap: 1.1rem; }
form.stack label { display: block; font-family: var(--mono); font-size: 0.68rem;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin-bottom: 0.35rem; }
input[type=text], input[type=search], input[type=email], input[type=url], textarea, select {
  width: 100%; font-family: var(--body); font-size: 1rem; padding: 0.65rem 0.75rem;
  background: var(--card); border: 1px solid var(--rule); border-radius: 2px; color: var(--ink); }
textarea { font-size: 0.97rem; }
.helptext { font-size: 0.82rem; color: var(--muted); margin-top: 0.3rem; }
.btn { display: inline-block; font-family: var(--mono); font-size: 0.75rem;
  text-transform: uppercase; letter-spacing: 0.1em; padding: 0.7rem 1.4rem;
  background: var(--ink); color: var(--paper); border: 0; border-radius: 2px; cursor: pointer; }
.btn:hover { background: var(--confirmed); }
.btn.ghost { background: transparent; color: var(--ink); border: 1px solid var(--rule); }
/* Correction prompt at the foot of a record page. An ochre wash rather than a
   fill — the same colour that marks anything reported-but-unconfirmed, at the
   weight the reported-note uses, so it reads as a flag without shouting. */
.btn.correction { background: rgba(178,107,0,0.10); color: var(--reported);
  border: 1px solid rgba(178,107,0,0.35); }
.btn.correction:hover { background: rgba(178,107,0,0.18);
  border-color: var(--reported); }
.correction-cta { margin: 3.5rem 0 0; font-family: var(--mono); font-size: 0.72rem; }
.checkbox-row { display: flex; gap: 0.6rem; align-items: flex-start; }
/* A word that is its own control, as the pricing page's periods are. The
   radio is hidden but kept for the keyboard and the form, and the word
   shows the state: picked, it sits in the lavender the site uses for
   "raised a round"; otherwise it is the bare word. The padding and the
   border are always laid out, the border unseen until picked, so nothing
   moves when the choice changes. The rows of a word-checks dropdown carry
   the same class and restyle it below, keeping from here the pointer
   cursor, the focus outline and text that a click does not select. */
.word-check { position: relative; align-self: center; display: inline-flex; align-items: center;
  gap: 0.45rem; padding: 0.2rem 0.4rem; border: 1px solid transparent; border-radius: 50px;
  cursor: pointer; user-select: none; font-family: var(--mono); font-size: 0.6rem;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); }
.word-check:hover { color: var(--ink); }
.word-check input[type=radio] { position: absolute; opacity: 0; width: 1px; height: 1px;
  margin: 0; pointer-events: none; }
.word-check:has(input:checked) { background: var(--company-tint); border-color: #C8CBF2; color: var(--ink); }
.word-check:has(input:checked):hover { border-color: var(--ink); }
.word-check:has(input:focus-visible) { outline: 2px solid var(--confirmed); outline-offset: 2px; }
.word-checks { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 0.15rem 0.35rem; }
/* Folded, the words sit behind a button that opens them: a dropdown at every
   width (Luke, 2026-09-10), because a column of twenty-five chips is not a
   control anyone wants to read, on a phone or off one. Open, each row is the
   word on the left in ink at reading size and its box at one fixed distance
   from the edge, so ticking several is one movement down a column. The
   dropdown pushes what follows down rather than covering it, which is what
   it has always done at phone width. */
.checks-toggle::after { content: " ▾"; }
/* The button and the list it opens are one element, so the list can hang
   under the button rather than beside it, and a wrapping filter row cannot
   put the two on different lines. */
.checks { position: relative; display: inline-block; }
/* A filter's button says what nothing ticked means, e.g. "All types", until
   a box in its list is ticked, then its name and the count, e.g. "Types · 2"
   (Luke, 2026-09-11). Both wordings are in the button and the ticks pick
   one, so the words change with the boxes. Only a named box counts: the
   all-box has no name, and it is ticked exactly when nothing else is. */
.checks:has(input[name]:checked) .checks-all,
.checks:not(:has(input[name]:checked)) .checks-some { display: none; }
/* As wide as its longest word and no wider: max-content takes the width at
   which nothing wraps, and the rows stretch to it, so the boxes line up on
   one right edge whatever the words are. It hangs over what follows rather
   than pushing it down, since a control that moves the page when it opens
   moves whatever you were about to click. Taller than the screen it scrolls
   itself, twenty-five sectors being more than a list can show at once. */
.word-checks.dropdown { position: absolute; top: calc(100% + 0.25rem); left: 0; z-index: 20;
  width: max-content; max-width: min(28rem, 90vw); max-height: 60vh; overflow-y: auto;
  display: none; flex-direction: column; gap: 0;
  padding: 0.2rem 0; border: 1px solid var(--rule); border-radius: 10px;
  background: var(--card); box-shadow: 0 6px 18px rgba(20, 24, 26, 0.12); }
.word-checks.dropdown.open { display: flex; }
.word-checks.dropdown .word-check { display: flex; gap: 1.25rem; align-items: center;
  align-self: stretch; min-height: 1.9rem; padding: 0 0.7rem; border: 0; border-radius: 0;
  background: none; font-family: var(--body); font-size: 0.85rem; text-transform: none;
  letter-spacing: 0; color: var(--ink); }
.word-checks.dropdown .word-check:hover { background: var(--paper); }
/* The rule under the first row marks the reset off from the words it clears,
   so it belongs only to a group that has a reset: a group that sets a record
   has no all-box and its first row is an ordinary word. */
.word-checks.dropdown.has-all .word-check:first-child { border-bottom: 1px solid var(--rule); }
.word-checks.dropdown .word-check:has(input:checked) { background: none; }
/* The word takes the room it needs and pushes the box to the edge, rather
   than sitting in a column of a width picked in advance that the longer
   names would spill out of. */
.word-checks.dropdown .word-check > span { flex: 1 1 auto; }
.word-checks.dropdown .word-check input[type=checkbox] { order: 1; width: 1rem; height: 1rem;
  margin: 0; accent-color: var(--confirmed); }
/* A filter row under a heading: the search box, then the word-checks. */
.filter-row { display: flex; gap: 0.6rem; margin: 1.25rem 0; flex-wrap: wrap; }
.filter-row select, .filters select { width: auto; max-width: 240px; }
/* A filter dropdown is no wider than its widest member (Luke, 2026-09-10); a name box is a
   comfortable line, never the row. */
.filters input[type=search] { width: 14rem; }
/* The filter rows' search boxes, dressed like the masthead's. */
form[data-live-filter] input[type=search] { width: 260px; padding: 0.5rem; border-radius: 10px; }
.checkbox-row label { text-transform: none; letter-spacing: 0; font-family: var(--body);
  font-size: 0.95rem; color: var(--ink); margin: 0; }

/* ============================================================================
   REVIEW QUEUE — staff only.
   The row is the unmodified feed row, so a reviewer sees what a reader will.
   Actions sit in the right margin as a stacked column, never in the row itself.
   ========================================================================= */
.review-head { padding: 1.5rem 0 0.25rem; }
.review-lede { margin: 0.35rem 0 0; color: var(--muted); font-size: 0.97rem; }
/* Only for a lede long enough to run past a comfortable line. The queue's is one
   line at any width, so capping it there constrains nothing. */
.review-lede.measured { max-width: var(--measure); }

.review-entry { grid-template-columns: 132px 1fr minmax(160px, auto); align-items: start; }
.review-entry:hover { background: linear-gradient(90deg, rgba(178,107,0,0.05), transparent 55%); }

.review-actions { display: flex; flex-direction: column; gap: 0.35rem; }
/* The type of everything in the row's right-hand column: the buttons, the
   line standing in for them while a re-extraction runs, and the status. */
.rbtn, .reextract-busy, .review-status { font-family: var(--mono); font-size: 0.66rem;
  text-transform: uppercase; letter-spacing: 0.09em; padding: 0.45rem 0.8rem;
  text-align: center; }
.rbtn { background: var(--card); color: var(--ink); border: 1px solid var(--rule);
  border-radius: 2px; cursor: pointer; }
/* Where the entry stands, above the buttons that move it: a Coverage tab
   mixes every status. A draft is muted; the other three take their colour. */
.review-status { margin: 0; font-weight: 500; color: var(--muted); }
.review-status[data-status="published"] { color: var(--confirmed); }
.review-status[data-status="rejected"] { color: var(--rejected); }
.review-status[data-status="reported"] { color: var(--reported); }
.rbtn:disabled { opacity: 0.32; cursor: default; }
.rbtn.publish:hover:not(:disabled) { background: var(--confirmed); border-color: var(--confirmed); color: var(--paper); }
.rbtn.reject:hover:not(:disabled) { background: var(--rejected); border-color: var(--rejected); color: var(--paper); }
.rbtn.draft:hover:not(:disabled) { background: var(--reported); border-color: var(--reported); color: var(--paper); }

.rbtn.report { display: block; margin-top: 0.35rem; border-style: dashed;
  color: var(--rejected); border-color: var(--rejected); }
.rbtn.report:hover { background: var(--rejected); border-style: solid; color: var(--paper); }

.review-edit { font-family: var(--mono); font-size: 0.62rem; text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--muted); text-align: center; padding-top: 0.2rem; }
.review-edit:hover { color: var(--ink); }

/* The row's two forms share the right-hand column: the review actions, and
   under them the Re-extract control (drafts only). Two forms because they
   post to different places; one column because they belong to one row. */
.review-side { display: flex; flex-direction: column; gap: 0.35rem; }
/* The machinery's question to the reviewer: one line under the people the
   article added — the sentence, the answers, one button. */
.review-question { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.review-question .question { font-weight: 500; }
.review-question select { font: inherit; font-size: 0.85rem; padding: 0.15rem 0.3rem; }
.review-reextract { display: flex; flex-direction: column; gap: 0.35rem;
  margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px dashed var(--rule); }
.rbtn.reextract { border-style: dashed; color: var(--muted); }
.rbtn.reextract:hover:not(:disabled) { background: var(--ink); border-style: solid;
  border-color: var(--ink); color: var(--paper); }
.rbtn.reextract.confirm { border-style: solid; color: var(--reported); border-color: var(--reported); }
.rbtn.reextract.confirm:hover { background: var(--reported); border-color: var(--reported); }
.reextract-why, .reextract-warn { font-family: var(--mono); font-size: 0.6rem;
  line-height: 1.5; color: var(--muted); }
.reextract-warn { color: var(--reported); }
/* The row while its re-extraction runs: the controls are withheld and this
   is what stands in the button's place. Set apart from the buttons so it
   doesn't read as one that is merely disabled. */
.reextract-busy { color: var(--reported); border: 1px dashed var(--reported); border-radius: 2px; }
.rbtn.report.disabled { opacity: 0.32; cursor: default; }
.rbtn.report.disabled:hover { background: transparent; border-style: dashed; color: var(--rejected); }

/* What Publish will drag live with the row, and which chips point nowhere.
   Rendered inside the entry body, directly under the byline — the actions
   column is too narrow for a list of names. Review queue only. */
.linked-notes { margin-top: 0.4rem; }
.linked-note { margin: 0; font-family: var(--mono); font-size: 0.63rem;
  line-height: 1.9; color: var(--muted); }
.linked-note.dead { color: var(--rejected); }

/* Flip chips: what Publish will put live, grouped by the table each record
   publishes from — the group's label says which, in words — and clicking
   flips the draft to the other one. The chip itself is the byline's chip,
   tint included: colour means the organisation's role in the row's money and
   never its page type. Buttons, not links: they change data. */
.chip-flip { display: inline; }
.chip-flip .chip { cursor: pointer; }
.pending-group { display: inline; }
.pending-group + .pending-group::before { content: "·"; margin: 0 0.4rem; color: var(--rule); }
.linked-hint { margin-left: 0.25rem; }
/* A name and the role this article gives it, kept on one line; the sentence
   it was read from is the hint's tooltip. A source link in a Sources cell
   carries the same tooltip for staff: the words that article used, and a
   run's line the same for a quote too long to print in it (core.marks). */
.pending-role { display: inline-block; margin-right: 0.6rem; }
.pending-role .linked-hint[title], .sources a[title], .run-line [title] { cursor: help; border-bottom: 1px dotted var(--rule); }

/* People review: two readings beside what we hold. A reading that changes
   nothing is muted; a row where neither reading changes anything is quieter
   still, so the eye lands on the rows with a decision in them. */
table.people-review td.tick, table.people-review th.tick { width: 3rem; text-align: center; }
table.people-review td.reading.same, table.people-review tr.unchanged td { color: var(--muted); }
table.people-review .applied { color: var(--confirmed); }
table.people-review .linked-hint[title] { cursor: help; }

/* An open report travels with the row it disputes, so nobody has to go looking. */
.report-flags { grid-column: 2 / -1; }
.report-flag { border-left: 2px solid var(--rejected); background: rgba(178,58,46,0.05);
  padding: 0.7rem 0.9rem; margin-top: 0.75rem; }
.report-flag-head { margin: 0 0 0.4rem; font-family: var(--mono); font-size: 0.66rem;
  color: var(--muted); display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
.report-badge { font-weight: 500; color: var(--rejected); text-transform: uppercase;
  letter-spacing: 0.1em; }
.report-flag-head a { border-bottom: 1px solid var(--rule); }
.report-detail { margin: 0 0 0.45rem; font-size: 0.93rem; color: #2C3236; }
/* The reporting email, verbatim. Folded away by default — it is evidence to
   check, not something to read on every pass down the queue. */
.report-email { margin: 0 0 0.5rem; }
.report-email summary { font-family: var(--mono); font-size: 0.63rem; text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--muted); cursor: pointer; }
.report-email summary:hover { color: var(--ink); }
.report-email pre { margin: 0.5rem 0 0; padding: 0.7rem 0.9rem; background: var(--card);
  border: 1px solid var(--rule); font-family: var(--mono); font-size: 0.72rem;
  line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 22rem;
  overflow-y: auto; }

.report-audit { margin: 0; font-family: var(--mono); font-size: 0.63rem; color: var(--muted); }
.report-audit a { border-bottom: 1px solid var(--rule); }
.report-audit a:hover { color: var(--ink); border-color: var(--ink); }

/* Report form */
.report-form { max-width: 640px; margin-top: 1rem; }
/* The pasted email keeps its own line breaks and column alignment. */
.report-form textarea[name=email_text] { font-family: var(--mono); font-size: 0.8rem;
  line-height: 1.5; white-space: pre; overflow-wrap: normal; overflow-x: auto; }
.field.has-error input, .field.has-error textarea, .field.has-error select { border-color: var(--rejected); }
.field-error, .form-error { font-family: var(--mono); font-size: 0.7rem; color: var(--rejected);
  margin: 0.35rem 0 0; }
.form-error { border-left: 2px solid var(--rejected); background: rgba(178,58,46,0.06);
  padding: 0.7rem 0.9rem; margin: 1.25rem 0; }
.form-error ul { margin: 0; padding-left: 1rem; }
.form-actions { display: flex; gap: 0.75rem; align-items: center; }
.btn.danger { background: var(--rejected); }
.btn.danger:hover { background: #8F2C22; }
.muted { color: var(--muted); }
/* A form that sits in a line of text or a table cell. */
.inline { display: inline; }
/* A link in running prose, underlined with the rule colour. */
a.ruled { border-bottom: 1px solid var(--rule); }
table.corrections { margin-top: 2rem; }
.tip-form { margin-top: 2rem; }
.thanks { padding: 5rem 0; }
.thanks p:last-child { margin-top: 2rem; }

/* ============================================================================
   OPERATIONS DASHBOARD — staff only.
   Panels are the whole hit area, not a card with a link in it: the question a
   panel asks and the page that answers it are the same object. Figures use the
   display face at data sizes so spend, intake and freshness read at a glance
   from across the desk.
   ========================================================================= */
.panels { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1px; background: var(--rule); border: 1px solid var(--rule); margin: 1.5rem 0 2.5rem; }
.panels.two { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

.panel { display: flex; flex-direction: column; gap: 0.35rem; background: var(--paper);
  padding: 1.1rem 1.15rem 1rem; color: inherit; }
a.panel:hover { background: var(--card); }
a.panel:hover .panel-go { color: var(--confirmed); }

.panel-label { font-family: var(--mono); font-size: 0.62rem; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--muted); }
.panel-figure { font-family: var(--display); font-weight: 800; letter-spacing: -0.03em;
  font-size: 2.1rem; line-height: 1.1; font-variant-numeric: tabular-nums; }
.panel-figure.small { font-size: 1.3rem; letter-spacing: -0.02em; }
.panel-sub { font-family: var(--mono); font-size: 0.66rem; color: var(--muted); line-height: 1.6; }
.panel-warn { font-family: var(--mono); font-size: 0.64rem; color: var(--reported);
  border-left: 2px solid var(--reported); padding: 0.3rem 0.5rem; margin-top: 0.3rem; }
.panel-go { margin-top: auto; padding-top: 0.7rem; font-family: var(--mono); font-size: 0.66rem;
  text-transform: uppercase; letter-spacing: 0.09em; color: var(--ink); }
.panel-note { font-family: var(--mono); font-size: 0.66rem; color: var(--muted); margin-top: 0.75rem; }

.panel-facts { display: grid; gap: 0.15rem 1rem; grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
  margin: 0.55rem 0 0; }
.panel-facts dt { font-family: var(--mono); font-size: 0.58rem; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted); }
.panel-facts dd { margin: 0; font-family: var(--mono); font-size: 1rem;
  font-variant-numeric: tabular-nums; }
.panel-facts dd.small { font-size: 0.7rem; line-height: 1.5; }
.panel-facts dd.flag, .panel-figure.flag { color: var(--rejected); }
/* A count under its figure, never beside it: "$0.0473 46" reads as one number. */
.panel-facts dd .unit { display: block; color: var(--muted); font-size: 0.62rem; }

/* Seven days of spend. Bars are relative to the busiest day, so the shape says
   "which days were expensive"; the figure inside each bar says how much, to the
   cent, and the tooltip keeps the exact amount. A priced day's bar is never
   shorter than its figure — that floor is set in core.dashboard._daily_spend
   as a share of this height — and overflow is clipped so white text can never
   land on the paper. */
.spark { display: flex; align-items: flex-end; gap: 3px; height: 56px; margin-top: 0.6rem; }
/* A bar stacks bottom-up: on the dashboard that is one figure sitting on the
   base; on the pricing page it is one segment per stage, in pipeline order. */
.spark-bar { flex: 1; min-width: 0; display: flex; flex-direction: column-reverse; align-items: center;
  overflow: hidden; background: var(--confirmed); min-height: 1px; }
.spark-bar.empty { background: var(--rule); height: 1px !important; }
.spark-val { font-family: var(--mono); font-size: 0.52rem; line-height: 1; color: #fff;
  padding-bottom: 3px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.spark-axis { display: flex; justify-content: space-between; font-family: var(--mono);
  font-size: 0.56rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); }

/* The pricing page's spark splits each day by stage. Segments take the bar in
   proportion to cost (flex-grow is the segment's share, set inline), so a
   segment can be a sliver — its figure shows only once the segment is tall
   enough to hold it, which the segment decides for itself as a size container.
   The tooltip carries every figure regardless. Taller than the dashboard's,
   because two figures have to fit where one did. */
.spark.stacked { height: 84px; }
.spark-seg { align-self: stretch; flex-basis: 0; min-height: 0; display: flex;
  flex-direction: column-reverse; align-items: center; container-type: size; }
.spark-seg.triage { background: var(--muted); }
.spark-seg.extract { background: var(--confirmed); }
.spark-seg .spark-val { display: none; }
@container (min-height: 13px) { .spark-seg .spark-val { display: block; } }
.spark-key { display: flex; gap: 0.9rem; margin-top: 0.3rem; font-family: var(--mono);
  font-size: 0.56rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); }
.spark-key .swatch { display: inline-block; width: 8px; height: 8px; margin-right: 0.35rem;
  vertical-align: -1px; }
.spark-key .swatch.triage { background: var(--muted); }
.spark-key .swatch.extract { background: var(--confirmed); }

/* --- The Fetch and Fixups pages' command panels -------------------------- */
/* The panel is the button. Nothing else on the page starts a process, so the
   thing you press is the whole card rather than a control hidden inside it. */
.panels.scripts .panel { padding: 0; }
.panel-hit { display: flex; flex-direction: column; gap: 0.3rem; width: 100%; text-align: left;
  padding: 1.1rem 1.15rem 0.9rem; background: var(--card); border: 0; border-bottom: 1px solid var(--rule);
  color: inherit; font: inherit; cursor: pointer; }
.panel-hit:hover { background: var(--paper); }
.panel-hit:hover .panel-cta { color: var(--confirmed); }
.panel-hit:disabled { opacity: 0.5; cursor: wait; }
.panel-cta { margin-top: 0.5rem; font-family: var(--mono); font-size: 0.68rem;
  text-transform: uppercase; letter-spacing: 0.1em; }
.panel-detail { padding: 0.85rem 1.15rem 1rem; display: flex; flex-direction: column; gap: 0.4rem; }
.panel-blurb { margin: 0; font-size: 0.88rem; color: #2C3236; }
.panel-cmd { display: block; font-family: var(--mono); font-size: 0.65rem; color: var(--muted);
  background: var(--card); border: 1px solid var(--rule); padding: 0.4rem 0.5rem;
  overflow-x: auto; white-space: nowrap; }

/* How much to do in one go is the only thing about a run worth changing, so it
   sits in the open under the blurb — above the command line it rewrites. */
.panel-limit { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap;
  margin-top: 0.2rem; }
.panel-limit-name { font-family: var(--mono); font-size: 0.58rem; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted); }
.panel-limit input { width: 4.5rem; font-family: var(--mono); font-size: 0.85rem;
  font-variant-numeric: tabular-nums; color: var(--ink); background: var(--paper);
  border: 1px solid var(--rule); padding: 0.2rem 0.35rem; }
.panel-limit-what { font-family: var(--mono); font-size: 0.6rem; color: var(--muted); }
/* Where a fixup that walks the archive in chunks has reached, so the page
   says it rather than the person keeping the number. */
.panel-place { margin: 0.3rem 0 0; font-family: var(--mono); font-size: 0.6rem;
  color: var(--muted); }
/* A fixup with a choice or two shows them as controls, not a box to type in:
   a checkbox per optional word, a dropdown where the words exclude each other. */
.panel-option.check { display: flex; align-items: center; gap: 0.4rem; margin-top: 0.3rem;
  font-family: var(--mono); font-size: 0.68rem; color: var(--ink); cursor: pointer; }
.panel-option.check input { margin: 0; }
.panel-limit select { font-family: var(--mono); font-size: 0.8rem; color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule); padding: 0.2rem 0.35rem; }

/* --- The model picker ----------------------------------------------------- */
/* One panel per stage; a row per model. The price sits with the name because
   price is the reason most switches happen — hiding it would invite one. */
.panels.models { margin-bottom: 1rem; }
.panel.model-stage { gap: 0.55rem; }
/* A panel used as a plain box of prose and tables, stacked with the next. */
.panel.block { display: block; margin: 1rem 0; }
.panel.block .mention { border-top: 1px solid var(--rule); padding-top: .6rem; margin-top: .6rem; }
.model-option { display: flex; align-items: baseline; gap: 0.55rem; cursor: pointer;
  font-size: 0.85rem; }
.model-option input { accent-color: var(--confirmed); }
.model-option .model-name { flex: 1; }
.model-option .model-price { font-family: var(--mono); font-size: 0.66rem; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
  display: flex; flex-direction: column; align-items: flex-end; }
/* What a price was before the weekly refresh moved it, under what it is now.
   Red because it is the dead figure, not because anything is wrong. */
/* A cost our own table produced rather than the vendor's bill. Muted, not
   warned about: the figure is sound, it is just ours. */
.estimated { font-size: 0.6rem; color: var(--muted); margin-left: 0.3rem;
  text-transform: uppercase; letter-spacing: 0.04em; }
.model-price-was { display: block; font-family: var(--mono); font-size: 0.6rem;
  color: var(--rejected); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* A run panel is headed by the command's name in the figure slot; the last-run
   time sits under it in the label slot, a dateline rather than the headline. */
/* A live run pulls the eye without moving anything: the left edge goes green
   and the marker breathes beside "Running now". Reduced-motion turns the
   animation off globally. */
.panel.run.live { box-shadow: inset 3px 0 0 var(--confirmed); }
.panel.run.live .panel-label::after { content: ""; display: inline-block; width: 7px; height: 7px;
  border-radius: 50%; background: var(--confirmed); margin-left: 0.5rem; vertical-align: 0.15em;
  animation: pulse 1.6s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

.run-state { font-family: var(--mono); font-size: 0.62rem; text-transform: uppercase;
  letter-spacing: 0.09em; }
.run-state.running   { color: var(--confirmed); }
.run-state.finished  { color: var(--confirmed); }
.run-state.failed    { color: var(--rejected); }
.run-state.stopped   { color: var(--reported); }
.run-state.abandoned { color: var(--reported); }
tr.watching td { background: rgba(15,107,92,0.06); }
.tabular-link, .row-form summary { font-family: var(--mono); font-size: 0.66rem; color: var(--muted); white-space: nowrap; }
.tabular-link:hover { color: var(--confirmed); }
/* The one row control that doesn't come back: it reads in the rejected colour
   rather than the confirmed one, in the row and on hover both. */
.tabular-link.danger:hover { color: var(--rejected); }
/* A button styled as one of the row links above: the Fix control on the
   sources page is a POST, so it can't be an anchor. */
button.tabular-link { background: none; border: 0; padding: 0; cursor: pointer; }
.row-fix { display: inline; margin: 0; }
/* Wraps rather than runs off the edge. This column holds up to five controls
   and used to be nowrap inside a width:100% table, which pushed it past the
   right edge of the page — the buttons were rendered and unreachable. */
.row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.7rem; }

/* The switch-on column, second from the left. It sat at the far right among
   four other controls, in a nowrap cell inside a width:100% table — rendered,
   past the edge of the page, and reported as missing. A column of its own on
   the reading side of the table cannot be pushed anywhere. */
.row-primary { white-space: nowrap; }
.row-on { font-family: var(--mono); font-size: 0.66rem; }
tr.just-activated td { background: rgba(15,107,92,0.08); }
tr.activate-failed td { background: rgba(176,58,46,0.07); }

/* A run started from a row, announced at the top of the page as well as in the
   row. One live thing on a table of 136 is not findable by scrolling. */
.run-banner { border: 1px solid var(--confirmed); background: var(--paper);
  padding: 0.8rem 0.9rem; margin: 1.25rem 0; }
.run-banner p { margin: 0 0 0.3rem; font-size: 0.9rem; }
.run-banner .panel-note, .form-actions .panel-note { margin: 0; }
.run-banner a { border-bottom: 1px solid var(--rule); }

/* The one action a row is actually for, when it has one: switch this source on
   and go and read it. Sized like a control rather than a footnote, because
   finding it is the whole job of this page after an import. */
.row-go { font-family: var(--mono); font-size: 0.66rem; white-space: nowrap;
  background: none; border: 1px solid var(--confirmed); color: var(--confirmed);
  padding: 0.2rem 0.45rem; cursor: pointer; }
.row-go:hover { background: var(--confirmed); color: var(--paper); }

/* A poll running against one row, reported in the row's own error cell —
   that column is empty while a source is working, and this is the one moment
   it has something better to say. Monospace so a line of command output
   doesn't reflow the column as it updates. */
.source-status { max-width: 260px; }
.source-status.run-live, .source-status.run-done {
  font-family: var(--mono); font-size: 0.66rem; color: var(--confirmed);
}
.source-status.run-live::before {
  content: "●"; margin-right: 0.35rem; animation: source-pulse 1.4s ease-in-out infinite;
}
@keyframes source-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) {
  .source-status.run-live::before { animation: none; }
}

/* --- Add a source (sources page) --------------------------------------- */
.add-source { margin: 1.5rem 0 0.5rem; border: 1px solid var(--rule); background: var(--paper); }
.add-source summary { cursor: pointer; padding: 0.7rem 0.9rem; font-family: var(--mono);
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); }
.add-source summary:hover, .add-source[open] summary { color: var(--ink); }
.add-source .source-form { padding: 0.25rem 0.9rem 1rem; }
.source-form-grid { display: grid; gap: 0.75rem 1rem;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.source-form-grid .field.wide { grid-column: 1 / -1; }
.source-form-grid input:not([type=checkbox]), .source-form-grid select { width: 100%; }
.source-edit { max-width: 820px; margin-top: 1.5rem; }
.source-form-grid .helptext { font-size: 0.72rem; }
/* The profile's staff panel: a standard cheque is a term of a program that
   takes equity, so its box shows while Takes equity reads Yes, or when a
   cheque is already on file (plans/profile-edit-panel.md, rule 3). */
.investor-edit .lsec:not(:has(select[name="takes_equity"] option[value="true"]:checked))
  .field:has(input[name="standard_cheque_aud"]:not([value])) { display: none; }

/* The Models page's prompt disclosures: the summary reads as a sentence, the
   template itself opens beneath it in the calls' own plain text. */
.prompt-block { margin: 0 0 0.6rem; border: 1px solid var(--rule); border-radius: 3px;
  background: var(--card); }
.prompt-block summary { padding: 0.6rem 0.75rem; cursor: pointer; font-size: 0.8rem;
  line-height: 1.5; }
.prompt-block summary strong { margin-right: 0.4rem; }
.prompt-note { color: var(--muted); }
.prompt-text { margin: 0; padding: 0.75rem; border-top: 1px solid var(--rule);
  font-family: var(--mono); font-size: 0.7rem; line-height: 1.55; white-space: pre-wrap;
  overflow-wrap: anywhere; max-height: 70vh; overflow-y: auto; }

/* The baseline misses page: one disclosure per column of failures, the
   critical columns accented the way the score table accents their cells. */
.miss-group { margin: 0 0 0.6rem; border: 1px solid var(--rule); border-radius: 3px;
  background: var(--card); }
.miss-group summary { padding: 0.6rem 0.75rem; cursor: pointer; font-size: 0.8rem;
  line-height: 1.5; }
.miss-group summary strong { margin-right: 0.4rem; }
.miss-group.is-critical { border-left: 3px solid rgba(15,107,92,0.55); }
.miss-critical { margin-left: 0.4rem; font-family: var(--mono); font-size: 0.63rem;
  text-transform: uppercase; letter-spacing: 0.06em; color: #0F6B5C; }
.miss-entries { padding: 0 0.9rem 0.7rem 2rem; border-top: 1px solid var(--rule);
  padding-top: 0.6rem; }
.miss-entries > li { margin: 0.35rem 0; }
.miss-entries ul { margin: 0.1rem 0 0.3rem; padding-left: 1.1rem; list-style: none; }

/* Wide tables scroll inside their own box rather than the page. */
.scroll-x { overflow-x: auto; }
table.data.calls { min-width: 1000px; }
/* A date is one thing and breaking "25 Aug 12:04" over two lines makes the
   column unreadable. The width above is meant to hold it; this is what stops a
   narrower viewport wrapping it anyway, since .scroll-x can scroll instead. */
table.data.calls td:first-child, table.data.calls th:first-child { white-space: nowrap; }
table.data tfoot td { border-top: 1px solid var(--ink); border-bottom: 0; font-family: var(--mono);
  font-size: 0.72rem; padding-top: 0.6rem; }
table.data td.article { max-width: 30ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.data td.article a:hover { color: var(--confirmed); }
.unpriced { color: var(--reported); border-bottom: 1px dotted var(--reported); cursor: help; }

/* --- Merge Records --------------------------------------------------------- */
.merge { max-width: 52rem; }
.merge .kinds { display: flex; gap: .5rem; flex-wrap: wrap; margin: 0 0 1.2rem; }
.merge .kinds button { padding: .45rem .9rem; border: 1px solid var(--rule); background: var(--card);
  border-radius: 4px; cursor: pointer; font: inherit; }
.merge .kinds button[aria-pressed="true"] { background: var(--ink); color: var(--card); border-color: var(--ink); }
.merge .picks { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; align-items: start; }
.merge .pick label { display: block; font-size: .85em; color: var(--muted); margin-bottom: .25rem; }
.merge .pick input[type=text] { width: 100%; box-sizing: border-box; padding: .5rem .6rem; font: inherit; }
.merge .card { border: 1px solid var(--rule); border-radius: 6px; padding: .8rem 1rem; margin-top: .6rem; background: var(--card); }
.merge .card .meta { display: block; margin-top: .2rem; }
.merge .result { margin-top: 1.4rem; }
.merge .result h2 { margin: 0 0 .4rem; font-size: 1.1em; }
.merge .words { padding: .8rem 1rem; border-left: 3px solid var(--ink); background: var(--paper); margin: .6rem 0 1rem; }
.merge .words.problem { border-left-color: var(--rejected); }
.merge table.fields { width: 100%; border-collapse: collapse; }
.merge table.fields th { text-align: left; font-weight: normal; color: var(--muted); width: 11rem; padding: .35rem .5rem .35rem 0; vertical-align: top; font-size: .9em; }
.merge table.fields td { padding: .35rem 0; vertical-align: top; border-top: 1px solid var(--rule); }
.merge table.fields .choice { display: inline-block; margin: 0 1.2rem .2rem 0; }
.merge table.fields .choice input { margin-right: .35rem; }
.merge .foot { color: var(--muted); font-size: .9em; margin-top: .6rem; }
.merge .actions { margin: 1rem 0 0; display: flex; gap: 1rem; align-items: center; }
.merge .actions button[disabled] { opacity: .45; cursor: default; }
.merge .also { margin-top: .8rem; }

/* --- Type-ahead ---------------------------------------------------------- */
/* The list of matches under a picking field (static/js/typeahead.js). */
.typeahead-wrap { position: relative; }
/* At least the field's width, and as wide as its longest match up to a
   cap: a picking box on a fixup panel is a few characters wide, and a
   source's name with its site URL under it needs room to be read. */
.typeahead-list { position: absolute; left: 0; top: 100%; z-index: 20; margin: 0; padding: 0;
  min-width: 100%; width: max-content; max-width: 30rem;
  list-style: none; background: var(--card); border: 1px solid var(--rule);
  border-radius: 4px; box-shadow: 0 4px 12px rgba(0,0,0,.08); max-height: 16rem; overflow-y: auto; }
.typeahead-list li { padding: .4rem .6rem; cursor: pointer; }
.typeahead-list li[aria-selected="true"], .typeahead-list li:hover { background: var(--paper); }
.typeahead-list .line { display: block; font-size: .85em; color: var(--muted); }
.typeahead-list li, .typeahead-list .line { white-space: nowrap; }
/* A row that is a link (a field that picks a page, the masthead search): the
   link carries the row's padding, so the whole row is the target. */
.typeahead-list li.link { padding: 0; }
.typeahead-list li.link a { display: block; padding: .4rem .6rem; }
/* A box that picks a record by name holds a name, not an id. */
.panel-args input[data-typeahead] { width: 14rem; }

/* --- Filters, pagination, footer ---------------------------------------- */
.filters { display: flex; gap: 0.5rem; flex-wrap: wrap; margin: 1.25rem 0; }
/* The Merge duplicates tab's form that starts the sweep: its box and button
   on one line (plans/duplicate-organisations.md, stage 16). */
.sweep-form { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin: 0.6rem 0 1.25rem; }
.sweep-form .panel-option.check { margin-top: 0; }
.filters a { font-family: var(--mono); font-size: 0.68rem; text-transform: uppercase;
  letter-spacing: 0.09em; padding: 0.35rem 0.7rem; border: 1px solid var(--rule);
  border-radius: 2px; color: var(--muted); }
.filters a.active { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.filters .queue-search { margin-left: auto; }
.filters .queue-search input { width: 260px; padding: 0.35rem 0.6rem; border: 1px solid var(--rule);
  border-radius: 2px; font-size: 0.85rem; }

/* Rule introducing the entry list — stands in for the old legend's border,
   held clear of the filters above it. */
.list-rule { border: 0; border-top: 1px solid var(--rule); margin: 1.25rem 0 0; }

/* Colour key, sitting between the filters and that rule. The swatches are the
   feed's own .rail-dot and .chip elements, so all this has to do is undo the
   absolute positioning the rail depends on, give the empty chips a size to be
   seen at, and stop them behaving as though they were clickable.

   Set as its own block rather than a loose line of small print: a key nobody
   notices is a key that isn't doing its job, and at byline weight this read as
   apparatus and got scrolled past. The border and the eucalypt edge carry that
   weight, NOT a fill — the strip has to stay on --paper, because an untinted
   .chip is --card and would vanish against a --card panel. A swatch that only
   reads on one background is worse than a quiet key. */
/* Closed, the key is one line of the page — a word and a marker, no box, no
   band. It costs the feed nothing to carry and the reader nothing to skip,
   which is the right price for something you read once and then know. */
.key { margin: 0 0 0.6rem; font-family: var(--mono); font-size: 0.7rem;
  color: var(--ink); }
.key > summary { display: inline-flex; align-items: center; gap: 0.4rem;
  cursor: pointer; list-style: none; padding: 0.15rem 0;
  text-transform: uppercase; letter-spacing: 0.12em; font-size: 0.62rem;
  color: var(--muted); }
.key > summary::-webkit-details-marker { display: none; }
.key > summary::before { content: "▸"; font-size: 0.6rem; line-height: 1;
  transition: transform 0.12s ease; }
.key[open] > summary::before { transform: rotate(90deg); }
.key > summary:hover, .key[open] > summary { color: var(--ink); }
/* Open, it splits where the feed splits: the chips of the byline on one line,
   the marker on the rail on the other. One line each, so neither has to be
   scanned past to reach the other. */
.key-rows { margin-top: 0.35rem; padding: 0.55rem 0.85rem; background: var(--paper);
  border: 1px solid var(--rule); border-left: 2px solid var(--confirmed);
  border-radius: 2px; }
.key-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 1.35rem;
  margin: 0; }
.key-row + .key-row { margin-top: 0.45rem; padding-top: 0.45rem;
  border-top: 1px solid var(--rule); }
.key-item { display: inline-flex; align-items: center; gap: 0.45rem; }
.key .rail-dot { position: static; transform: none; box-shadow: none; flex: none; }
/* Wide enough that a tint reads as a colour, not as a tinge on a border. */
.key .chip { display: inline-block; width: 28px; height: 16px; padding: 0;
  flex: none; pointer-events: none; }

/* The one pager (_pager.html): back, the pages around this one with the first
   and last, next; under it the line saying what is shown, with the size
   select. Both centred under the table. */
.pager { display: flex; gap: 0.55rem 0.9rem; justify-content: center; flex-wrap: wrap;
  padding: 1.5rem 0 0.5rem; font-family: var(--mono); font-size: 0.75rem; }
.pager a:hover { color: var(--confirmed); }
.pager .current { font-weight: 700; padding: 0 0.3rem; border-bottom: 2px solid var(--confirmed); }
.pager .dim { color: var(--muted); }
.pager-line { display: flex; justify-content: center; align-items: center; gap: 0.6rem;
  margin: 0; padding: 0.5rem 0 1.5rem; font-family: var(--mono); font-size: 0.72rem;
  color: var(--muted); }
.pager-line label { display: inline-flex; align-items: center; gap: 0.4rem; }
.pager-line select { width: auto; font-family: var(--mono); font-size: 0.72rem;
  color: var(--ink); padding: 0.2rem 0.35rem; }
.pager-line .btn { padding: 0.3rem 0.7rem; }

.notice { background: rgba(15,107,92,0.08); border-left: 2px solid var(--confirmed);
  padding: 0.8rem 1rem; margin: 1.25rem 0; font-size: 0.93rem; }

footer.site { border-top: 1px solid var(--rule); margin-top: 4rem; padding: 2rem 0 3rem;
  font-family: var(--mono); font-size: 0.72rem; color: var(--muted); }
footer.site a { border-bottom: 1px solid var(--rule); }
footer.site a:hover { color: var(--ink); border-color: var(--ink); }
.footer-cols { display: flex; gap: 2.5rem; flex-wrap: wrap; margin-bottom: 1.5rem; }

.empty { padding: 3rem 0; color: var(--muted); font-size: 0.97rem; }
.empty strong { display: block; font-family: var(--display); font-size: 1.1rem;
  color: var(--ink); margin-bottom: 0.35rem; }

@media (max-width: 700px) {
  .panels { grid-template-columns: 1fr; }
  .panel-figure { font-size: 1.7rem; }
  .entry { grid-template-columns: 1fr; gap: 0.5rem; }
  .review-entry { grid-template-columns: 1fr; }
  .review-actions { flex-direction: row; flex-wrap: wrap; align-items: center; }
  .rbtn { flex: 1 1 auto; }
  .rail { min-height: 44px; }
  .profile-head { grid-template-columns: 1fr; }
  .tabbar { gap: 0.5rem; }
  .tabbar .tab { padding: 0; gap: 0.1rem; }
  /* The masthead's padding of top and bottom alone replaces .wrap's gutter,
     which on a desktop leaves the row overhanging the page by that gutter
     at each side; on a phone it would sit flush against the screen's edge,
     so here the sides get the gutter back. */
  .masthead-inner { padding: 1rem 1.25rem 0.9rem; gap: 0.2rem; }
  /* The tagline small beside the wordmark, a rem off it, so the two and
     the nav under them take as little of the screen as they can. */
  .tagline { font-size: 0.5rem; margin-left: 1rem; }
  /* The nav at phone width: one line, a menu button at the left and the
     search box filling the rest. The links are behind the button
     (static/js/masthead.js opens them), and open they drop under the line
     as a column, the same anchors the desktop shows beside the search. */
  nav.primary { margin-left: 0; width: 100%; flex-wrap: wrap; align-items: center;
    gap: 0.6rem; font-size: 0.68rem; }
  .menu-toggle { display: inline-flex; align-items: center; justify-content: center;
    flex: none; width: 2.4rem; height: 2.4rem; padding: 0; background: none;
    border: 1px solid var(--rule); border-radius: 10px; cursor: pointer; }
  .menu-toggle[aria-expanded="true"] { border-color: var(--ink); }
  .menu-bars { display: block; width: 1.1rem; height: 2px; background: var(--ink);
    box-shadow: 0 -6px 0 var(--ink), 0 6px 0 var(--ink); }
  .masthead-search { flex: 1; min-width: 0; }
  .masthead-search input[type=text] { flex: 1; width: auto; min-width: 0; }
  /* With scripting the box sits inside the wrap typeahead.js puts round it:
     the wrap takes the box's share of the line and the box fills the wrap.
     The list is as wide as the box and its words wrap, since a phone has no
     room for the 30rem a long match is given at desktop width. */
  .masthead-search .typeahead-wrap { flex: 1; min-width: 0; }
  .masthead-search .typeahead-wrap input[type=text] { width: 100%; }
  .masthead-search .typeahead-list { width: 100%; max-width: 100%; }
  .masthead-search .typeahead-list li,
  .masthead-search .typeahead-list .line { white-space: normal; }
  .primary-links { display: none; flex-basis: 100%; flex-direction: column;
    gap: 0.8rem; padding: 0.4rem 0 0.3rem; }
  .primary-links.open { display: flex; }
  /* A heading stays on one line with its sort arrow, so a column is never
     narrower than "Deals ▼": on a phone a count column's least width is
     less than that, and the arrow was dropping to a second line. */
  table.data th { white-space: nowrap; }
  /* A column a phone does without. The class sits on the heading beside its
     kind and on every cell under it; the table keeps the rest. */
  table.data .desktop { display: none; }
  .phone { display: inline; }
  /* A filter row at phone width: the search box fills the line, and the
     button that opens the folded checks sits beside it. */
  form[data-live-filter] input[type=search] { flex: 1; width: auto; min-width: 0; }
  /* A select beside it is as wide as its longest option and no wider, so
     the box gets the rest of the line. */
  .filter-row select { flex: none; width: auto; max-width: none; }
  /* A group that narrows a column the phone's table does not show has no
     business on a phone: the rounds table drops its stage column here, so
     the Stages button goes with it. */
  .checks.desktop { display: none; }
  /* In the dropdown a row is a thumb's target rather than a pointer's:
     taller, wider, at reading size, with a box big enough to hit. Only the
     sizes are here; what a dropdown is lives with the other dropdown rules,
     because it is one at every width. */
  /* A phone's dropdown sits in the flow and fills the line, as it always
     has: there is only the one column, the words sit in a 10rem block so
     the boxes are at one fixed distance from the edge, and the page itself
     scrolls rather than a list inside it. */
  .checks { display: block; flex-basis: 100%; position: static; }
  .word-checks.dropdown { position: static; width: auto; max-width: none;
    max-height: none; overflow: visible; box-shadow: none; }
  .word-checks.dropdown .word-check { min-height: 2.75rem; padding: 0 0.9rem; font-size: 1rem;
    gap: 0; }
  .word-checks.dropdown .word-check > span { flex: 0 0 10rem; }
  .word-checks.dropdown .word-check input[type=checkbox] { width: 1.25rem; height: 1.25rem; }
  /* A figure the article gave in another currency carries our conversion
     beside it; at phone width the conversion takes a second line rather
     than widening the column. */
  table.data .twin { display: block; }
  /* A date column is 6rem on a phone: the longest date the formatter
     writes, e.g. "28 Aug 2026", is 88px in the table's face against 102px,
     so it stays on one line; a phrase the article gave instead wraps. */
  table.data th.date { min-width: 6rem; }
  table.data td.date { max-width: 6rem; }
  /* A name column keeps 14ch on a phone, 85px in the heading's type: the
     desktop's 10rem would be nearly half a phone's table. */
  table.data th.name { min-width: 14ch; }
  /* A count column is as wide as its heading and no wider, so the slack a
     phone has goes to the words beside it rather than to a column of one
     digit. */
  table.data th.count { width: 5ch; }
  /* The portfolio's First invested column holds a date and a stage, e.g.
     "1 Jan 2025, Seed", so it gets more than a date column's 6rem. */
  table.data th.first { min-width: 8rem; }
  /* A button in a table cell keeps its word on one line, small: the cell's
     rule that lets a long word break anywhere would otherwise stack the
     button's letters when the column is squeezed. */
  table.data td .btn { white-space: nowrap; font-size: 0.5rem; }
  /* The source column holds one arrow: 1rem, headed "Src". */
  table.data th.src { min-width: 1rem; }
  table.data td.src { max-width: 1rem; }
  /* The amount column is as wide as its widest figure and no wider: the
     conversion has its own line here, so the 23ch reserved on a desktop for
     the pair on one line would be spare, and the name column takes it. */
  table.data th.money, table.data td.money { width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* --- Extraction baseline: the label editor ------------------------------- */
.baseline-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
  gap: var(--gap); align-items: start; }
@media (max-width: 900px) { .baseline-grid { grid-template-columns: 1fr; } }
.article-pane { position: sticky; top: 1rem; }
.article-body { white-space: pre-wrap; max-height: 78vh; overflow-y: auto;
  background: var(--card); border: 1px solid var(--rule); padding: 1rem;
  font-size: 0.85rem; line-height: 1.55; }
.label-row { position: relative; border: 1px solid var(--rule); background: var(--card);
  padding: 0.6rem 0.75rem 0.75rem; margin: 0 0 0.6rem; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 0.55rem 0.9rem; }
.label-row .field { min-width: 0; }
.label-row .field.wide { grid-column: 1 / -1; }
.label-row .field .field-name { display: block; font-family: var(--mono);
  font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--muted); margin-bottom: 0.15rem; }
.label-row .field input[type="text"], .label-row .field select, .label-row .field textarea {
  display: block; width: 100%; font-family: var(--body); font-size: 0.85rem;
  border: 1px solid var(--rule); background: var(--paper); padding: 0.25rem 0.4rem; }
.disagree { display: block; margin-top: 0.2rem; font-family: var(--mono);
  font-size: 0.68rem; color: var(--rejected); }
.disagree a { color: var(--rejected); text-decoration: underline; }
.section-note { margin: 0 0 0.5rem; }
.legend { border-left: 3px solid var(--rule); padding-left: 0.75rem; }
.legend .disagree { position: static; }
.legend .check { display: inline; }
.label-row .remove-row { position: absolute; top: 0.3rem; right: 0.3rem;
  border: none; background: none; color: var(--muted); cursor: pointer; font-size: 0.9rem; }
.add-row { font-family: var(--mono); font-size: 0.62rem; text-transform: uppercase;
  border: 1px solid var(--rule); background: var(--card); cursor: pointer;
  padding: 0.15rem 0.5rem; vertical-align: middle; }
.label-actions { display: flex; gap: 1rem; align-items: center; margin-top: 1rem; }
.badge { display: inline-block; font-family: var(--mono); font-size: 0.68rem;
  padding: 0.1rem 0.5rem; border: 1px solid var(--rule); border-radius: 3px; }
.badge-investee { background: var(--company-tint); border-color: #A9AEE0; }
.badge-investor { background: var(--investor-tint); border-color: #9CCF9C; }
.badge-raised { background: var(--raised-tint); border-color: #E0C26A; }
.badge-exec { background: var(--person-tint); border-color: #E8C9A0; }
/* A mention row — recorded for analysis, never staged as a round. */
.badge-mention { background: var(--paper); border-style: dashed; color: var(--muted); }
/* An organisation's chip is a button: click cycles the hand-set role. */
button.badge { cursor: pointer; font: inherit; font-family: var(--mono);
  font-size: 0.68rem; line-height: inherit; color: inherit; background: var(--paper); }
button.badge-investee { background: var(--company-tint); }
button.badge-investor { background: var(--investor-tint); }
button.badge-raised { background: var(--raised-tint); }
.badge-why { display: block; margin-top: 0.15rem; font-family: var(--mono); font-size: 0.62rem;
  color: var(--muted); }
.check { display: block; margin-top: 0.2rem; font-family: var(--mono); font-size: 0.68rem;
  color: var(--reported); }

/* --- The label editor, as cards ------------------------------------------ */
/* A section is a compact list, one line per row, that opens to the row's
   fields; only the rows being worked on are open. */
.lsec { margin: 0 0 1.4rem; }
.lsec h2 { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.3rem; }
.lsec-count { font-family: var(--mono); font-size: 0.68rem; color: var(--muted);
  border: 1px solid var(--rule); border-radius: 999px; padding: 0 0.5rem; }
.lsec-help { font-size: 0.8rem; color: var(--muted); margin: 0 0 0.5rem; }
.lsec-rows:empty::after { content: "nothing here"; display: block; font-family: var(--mono);
  font-size: 0.68rem; color: var(--muted); padding: 0.3rem 0; }
.card { border: 1px solid var(--rule); background: var(--card); margin: 0 0 0.35rem; }
.card > summary { cursor: pointer; padding: 0.45rem 0.75rem; font-size: 0.88rem;
  list-style: none; display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.card > summary::-webkit-details-marker { display: none; }
.card > summary::before { content: "▸"; color: var(--muted); font-size: 0.7rem; }
.card[open] > summary::before { content: "▾"; }
.card[open] > summary { border-bottom: 1px solid var(--rule); }
.sum:empty { display: none; }
.sum:not(:empty) ~ .sum:not(:empty)::before { content: "· "; color: var(--muted); }
.sum-blank { display: none; color: var(--muted); font-style: italic; }
.card > summary:not(:has(.sum:not(:empty))) .sum-blank { display: inline; }
.card-badge { flex: none; }
.card-body { position: relative; padding: 0.6rem 0.75rem 0.75rem; }
.card-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.55rem 0.9rem; }
.top-fields { border: 1px solid var(--rule); background: var(--card); padding: 0.6rem 0.75rem; }
.lf { min-width: 0; }
.lf.wide { grid-column: 1 / -1; }
.lf-name { display: block; font-size: 0.72rem; color: var(--muted); margin-bottom: 0.15rem; }
.lf-name[title], .field label[title] { cursor: help; border-bottom: 1px dotted var(--rule); width: max-content; }
.lf input[type="text"], .lf select, .lf textarea { display: block; width: 100%;
  font-family: var(--body); font-size: 0.85rem; border: 1px solid var(--rule);
  background: var(--paper); padding: 0.25rem 0.4rem; }
.lf-badge { margin-bottom: 0.6rem; }
.card-body .remove-row { position: absolute; top: 0.45rem; right: 0.6rem; border: none;
  background: none; color: var(--muted); cursor: pointer; font-family: var(--mono);
  font-size: 0.62rem; text-transform: uppercase; }
.card-body .remove-row:hover { color: var(--rejected); }
.more { margin-top: 0.6rem; }
.more > summary { cursor: pointer; font-family: var(--mono); font-size: 0.62rem;
  text-transform: uppercase; color: var(--muted); }
.more[open] > summary { margin-bottom: 0.5rem; }
/* A round's card is grouped: the company, the stage and amount, the date,
   then its investors as cards of their own. */
.card-group { margin: 0 0 0.7rem; }
.card-group:last-child { margin-bottom: 0; }
.group-name { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0.3rem;
  font-family: var(--mono); font-size: 0.62rem; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--muted); font-weight: normal; }
.lsec-rows.nested .card { background: var(--paper); }
.lf-line { display: block; margin-top: 0.2rem; font-family: var(--mono); font-size: 0.66rem;
  color: var(--muted); }
.lf-line a { color: var(--muted); text-decoration: underline; }
.entry-edit { font-family: var(--mono); font-size: 0.62rem; text-transform: uppercase;
  color: var(--muted); border: 1px solid var(--rule); padding: 0.05rem 0.4rem;
  margin-left: 0.3rem; text-decoration: none; }
.entry-edit:hover { color: var(--ink); }
fieldset.readonly { border: none; padding: 0; margin: 0; min-width: 0; }
.rbtn.edit { display: inline-block; text-decoration: none; }
.rbtn.edit:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }
fieldset.readonly .lsec { opacity: 0.55; }
fieldset.readonly .add-row, fieldset.readonly .remove-row { display: none; }
/* Evidence: the pane marks what the fields cite; a selection waits for the
   next evidence field clicked. */
.article-body mark.ev { background: #FFF3B0; color: inherit; padding: 0; }
.article-body mark.ev.model { background: none; border-bottom: 2px dotted var(--rejected); }
.article-body mark.ev.current { background: #FFD34D; }
.has-span textarea[name$="quote"] { outline: 2px dashed var(--reported); }
.money-words { color: var(--ink); }

/* Coverage by Company (Luke, 2026-09-10): the action sits at the end of the row and its
   button stays on one line; a figure takes the room a figure needs, not a round's twin
   conversion; a list of names wraps between names, never inside one. */
.coverage-companies th.money, .coverage-companies td.money { width: 7ch; }
.coverage-companies th.text { min-width: 10rem; }
.coverage-companies td.text { overflow-wrap: normal; }
td.search-cell { white-space: nowrap; }
.search-cell form { display: inline; }
/* A verdict's form on a gap row sits behind a closed line, so the row is the
   row it was until the line is opened (plans/profile-gaps-and-sources.md). */
.search-cell .row-form { display: block; margin-top: 0.3rem; white-space: normal; }
.row-form summary { cursor: pointer; }
.search-cell .row-form form { display: block; margin-top: 0.3rem; }
/* The badge a record's row carries for its gap, staff only: a line under the
   record with the same controls as the gap's row on Gap Searches. */
.gap-badge { display: block; margin-top: 0.25rem; }
.gap-badge .search-cell { white-space: normal; }
/* A listing an editor removed stays on the staff's table, struck through,
   so its Undo has somewhere to be. */
tr.removed td:not(.search-cell) { text-decoration: line-through; color: var(--muted); }

/* A run's output under the row that started it (static/js/run_panel.js): a bounded
   panel, the newest line kept in view. */
.run-row td, .run-row > div { padding: 0 0 1rem 0; background: var(--card); }
.run-panel { border-left: 3px solid var(--confirmed); padding: 0.6rem 1rem 0.4rem 1rem; }
.run-panel.is-over { border-left-color: var(--rule); }
.run-panel-head { display: flex; gap: 1rem; align-items: baseline; margin-bottom: 0.4rem;
  font-family: var(--mono); font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.08em; }
.run-panel-title { color: var(--ink); font-weight: 600; }
.run-panel-state { color: var(--muted); }
.run-panel-stop, .run-panel-close { margin-left: auto; color: var(--muted); text-decoration: none; }
.run-panel-stop:hover, .run-panel-close:hover { color: var(--confirmed); }
.run-panel-lines { max-height: 16rem; overflow-y: auto; font-size: 0.88rem; line-height: 1.45; }
.run-line { margin: 0; padding: 0.12rem 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.run-line a { color: var(--confirmed); }
/* Under a panel on the Fetch and Fixups pages the run spans the grid, under the
   row of cards that holds its panel, and the cards after it close up behind it;
   what the run wrote sits under its lines (plans/runs-open-under-their-panel.md). */
.panels.scripts { grid-auto-flow: dense; }
.panels > .run-row { grid-column: 1 / -1; }
.run-panel-results { margin-top: 0.6rem; }
