/*
 * simple.css — the simple surface. Tokens only; not one colour of its own.
 * @license LQD Research LLC   @author Scott Martin
 *
 * Bigger type, more space, fewer things. The reduction is in the PRESENTATION
 * and never in the engine — every control here reaches the same plans the expert
 * surface does, which is why "show me the SQL" can always be one click away
 * rather than a feature that had to be added back.
 */
.s-top {
  display: flex; align-items: center; gap: var(--space-5);
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--line); background: var(--surface-raised);
}
.s-brand { font-size: var(--text-lg); color: var(--ink-strong); }
.s-verbs { display: flex; gap: var(--space-2); }
.s-verbs button {
  font-size: var(--text-lg); padding: var(--space-2) var(--space-4);
  border-color: transparent; background: transparent; color: var(--ink-muted);
}
.s-verbs button[aria-current="page"] {
  background: var(--accent-quiet); color: var(--accent); border-color: var(--accent-quiet);
}
.s-conn { margin-left: auto; color: var(--ink-faint); font-size: var(--text-xs); }

.s-main { max-width: 900px; margin: 0 auto; padding: var(--space-6) var(--space-5); }
.s-row { display: flex; gap: var(--space-3); align-items: center; margin-bottom: var(--space-3); }
.s-row input, .s-row select { font-size: var(--text-lg); padding: var(--space-2) var(--space-3); }
.s-row input { flex: 1; }
.s-hint { color: var(--ink-muted); margin: 0 0 var(--space-4); }

/* Records read as CARDS, not as a grid. A person looking for Maria is looking
   for a person, and a row of forty columns is a spreadsheet. */
.s-card {
  background: var(--surface-raised); border: 1px solid var(--line);
  border-radius: var(--radius); padding: var(--space-4); margin-bottom: var(--space-3);
}
.s-card h3 { margin: 0 0 var(--space-3); font-size: var(--text-lg); color: var(--ink-strong); }
.s-fields { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-2) var(--space-5); }
.s-fields dt { color: var(--ink-muted); }
.s-fields dd { margin: 0; color: var(--ink-strong); }
.s-fields dd[data-editable="true"] { cursor: text; border-bottom: 1px dashed var(--line-strong); }
.s-fields dd[data-editable="true"]:hover { background: var(--surface-hover); }
.s-fields dd .empty { color: var(--ink-faint); font-style: italic; }

/* The plan, as a sentence. This is the whole product for this reader. */
.s-plan {
  border: 1px solid var(--accent); border-left-width: 3px;
  background: var(--accent-quiet); border-radius: var(--radius);
  padding: var(--space-4); margin-top: var(--space-4);
}
.s-plan .sentence { font-size: var(--text-lg); color: var(--ink-strong); margin-bottom: var(--space-2); }
.s-plan .caution { color: var(--risk-high); font-weight: var(--weight-medium); margin-bottom: var(--space-3); }
.s-plan .acts { display: flex; gap: var(--space-2); align-items: center; }
.s-plan .acts .spacer { flex: 1; }
.s-sql { margin-top: var(--space-3); }
.s-sql pre {
  background: var(--surface-sunken); border-radius: var(--radius-sm);
  padding: var(--space-3); font-size: var(--text-sm); overflow-x: auto;
  white-space: pre-wrap; word-break: break-word; margin: var(--space-2) 0 0;
}
.s-answer { font-size: var(--text-xl); color: var(--ink-strong); margin: var(--space-4) 0; }

/* ── The naming review ─────────────────────────────────────────────
   A list, not a sentence. Every other plan on this surface is one change and
   the server's sentence says the whole of it; a naming pass is hundreds of
   changes and "412 changes" tells a reviewer the count and nothing they are
   being asked about. The table is what makes it approvable.

   Bounded height with its own scroll, because a review that pushes its own
   buttons off the screen is a review nobody finishes. */
.s-scroll { max-height: 22rem; overflow: auto; border: 1px solid var(--line);
  border-radius: var(--radius); margin-bottom: var(--space-3); }
.s-grid { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.s-grid th { position: sticky; top: 0; background: var(--surface-raised);
  text-align: left; font-weight: var(--weight-medium); color: var(--ink-muted);
  padding: var(--space-2); border-bottom: 1px solid var(--line); }
.s-grid td { padding: var(--space-2); border-bottom: 1px solid var(--line); }
.s-grid tr:last-child td { border-bottom: 0; }
.s-grid .mono { font-family: var(--font-mono); color: var(--ink-muted); }
.s-grid .muted { color: var(--ink-muted); }
/* The wording that would be REPLACED, marked so the eye finds it. A row with
   something in this column is the only kind a reviewer must read carefully. */
.s-grid .was { color: var(--risk-high); }
/* What a column POINTS AT — the relationship sentence somebody wrote, or the
   bare name of the relation. Quieter than the label, because it is context for
   the field rather than a second field. */
.s-fields dt .points-at { color: var(--ink-muted); font-weight: var(--weight-normal);
  margin-left: var(--space-1); }
/* The typed confirmation. Deliberately not styled as a warning banner: the
   point is not to alarm, it is to make the action cost a sentence of attention
   rather than a click. */
.s-plan .confirm { margin-bottom: var(--space-3); }
.s-plan .confirm label { display: block; color: var(--risk-high);
  margin-bottom: var(--space-1); }
.s-plan .confirm input { width: 12rem; }
/* Sign in. Two fields and a button — §3.2's full screen is Phase D, and this is
   the part Phase C's own exit condition needs in order to be reachable. */
.s-signin { display: flex; flex-direction: column; gap: var(--space-2);
  max-width: 20rem; margin-top: var(--space-3); }
.s-signin .caution { margin: 0; }

/* ── Team: the standing rule, your own row, and an empty section ────
   Three classes, added for the Team screen. Tokens only, both themes. */

/* The rule the whole product is shaped by — one person writes a change, a
   different one approves it, and nobody approves their own.

   Deliberately NOT `.s-plan`. That box is bordered in the accent, and
   `design.css` reserves the accent for two meanings: "this is where you are"
   and "this is the action". A statement of how the product works is neither —
   it is standing, not pending — so it is raised and lined rather than accented,
   and it does not compete with the invitation form further down the page for
   the one colour that means "do this". */
.s-principle {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--radius);
  padding: var(--space-4);
  margin-bottom: var(--space-3);
  color: var(--ink);
  max-width: 62ch;   /* a measure a person can read, not the width of a window */
}
.s-principle p { margin: 0 0 var(--space-2); }
.s-principle p:last-child { margin-bottom: 0; color: var(--ink-strong); }

/* Your own row in the member list.

   This one IS the accent, and by the rule rather than around it: `design.css`
   gives the accent to "this is where you are", and among a list of people that
   is precisely what "you" means. It is not `.pill[data-risk]` — that ramp is
   the product's single severity vocabulary, and borrowing it to mark yourself
   would render "you" in the same colour as a low-risk finding. */
.s-you {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--accent-quiet);
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
}

/* A section with nothing in it, saying what that means.

   Left-aligned and given a measure, unlike `.plan-empty`, which centres one
   short line. An empty state here is two or three sentences — what is absent,
   why, and what to do — and centred prose of that length is unreadable. Quiet
   rather than alarming: nothing is wrong, there is simply nothing yet. */
.s-empty {
  color: var(--ink-muted);
  padding: var(--space-3) 0 var(--space-1);
  max-width: 62ch;
}
.s-empty p { margin: 0 0 var(--space-2); }
.s-empty p:last-child { margin-bottom: 0; }

/* ── Change: the five classes the write screen adds ─────────────────
   Tokens only, both themes, and nothing here sets `display` on anything that
   can be hidden — visibility on that screen is the `hidden` attribute, and
   mostly it is the element simply not being in the document. */

/* What has to happen before a change on this screen can run — somebody else
   agreeing to it, a database open for reading only, an account that may look
   and not change. Said BEFORE anything is typed, so it is a standing statement
   rather than a refusal, and it is coloured as the caution band rather than the
   risk one: nothing has gone wrong, and there is something to know. */
.s-notice {
  background: var(--warn-bg);
  border: 1px solid var(--risk-medium);
  border-left-width: 3px;
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
  color: var(--ink-strong);
  max-width: 62ch;   /* a measure a person can read, not the width of a window */
}
.s-notice p { margin: 0 0 var(--space-2); }
.s-notice p:last-child { margin-bottom: 0; }

/* The editor, in the field it replaces. It fills the field's own column so the
   record does not reflow the instant somebody clicks it — a card that jumps
   under the cursor is a card you click the wrong thing in. */
.s-fields dd input { width: 100%; font-size: inherit; }

/* A field whose new value is written down and has NOT happened yet.
   The same `--warn-bg` the expert grid marks a pending cell with, on purpose:
   two surfaces of one product that colour "not yet" differently teach a reader
   that the colour means nothing. The dashed underline of an editable field
   becomes solid, so the state is legible without relying on colour alone. */
.s-fields dd[data-staged="true"] {
  background: var(--warn-bg);
  border-bottom: 1px solid var(--risk-medium);
}

/* Making a record: the same two-column shape as reading one, so a new record
   and an existing one are recognisably the same thing in two states. */
.s-new {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-3) var(--space-5);
  align-items: start;
  margin-bottom: var(--space-4);
}
.s-new label { color: var(--ink-muted); padding-top: var(--space-1); }
.s-new input { width: 100%; }

/* Removing a record is at the bottom of the record, and quiet — §3.7 asks for
   exactly that. It is not `button.danger`: a red button invites the eye, and
   this one should be found by somebody looking for it rather than offered to
   somebody who is not. It turns the risk colour on hover, which is the moment
   it stops being scenery and starts being a thing about to be clicked. */
.s-card .s-remove {
  margin-top: var(--space-4);
  border-color: transparent;
  background: transparent;
  color: var(--ink-muted);
}
.s-card .s-remove:hover:not(:disabled) {
  background: transparent;
  border-color: var(--risk-high);
  color: var(--risk-high);
}

/* ── Reviews: what is waiting for a decision (§3.11) ────────────────
   Four additions and one extension. Tokens only, both themes. */

/* A section heading inside a room.

   The room's own title is the `h1` in the header bar, so a section inside it is
   an `h2` — and an unstyled `h2` renders at the browser's default 1.5em with
   margins nothing else here uses, which is how one room stops looking like the
   rest of the product. The first one loses its top margin so a screen does not
   open with a gap above its own first word. */
.s-heading { font-size: var(--text-lg); font-weight: var(--weight-medium);
  color: var(--ink-strong); margin: var(--space-5) 0 var(--space-3); }
.s-heading:first-child { margin-top: 0; }

/* The composed sentence, inside a card.

   `.sentence` already means one thing in this product — the wording the server
   composed for a change, the same one the reviewer sees, the history shows and
   the email says — and `.s-plan` already styles it. Extending that name into
   the card rather than inventing a second is deliberate: a class whose meaning
   is "this is the sentence" should not have two spellings depending on which
   box it is standing in. Same declaration, same reason. */
.s-card .sentence { font-size: var(--text-lg); color: var(--ink-strong);
  margin-bottom: var(--space-2); }

/* The NOT-YET-ANSWERABLE state.

   Built with a refusal's anatomy — what, why, and what happens instead — and
   deliberately NOT in a refusal's colours. Nothing has gone wrong when a
   server has nobody to review to; a database you are running by yourself has
   no second person in it. Red here would teach a reader that the screen is
   broken on the setup where it is behaving exactly as designed, so it is lined
   and sunken rather than alarmed. The measure is there because this is prose:
   three sentences across the width of a window cannot be read. */
.s-not-yet {
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--radius);
  padding: var(--space-4);
  margin-bottom: var(--space-3);
  color: var(--ink);
  max-width: 62ch;
}
.s-not-yet h4 { margin: 0 0 var(--space-2); font-size: var(--text-ui);
  color: var(--ink-strong); }
/* The server's own sentence. Prose rather than `.refusal .why`'s monospace:
   that one is the engine quoting an engine, and this one is a note written for
   a person to read. */
.s-not-yet .why { color: var(--ink-muted); }
.s-not-yet .what { margin-top: var(--space-2); color: var(--ink); }

/* What just happened, and what has NOT happened yet.

   The one place in this product that uses `--ok`, and it earns it: this is the
   only surface where something a person did came back confirmed. It is not the
   accent — `design.css` gives the accent to "this is where you are" and "this
   is the action", and an outcome is neither; and it is not `.pill[data-risk]`,
   because that ramp is the single severity vocabulary and a confirmation
   rendered in the low-risk green would be claiming a rank rather than
   reporting an event. */
.s-approved {
  background: var(--ok-bg);
  border: 1px solid var(--ok);
  border-left-width: 3px;
  border-radius: var(--radius);
  padding: var(--space-4);
  color: var(--ink);
  max-width: 62ch;
}
.s-approved strong { display: block; color: var(--ink-strong);
  font-size: var(--text-lg); margin-bottom: var(--space-2); }
/* The half that matters most: an approved change has not run. Given the strong
   ink because a reader who stops after the heading has read the wrong half. */
.s-approved .next { margin-top: var(--space-2); color: var(--ink-strong); }

/* The server's own reason for refusing this person the button.

   Quoted rather than boxed. It is not a refusal of anything they attempted —
   nobody clicked — so a `.refusal` would put a red box around the ordinary
   working of the rule the whole product is shaped by. A rule read is not a
   rule enforced against you, and it should not look like one. Full ink, not
   muted: it is the point of the card it sits on. */
.s-because {
  border-left: 2px solid var(--line-strong);
  padding-left: var(--space-3);
  margin-top: var(--space-3);
  color: var(--ink);
  max-width: 62ch;
}

/* ── Structure: the database in words ──────────────────────────────
   One table per disclosure, so the room is a list of what exists and opening
   one is the reader's choice rather than a scroll they did not ask for. The
   disclosure is `<details>`, so the open/closed state is the browser's — there
   is no `display` here for a script to fight with.

   NOTHING on this screen is coloured by the risk ramp. A field that must be
   filled in is not a warning and a hidden field is not a hazard; borrowing the
   risk colours for facts teaches a reader that the ramp means nothing, which is
   the one scale this product cannot afford to spend. The marks are separated by
   weight and by a border instead. */
.s-table > summary { cursor: pointer; padding: var(--space-1) 0; }
.s-table > summary::marker { color: var(--ink-faint); }
/* Inline-flex INSIDE the summary rather than flex ON it: `display: flex` on a
   summary removes the disclosure triangle, and the triangle is the only thing
   telling a reader there is anything under the heading. */
.s-table-head {
  display: inline-flex; align-items: baseline; gap: var(--space-3);
  width: calc(100% - 1.5em);
}
/* An `h3` inside a `<summary>`: it must sit on the same line as the address and
   the count, so the browser's own heading block/margin is cleared here. It is a
   heading for the reader who moves by heading, and a line of text for the one
   who reads it. */
.s-table-name {
  display: inline; margin: 0;
  font-size: var(--text-lg); color: var(--ink-strong); font-weight: var(--weight-medium);
}
/* The record count sits at the far end of the row, where the eye can run down a
   column of them. It arrives after the list renders and replaces a longer
   placeholder, so the row does reflow when it lands; `nowrap` is only the
   promise that "1,204 records" is never broken across two lines. */
.s-count { margin-left: auto; white-space: nowrap; }

/* The sentence somebody wrote about the table. Prose, at reading size — this is
   the thing the screen exists to show, not a caption under a heading. */
.s-said { margin: var(--space-3) 0; font-size: var(--text-lg); color: var(--ink); }
.s-said.s-unsaid { color: var(--ink-faint); font-size: var(--text-md); }

/* A section heading inside one table. Quieter than the table's own name so the
   list still reads as one heading per table. */
.s-part {
  color: var(--ink-muted); font-weight: var(--weight-medium);
  margin: var(--space-4) 0 var(--space-2);
}

/* A field's own description, and the note under a type this screen was not
   taught. Both are a second line under the thing they are about. */
.s-field-said { display: block; color: var(--ink-faint); font-size: var(--text-xs); }
/* A type shown by its own name because there is no word for it here. Muted
   rather than alarmed: it is a gap in this screen, not a fault in the data. */
.s-untaught { color: var(--ink-muted); font-family: var(--font-mono); }

/* A fact about a field, as a small neutral mark. */
.s-mark {
  display: inline-block; margin-right: var(--space-1);
  padding: 0 var(--space-2); border-radius: 999px;
  font-size: var(--text-xs); line-height: 18px;
  background: var(--surface-sunken); color: var(--ink-muted);
  border: 1px solid transparent;
}
/* A field somebody has hidden elsewhere is still listed here, and reads as
   set-apart rather than as filled-in: an outline instead of a fill. */
.s-mark[data-mark="hidden"] {
  background: transparent; border-color: var(--line-strong); border-style: dashed;
}

/* The relationships. Sentences at reading size, one per line, with the field
   that carries the link underneath in the quietest voice on the page — a
   person who has never seen a foreign key reads the sentence and stops, and a
   person who wants to know which field it is has it without asking. */
.s-sentences { list-style: none; margin: 0; padding: 0; }
.s-sentences li { margin-bottom: var(--space-3); }
/* `:not(.s-through)` because one item in this list is only the quiet line —
   the note saying a direction was never described — and without the guard the
   first-child rule outranks `.s-through` and shouts it. */
.s-sentences li > span:first-child:not(.s-through) {
  font-size: var(--text-lg); color: var(--ink-strong);
}
.s-through { display: block; color: var(--ink-faint); font-size: var(--text-xs); }

/* ── History ───────────────────────────────────────────────────────
   A timeline of sentences, not a table of rows. Every value below is a token,
   so both themes and all three densities come out of the same declarations —
   there is not one colour of its own in here, and `check-web.ts` fails the
   build if one appears. */

/* The day heading STICKS to the top of the room while its day scrolls past.
   A history is long and the thing a reader loses first is which day they are
   in; the heading is the cheapest possible answer to that, and it needs its own
   background because the entries scroll underneath it rather than behind a
   panel. `--surface-base` is the room's own ground, so it is invisible until
   something is under it. */
.h-day {
  position: sticky; top: 0; z-index: 1;
  margin: var(--space-5) 0 var(--space-2);
  padding: var(--space-2) 0;
  background: var(--surface-base);
  color: var(--ink-muted); font-size: var(--text-md);
  font-weight: var(--weight-medium);
  border-bottom: 1px solid var(--line);
}
.h-day:first-of-type { margin-top: 0; }

/* One entry. Quieter than `.s-card`, because a card per change turns a hundred
   changes into a hundred boxes; the border-left is the timeline. */
.h-entry {
  border-left: 2px solid var(--line-strong);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-2);
  background: var(--surface-raised);
  border-radius: 0 var(--radius) var(--radius) 0;
}

/* The sentence and the moment, on one line, with the moment pushed to the end.
   It wraps rather than truncates: a change's sentence is the entry, and a
   history that hides the end of what somebody did is not a history. */
.h-line { display: flex; gap: var(--space-3); align-items: baseline; flex-wrap: wrap; }
.h-sentence { flex: 1; min-width: 12rem; font-size: var(--text-lg); color: var(--ink-strong); }
.h-when { color: var(--ink-faint); font-size: var(--text-xs); white-space: nowrap; }

/* Somebody's words about the change — a reviewer's note, or what the server
   said when it ran. Labelled, because an unlabelled second line is
   indistinguishable from the sentence above it. */
.h-note { display: flex; gap: var(--space-2); align-items: baseline;
  margin-top: var(--space-1); color: var(--ink-muted); }
.h-note .faint { text-transform: uppercase; letter-spacing: 0.06em; }

/* The fold: this change was put back. It reuses the risk ramp's LOW colour
   through `.pill`, deliberately — undone is the settled state, and inventing a
   second colour scale for a lifecycle would teach a reader that the ramp they
   see on findings and plans means something different here. */
.h-undone { display: flex; gap: var(--space-2); align-items: baseline;
  margin-top: var(--space-2); color: var(--ink-muted); font-size: var(--text-sm); }

/* Where the undo is NOT. Said once, above the durable list, with the way
   through beside it — so it reads as a signpost rather than as a refusal. */
.h-elsewhere { display: flex; gap: var(--space-3); align-items: center;
  flex-wrap: wrap; margin-top: var(--space-3); color: var(--ink-muted); }

.h-acts { display: flex; gap: var(--space-2); align-items: center; margin-top: var(--space-2); }

/* The typed confirmation. Deliberately not a warning banner: the point is not
   to alarm, it is to make the act cost a sentence of attention rather than a
   click — the same argument `.s-plan .confirm` above makes, in the one other
   place this product asks for a word. */
.h-confirm { margin-top: var(--space-2); }
.h-confirm label { display: block; color: var(--risk-high); margin-bottom: var(--space-1); }
.h-confirm input { width: 12rem; }

/* What the server said back, in the place the button is. A refusal renders its
   own component in here; the margin is so it does not sit against the button
   that provoked it. */
.h-said:not(:empty) { margin-top: var(--space-2); }

/* ── The naming review's two endings ───────────────────────────────
   A pass that has been WRITTEN is not a pass that is waiting, and `.s-plan` —
   accent-bordered, the colour this surface uses for "a change is pending" —
   says the wrong thing about it. The confirmation gets the OK ramp instead, so
   the difference between "read this" and "this is done" is visible before a
   word is read. Same shape, same spacing; only the ramp differs. */
.s-done {
  border: 1px solid var(--ok); border-left-width: 3px;
  background: var(--ok-bg); border-radius: var(--radius);
  padding: var(--space-4); margin-top: var(--space-4);
}
.s-done .sentence { font-size: var(--text-lg); color: var(--ink-strong); margin-bottom: var(--space-2); }
/* The audit warning: the names WERE written and the team's record of them was
   not. Medium, not high — nothing is wrong with the database — and never the
   OK colour it sits on, because it is the one line here that is not good news. */
.s-done .caution { color: var(--risk-medium); margin-top: var(--space-2); }

/* ── Suggestions the pass would not use ────────────────────────────
   The count is the line and the reasons are the disclosure under it: a reader
   who does not care sees one sentence, and a reader who typed those names sees
   exactly which ones did not land and why. Medium rather than high — nothing
   was damaged, something was declined — and it must read the same inside the
   review box and inside the plain card the "nothing to name" answer uses, which
   is why it carries its own colour rather than borrowing `.s-plan .caution`. */
.s-rejected { color: var(--risk-medium); margin-bottom: var(--space-3); }
.s-rejected summary { cursor: pointer; color: var(--ink-muted); font-size: var(--text-sm); }
.s-rejected ul { margin: var(--space-2) 0 0; padding-left: var(--space-5); color: var(--ink-muted); }
.s-rejected li { margin-bottom: var(--space-1); }

/* ── Settings ──────────────────────────────────────────────────────
   Four classes, all of them for the Settings screen, all of them tokens.

   `.s-split` puts the controls and the live preview beside each other where
   there is room and stacks them where there is not. The basis is a real width
   rather than a percentage, because the thing on the right is a record card
   and a record card squeezed under 20rem stops being readable — below that it
   is better as a second row than as a narrow column. */
.s-split { display: flex; gap: var(--space-4); flex-wrap: wrap; align-items: flex-start; }
.s-split > * { flex: 1 1 22rem; min-width: 0; }

/* The preview is deliberately NOT styled like the record cards it contains.
   It is a rendering of a decision that has not been saved yet, and a dashed
   edge on a sunken ground is the difference between "this is what it would
   look like" and "this is what it looks like". */
.s-preview {
  background: var(--surface-sunken);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  padding: var(--space-3);
}
/* The card inside the preview loses its own margin: it is the only thing in
   there, and a trailing gap under it reads as a missing second card. */
.s-preview .s-card { margin-bottom: 0; }

/* A group of named choices — the density, the theme, developer mode. The
   pressed one is marked with `aria-pressed`, which is the state a screen
   reader already announces, so the visual state and the announced state are
   one attribute rather than a class that has to be kept in step with one. */
.s-choice { margin-top: var(--space-4); }
.s-choice .s-row { margin-bottom: var(--space-1); }
.s-choice button[aria-pressed="true"] {
  background: var(--accent-quiet); color: var(--accent); border-color: var(--accent);
  font-weight: var(--weight-medium);
}

/* A heading INSIDE a card, under the card's own `h3`. The browser default
   would set it larger than the h3 it sits beneath, which reads as the section
   ending and a new one starting. */
.s-sub {
  margin: var(--space-3) 0 var(--space-1);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  color: var(--ink-strong);
}

/* ── Home: the operator's morning ───────────────────────────────────
   Every rule below is scoped under `.s-home`, and every class this screen
   introduces carries an `hm-` prefix. Both, deliberately: the plain screens
   were written at the same time against this one stylesheet, and `.s-table`
   and `.s-count` had already been claimed by another screen, for different
   things, by the time this one wanted those names. A scoped selector stops
   this screen's rules leaking out; a prefixed class stops somebody else's
   leaking in. Tokens only, both themes, no colour of its own. */

.s-home { display: grid; gap: var(--space-5); max-width: 1100px; }
/* A grid child will not shrink below its own content without this, and the
   thing that would overflow is a long pinned question. */
.s-home > section { min-width: 0; }
.s-home h2 { margin: 0 0 var(--space-2); font-size: var(--text-lg);
  font-weight: var(--weight-medium); color: var(--ink-strong); }
.s-home .hm-lead { font-size: var(--text-lg); color: var(--ink-strong);
  margin-bottom: var(--space-2); }

/* A button that reads as a link. It navigates and changes nothing, and a
   bordered control on this surface reads as something that acts. */
.s-home .hm-link { border: none; background: transparent; color: var(--accent);
  padding: var(--space-1) 0; }
.s-home .hm-link:hover:not(:disabled) { background: transparent;
  color: var(--accent-hover); text-decoration: underline; }

/* Nothing here yet, said as a thing rather than left as a blank. Given a
   measure, because prose set to the width of a window is prose nobody reads. */
.s-home .hm-blank { background: var(--surface-raised); border: 1px solid var(--line);
  border-radius: var(--radius); padding: var(--space-4); max-width: 62ch; }
.s-home .hm-blank .muted { margin-top: var(--space-2); }

/* ── The board ─────────────────────────────────────────────────────
   `auto-fill` rather than a fixed count: one pin should not sit alone across a
   third of the window, and twelve should not each be a column one digit wide. */
.s-home .hm-board { display: grid; gap: var(--space-3);
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
.s-home .hm-tile { background: var(--surface-raised); border: 1px solid var(--line);
  border-radius: var(--radius); padding: var(--space-3); min-width: 0; }
.s-home .skeleton + .skeleton { margin-top: var(--space-2); }
.s-home .hm-head { display: flex; gap: var(--space-2); align-items: flex-start; }
/* The question is the thing you click to ask it again, and it WRAPS: a pinned
   question is a sentence somebody wrote, and cutting it to one line is how two
   different questions come to look like the same tile. */
.s-home .hm-q { flex: 1; text-align: left; border: none; background: transparent;
  padding: 0; color: var(--ink-strong); font-weight: var(--weight-medium); }
.s-home .hm-q:hover:not(:disabled) { background: transparent; color: var(--accent); }
.s-home .hm-off { border: none; background: transparent; color: var(--ink-faint);
  font-size: var(--text-xs); padding: 0 var(--space-1); white-space: nowrap; }
.s-home .hm-off:hover:not(:disabled) { background: transparent; color: var(--risk-high); }
/* The number: the one thing on this screen meant to be read from across a desk,
   in the data face, because it is data. */
.s-home .hm-n { font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--text-xl); color: var(--ink-strong); margin-top: var(--space-2); }
/* The delta is muted and never coloured. Up is good news on orders taken and
   bad news on orders failing; the board cannot tell which it is holding, and a
   green number would be it guessing on the one line where a guess reads as a
   judgement. */
.s-home .hm-delta { color: var(--ink-muted); margin-top: var(--space-1); }

/* The sparkline, stretched to the tile with `preserveAspectRatio="none"` so the
   line reaches both ends of it. `vector-effect` is what keeps the stroke one
   weight while that happens — without it, two tiles of different widths draw
   the same history at two different thicknesses. */
.s-home .hm-spark { display: block; width: 100%; height: 2rem; margin-top: var(--space-2); }
.s-home .hm-spark .hm-stroke { fill: none; stroke: var(--accent); stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.s-home .hm-spark .hm-dot,
.s-home .hm-spark .hm-now { fill: var(--accent); stroke: none; }

/* ── Waiting on you, and Recent: one line each ─────────────────────
   The same row in both, because they are the same shape — a sentence and when
   — and two lists that differ only in what they are about should not differ in
   how they read. */
.s-home .hm-lines { background: var(--surface-raised); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; }
.s-home .hm-row { display: flex; gap: var(--space-3); align-items: baseline;
  width: 100%; text-align: left; color: var(--ink);
  border: none; border-bottom: 1px solid var(--line); border-radius: 0;
  background: transparent; padding: var(--space-2) var(--space-3); }
.s-home .hm-row:last-child { border-bottom: none; }
.s-home button.hm-row:hover:not(:disabled) { background: var(--surface-hover); }
.s-home .hm-what { flex: 1; min-width: 0; color: var(--ink-strong); }
.s-home .hm-who { color: var(--ink-faint); font-size: var(--text-xs); white-space: nowrap; }

/* ── The tables ────────────────────────────────────────────────────*/
.s-home .hm-tables { display: grid; gap: var(--space-1);
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); }
.s-home .hm-table { display: flex; gap: var(--space-3); align-items: baseline;
  text-align: left; background: var(--surface-raised); border: 1px solid var(--line);
  border-radius: var(--radius); padding: var(--space-2) var(--space-3); }
.s-home .hm-name { flex: 1; min-width: 0; color: var(--ink-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The count is quiet, and in the data face with tabular figures: a column of
   counts whose digits do not line up cannot be compared at a glance, which is
   the only reason to put them beside each other. */
.s-home .hm-count { color: var(--ink-muted); font-family: var(--font-mono);
  font-variant-numeric: tabular-nums; font-size: var(--text-xs); white-space: nowrap; }
.s-home .hm-count .hm-link { font-size: var(--text-xs); }

/* ── Ask: the thread ───────────────────────────────────────────────
   A question, its answer, then the next question underneath — so a follow-up
   reads as a conversation rather than as a screen that replaced itself. The
   rule is on the LEFT rather than a border all the way round: a card per turn
   would make three answers look like three unrelated screens stacked up, and
   the thing being shown is that they are one thought. */
.s-turn { border-left: 2px solid var(--line); padding-left: var(--space-4);
  margin-bottom: var(--space-5); }
/* The newest turn is the one being read, and the accent alone says so. The
   earlier ones are NOT dimmed: an answer somebody is still comparing against
   has to stay as legible as the one under it, and greying out the context is
   how a thread stops being usable at the third question. */
.s-turn[data-latest="true"] { border-left-color: var(--accent); }
.s-asked { font-size: var(--text-lg); color: var(--ink-strong);
  margin-bottom: var(--space-2); }

/* The examples, built from this database's own names. Buttons and not text,
   because their whole purpose is to be put in the field and edited — and a
   button is the thing a keyboard already knows how to reach. */
.s-examples { display: flex; flex-direction: column; align-items: flex-start;
  gap: var(--space-1); margin-top: var(--space-3); }
.s-example { border-color: transparent; background: transparent;
  color: var(--accent); padding: var(--space-1) 0; text-align: left; }
.s-example:hover:not(:disabled) { background: transparent; text-decoration: underline; }

/* "Show me how" — one control over two artifacts: the statement the database
   saw, and what the model wrote. Each gets a name of its own, because a person
   debugging a bad answer wants both and should not have to wonder which one
   they are looking at. Quiet headings: they label the evidence, they are not
   headings of the page. */
.s-how { margin-top: var(--space-3); }
.s-how h4 { margin: var(--space-3) 0 0; font-size: var(--text-sm);
  color: var(--ink-muted); font-weight: var(--weight-medium); }
.s-how pre { background: var(--surface-sunken); border-radius: var(--radius-sm);
  padding: var(--space-3); font-size: var(--text-sm); overflow-x: auto;
  white-space: pre-wrap; word-break: break-word; margin: var(--space-1) 0 0; }

/* The row under an answer: what can be done with it, or the sentence saying
   why it cannot. The sentence occupies the same place as the button on
   purpose — a control that is simply absent teaches nothing. */
.s-acts { display: flex; align-items: center; gap: var(--space-2);
  flex-wrap: wrap; margin-top: var(--space-3); }

/* A control that reads as a link, wherever it appears. It is a BUTTON: a thing
   that opens a panel on this page has no address, and `<a href="#">` hands a
   keyboard user a destination that is not one. `card()` in `app.js` uses it for
   a record's own name, so it needs a rule outside any one screen's scope. */
.as-link {
  background: none; border: 0; padding: 0;
  font: inherit; color: var(--accent); text-align: left;
}
.as-link:hover { text-decoration: underline; }

/* The notice strip above the grid, where a refusal about a filter lands. It is
   a container for `.caution` lines rather than a look of its own, so it carries
   spacing and nothing else — its own block was the one class the screen's
   stylesheet did not declare, found by `check:web`'s used-versus-declared rule.
*/
.f-notice { margin: var(--space-2) 0; }

/* ── FIND (§3.6) ───────────────────────────────────────────────────
   Every rule below is scoped to a class this screen writes, or to `.s-grid`
   INSIDE this screen's own scroller. `.s-grid` is shared with the naming
   review, and a screen that restyled a shared component to suit itself would
   be the ad-hoc drift `design.css`'s header is about. Not one colour of its
   own: every value here is a token. */

.f-title { margin: 0 0 var(--space-1); font-size: var(--text-xl); color: var(--ink-strong); }

/* The filter row. Chips wrap rather than scroll — a filter that has scrolled
   out of sight is one somebody will forget is narrowing the list they are
   reading, and that is the whole hazard this control has. */
.f-chips { display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-2); margin-bottom: var(--space-3); }
.f-chip { display: inline-flex; align-items: center; gap: var(--space-1);
  background: var(--surface-raised); border: 1px solid var(--line-strong);
  border-radius: var(--radius); padding: var(--space-1) var(--space-1) var(--space-1) var(--space-2); }
.f-chip select, .f-chip input { border-color: transparent; background: transparent; }
.f-chip input { width: 9rem; }
.f-chip select:focus-visible, .f-chip input:focus-visible { background: var(--surface-base); }
/* The × that takes a filter off. Quiet until reached for: removing one is
   cheap and reversible, so it does not need to look like a decision. */
.f-drop { border-color: transparent; background: transparent; color: var(--ink-faint);
  padding: 0 var(--space-2); line-height: 1; }
.f-drop:hover:not(:disabled) { background: var(--risk-high-bg); color: var(--risk-high); }
.f-add { border-style: dashed; color: var(--ink-muted); }

/* Said only when something the reader can see is being ignored. `caution` is
   the shared warning ink; the layout is this screen's. */
.f-notice-line { display: flex; align-items: center; gap: var(--space-2);
  flex-wrap: wrap; margin-bottom: var(--space-3); color: var(--risk-medium); }

/* The line that says what the list IS. One line, quiet, above the numbers. */
.f-state { margin-bottom: var(--space-2); }
.f-aside { color: var(--ink-faint); }
/* A count and a price are numbers you can click. Styled as text with an
   underline rather than as buttons, because a row of three buttons under a
   grid reads as three actions and these are two explanations. */
.f-count, .f-cost {
  border: none; background: transparent; padding: 0; font: inherit;
  color: var(--accent); text-decoration: underline; text-underline-offset: 2px;
}
.f-count:hover:not(:disabled), .f-cost:hover:not(:disabled) { background: transparent; color: var(--accent-hover); }

/* ── The grid ──
   `.s-scroll` caps at 22rem, which was sized for the naming review's list. A
   page of records wants the height of the window; the horizontal scroll is the
   half that matters here, and it is why the cells do not wrap and the table is
   allowed to be wider than its box. The PAGE never scrolls sideways — if it
   did, the heading, the search box and the filters would go with it. */
.f-rows { max-height: 60vh; }
.f-rows .s-grid { width: auto; min-width: 100%; }
.f-rows td, .f-rows th { white-space: nowrap; }
.f-rows td { max-width: 22rem; overflow: hidden; text-overflow: ellipsis; }

/* A header is a button so it can be reached without a mouse. It has to look
   like the header it replaced, so it keeps none of a button's chrome. */
.f-sort { width: 100%; border: none; background: transparent; padding: 0;
  font: inherit; color: inherit; text-align: left; }
.f-sort:hover:not(:disabled) { background: transparent; color: var(--ink-strong); }
.f-arrow { color: var(--accent); }
/* What a field points at, in a header — quieter than the field's own name,
   because it is context for the field rather than a second field. The record
   card already says this in `.s-fields dt`; this is the same idea in a row. */
.s-grid th .points-at { color: var(--ink-faint); font-weight: var(--weight-normal); }

.f-row:hover td { background: var(--surface-hover); cursor: pointer; }
/* The name that opens a record. `as-link` is the shared idiom for a button that
   reads as text, and it is styled HERE rather than globally: other screens use
   it too and this one does not get to change how they look. */
.f-rows .as-link { border: none; background: transparent; padding: 0; font: inherit;
  color: var(--accent); text-align: left; }
.f-rows .as-link:hover:not(:disabled) { background: transparent; text-decoration: underline; }
/* An absent value is the WORDS "nothing yet" and must not be mistaken for one.
   `.empty` is already styled inside the record card; a grid cell is a different
   place and the rule was scoped there, so it is scoped here too. */
.s-grid .empty { color: var(--ink-faint); font-style: italic; }
/* An empty list explains itself in the space the records would have filled. */
.f-none { color: var(--ink-muted); white-space: normal; padding: var(--space-4); }

.f-page { margin-top: var(--space-3); }

/* ── One record ──
   An aside, not a dialog. It sits in the flow after the list, so nothing behind
   it is covered, dimmed or disabled and the list stays scrollable while it is
   open. The accent edge is what marks it as the thing that just opened. */
.f-record {
  border: 1px solid var(--line); border-left: 3px solid var(--accent);
  background: var(--surface-raised); border-radius: var(--radius);
  padding: var(--space-4); margin-top: var(--space-4);
}
.f-record h3 { margin: var(--space-4) 0 var(--space-2);
  font-size: var(--text-md); color: var(--ink-strong); }
.f-links { list-style: none; margin: 0; padding: 0; }
.f-links li { padding: var(--space-1) 0; border-bottom: 1px solid var(--line); }
.f-links li:last-child { border-bottom: 0; }
.f-link-value { color: var(--ink-muted); }

/* ── The foot: what it cost, and the SQL ──
   Both are always here, and both are one click from their explanation. */
.f-foot { margin-top: var(--space-4); border-top: 1px solid var(--line);
  padding-top: var(--space-3); }
.f-why { color: var(--ink-muted); font-size: var(--text-sm);
  background: var(--surface-sunken); border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3); margin-top: var(--space-2); max-width: 46rem; }
.f-why p { margin: 0 0 var(--space-2); }
.f-why p:last-child { margin-bottom: 0; }

/* The entries under one day. A list, because a history is one — the bullets and
   the indent are dropped, the semantics are kept. */
.h-list { list-style: none; margin: 0; padding: 0; }

/* ── The sign-in code, shown in the tab that asked and nowhere else ──
   Big and monospaced because somebody is about to copy it onto another device,
   often by reading it off one screen and typing it into another. `user-select`
   is left alone deliberately: making it selectable is the whole point. */
.s-code {
  display: block;
  margin: var(--space-3) 0;
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  letter-spacing: 0.18em;
  color: var(--accent);
}
.s-linkcode {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent-quiet);
}
/* The seam between the two ways in. A rule would say they are alternatives of
   equal weight; they are not — the passphrase is the one most people have. */
.s-or { margin-top: var(--space-3); font-size: var(--text-sm); }

/* An editable field is in the tab order now, so it needs to SHOW when it is
   focused — the hover style alone was a mouse-only affordance on a control a
   keyboard can reach. */
.s-fields dd[data-editable="true"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  background: var(--surface-hover);
}
