/* ==========================================================================
   Collector — clear daylight.

   The reading-room design this replaces set nearly everything in a warm
   serif on clay-tinted paper. The owner's verdict after living with it:
   old-fashioned, and tiring to read. So the registers are redrawn:

   - The interface — titles, lists, labels, controls — speaks Golos Text,
     a Cyrillic-native humanist sans (Paratype), with weight carrying the
     hierarchy. Crisp, current, quiet.
   - Only text somebody actually reads at length — articles, comments, AI
     answers, quotations — is set in Literata, a serif designed for screen
     reading (it is the Google Play Books face), not for nostalgia.

   The ground is a cool near-white; the one accent is a deep sky blue.
   Chroma stays low everywhere: this is read for hours at a time.

   Ө (U+04E8) and Ү (U+04AE) live in Google Fonts' `cyrillic-ext` subset, not
   in `cyrillic`. base.html therefore requests the families unpinned so the
   browser fetches both. Never add `&subset=cyrillic` — it silently breaks
   Mongolian while leaving Russian looking fine.
   ========================================================================== */

:root {
  /* --- surfaces -------------------------------------------------------- */
  /* Cool, low-chroma, tinted toward the sky accent so the neutrals and the
     accent read as one family rather than as grey plus a colour. */
  --paper:       oklch(98.3% 0.003 250);  /* the page itself */
  --sheet:       oklch(99.6% 0.002 250);  /* reading surfaces sit ABOVE the
                                             page, not below it */
  --sunk:        oklch(95.8% 0.005 248);  /* inputs and quiet fills */

  /* --- ink ------------------------------------------------------------- */
  --ink:         oklch(22% 0.015 262);    /* body text        ~14:1 on paper */
  --ink-soft:    oklch(44% 0.014 258);    /* secondary        ~7.5:1         */
  --ink-faint:   oklch(56% 0.012 255);    /* meta and labels  ~4.8:1, AA     */

  /* --- rules ----------------------------------------------------------- */
  --rule:        oklch(91.5% 0.005 250);  /* decorative hairlines           */
  --edge:        oklch(72% 0.010 252);    /* control borders — 3:1, AA      */

  /* --- accents --------------------------------------------------------- */
  /* One accent, used rarely, so it still means something when it appears.
     Chroma stays low: this is read for hours at a time. */
  --sky:        oklch(46% 0.135 250);
  --sky-deep:   oklch(37% 0.120 252);
  --sky-wash:   oklch(95.5% 0.020 245);

  --moss:        oklch(46% 0.085 155);    /* healthy, collected             */
  --moss-wash:   oklch(95.8% 0.030 152);
  --rust:        oklch(49% 0.150 28);     /* trouble — stated, not alarmed  */
  --rust-wash:   oklch(96% 0.025 26);

  /* --- type ------------------------------------------------------------ */
  --serif: "Literata", Georgia, "Times New Roman", serif;
  --sans:  "Golos Text", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Only for literal code inside an answer — never as "technical" costume. */
  --mono:  ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* Few sizes, real distance between them. The small end carries different
     registers (tracked labels vs. running meta), not competing steps. */
  --t-label: 0.8125rem;   /* 13 — tracked, uppercase                       */
  --t-meta:  0.9375rem;   /* 15 — dates, counts                            */
  --t-ui:    1.0625rem;   /* 17 — interface base, deliberately generous    */
  --t-read:  1.1875rem;   /* 19 — collected text                           */
  --t-sub:   1.375rem;    /* 22                                            */
  --t-head:  1.75rem;     /* 28                                            */
  --t-title: clamp(2rem, 1.55rem + 1.6vw, 2.75rem);
  --t-display: clamp(2.25rem, 1.6rem + 2.4vw, 3.25rem);

  /* --- space ----------------------------------------------------------- */
  --space-2xs: 0.25rem;
  --space-xs:  0.5rem;
  --space-sm:  0.75rem;
  --space-md:  1rem;
  --space-lg:  1.5rem;
  --space-xl:  2rem;
  --space-2xl: 3rem;
  --space-3xl: 4rem;
  --space-4xl: 6rem;

  --measure: 66ch;
  --shell: 74rem;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);   /* ease-out-quint */
}

/* Committed to light. The audience reads long Mongolian text at a desk in
   daylight; a dark theme here would be decoration, not a response to how the
   thing is used. Nothing below assumes a dark counterpart exists. */

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: var(--t-ui)/1.65 var(--sans);
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

/* Cyrillic lowercase is wider and more even than Latin; it wants a touch more
   air between lines and a hair less between letters than a Latin default. */
:lang(mn) { letter-spacing: -0.002em; }

a { color: var(--sky); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--sky-deep); }

:focus-visible {
  outline: 2px solid var(--sky-deep);
  outline-offset: 3px;
  border-radius: 2px;
}

img { max-width: 100%; }

.skip {
  position: absolute;
  left: -9999px;
  top: var(--space-xs);
  background: var(--sheet);
  border: 1px solid var(--edge);
  padding: var(--space-xs) var(--space-md);
  z-index: 100;
}
.skip:focus { left: var(--space-md); }

/* ============================================================ the masthead */

.masthead {
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  position: sticky;
  top: 0;
  z-index: 10;
}

.masthead-inner {
  max-width: var(--shell);
  margin: 0 auto;
  padding: var(--space-sm) var(--space-lg);
  display: flex;
  align-items: baseline;
  gap: var(--space-lg);
  flex-wrap: wrap;
}

.masthead-brand {
  font: 800 var(--t-sub)/1 var(--sans);
  color: var(--ink);
  text-decoration: none;
  letter-spacing: -0.01em;
  flex: 0 0 auto;
}
.masthead-brand:hover { color: var(--sky-deep); }

.masthead-nav {
  display: flex;
  gap: var(--space-lg);
  flex-wrap: wrap;
  flex: 1 1 auto;
}
.masthead-nav a {
  color: var(--ink-soft);
  font-size: var(--t-meta);
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
  transition: color 140ms var(--ease), border-color 140ms var(--ease);
}
.masthead-nav a:hover {
  color: var(--ink);
  border-bottom-color: var(--sky);
}
/* Where the reader is: a quiet neutral fill. Not the focus ring (that is an
   outline and stays one) and not sky, which means "the main action". */
.masthead-nav a[aria-current] {
  color: var(--ink);
  font-weight: 600;
  background: var(--sunk);
  border-radius: 4px;
  padding: 0 var(--space-2xs) 2px;
  margin: 0 calc(-1 * var(--space-2xs));
}

.masthead-end {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
  margin-left: auto;
  flex: 0 0 auto;
}

/* A running job is a sentence, not a blinking light. */
.masthead-status {
  font-size: var(--t-meta);
  color: var(--moss);
  text-decoration: none;
}
.masthead-status:hover { text-decoration: underline; }
.masthead-status-kind { color: var(--ink-soft); }

.masthead-account { display: flex; align-items: baseline; gap: var(--space-sm); }
.masthead-account a { font-size: var(--t-meta); color: var(--ink-soft); }
.masthead-account button {
  font: 500 var(--t-label)/1 var(--sans);
  padding: var(--space-2xs) var(--space-xs);
  background: none;
  border: 1px solid var(--edge);
  color: var(--ink-soft);
  cursor: pointer;
}
.masthead-account button:hover { color: var(--ink); border-color: var(--ink-soft); }

/* ================================================================== shell */

.page {
  max-width: var(--shell);
  margin: 0 auto;
  padding: var(--space-2xl) var(--space-lg) var(--space-4xl);
}

.colophon {
  max-width: var(--shell);
  margin: 0 auto;
  padding: var(--space-lg) var(--space-lg) var(--space-2xl);
  border-top: 1px solid var(--rule);
  color: var(--ink-faint);
  font-size: var(--t-meta);
}
.colophon p { margin: 0 0 var(--space-2xs); max-width: 60ch; }
.colophon-rule { color: var(--ink-soft); }

.backlink {
  margin: 0 0 var(--space-lg);
  font-size: var(--t-meta);
}
.backlink a { text-decoration: none; }
.backlink a::before { content: "← "; color: var(--ink-faint); }
.backlink a:hover { text-decoration: underline; }

/* ============================================================ page heading */

.page-head { margin-bottom: var(--space-2xl); }

.page-title {
  font: 800 var(--t-title)/1.1 var(--sans);
  letter-spacing: -0.018em;
  margin: 0;
  max-width: 20ch;
}

/* The sentence under a title explains the screen. It is set wide and soft so
   it reads as an aside, not as a second heading. */
.page-standfirst {
  margin: var(--space-md) 0 0;
  max-width: 58ch;
  color: var(--ink-soft);
  font-size: var(--t-ui);
  line-height: 1.6;
}

/* -- the working register ------------------------------------------------- */
/* Lists, search and operator screens are visited daily and scanned, not
   read: the chrome steps down one size, speaks sans, and says one sentence.
   Reading surfaces keep the editorial head above. (Brief, 2026-08-27.) */
.page-head--work { margin-bottom: var(--space-xl); }
.page-head--work .page-title {
  font: 600 var(--t-head)/1.15 var(--sans);
  letter-spacing: -0.008em;
}
.page-head--work .page-standfirst {
  margin-top: var(--space-xs);
  font-size: var(--t-meta);
  max-width: 64ch;
}

/* ================================================================ notices */

/* No coloured stripe down the side. A notice is a full-bordered slip of paper
   with a tinted ground — it reads as something set apart, not as a row with a
   highlighter mark on it. */
.notices { margin-bottom: var(--space-xl); }

.notice {
  margin: 0 0 var(--space-sm);
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--edge);
  background: var(--sheet);
  font-size: var(--t-meta);
  line-height: 1.6;
  max-width: 68ch;
}
.notice--message, .notice--ok { border-color: var(--moss); background: var(--moss-wash); }
.notice--warn { border-color: var(--sky); background: var(--sky-wash); }
.notice--error { border-color: var(--rust); background: var(--rust-wash); color: var(--ink); }

/* ================================================================== index */

/* A ruled index, the way a periodicals holdings list is set. Not cards: cards
   would put a box around every item and make sixty of them look like sixty
   products. Hairlines let the eye run straight down the titles. */
.index {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--rule);
}

.index-item {
  padding: var(--space-lg) 0;
  border-bottom: 1px solid var(--rule);
}

/* A filter bar already closes with a rule. Letting the list open with its own
   draws two hairlines a gap apart, which reads as a mistake. */
.sift + .index,
.toolbar + .index { border-top: none; }

.index-source {
  margin: 0 0 var(--space-2xs);
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-right: auto;          /* the two controls sit together on the right */
}

.index-title {
  margin: 0;
  font: 600 var(--t-sub)/1.3 var(--sans);
  letter-spacing: -0.008em;
  max-width: 46ch;
}
.index-title a { color: var(--ink); text-decoration: none; }
.index-title a:hover { color: var(--sky-deep); text-decoration: underline; }

.index-lede {
  margin: var(--space-xs) 0 0;
  max-width: var(--measure);
  color: var(--ink-soft);
  font-size: var(--t-meta);
  line-height: 1.6;
}

.index-meta {
  margin: var(--space-sm) 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  font-size: var(--t-meta);
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.index-meta a { color: var(--ink-faint); }
.index-meta a:hover { color: var(--sky-deep); }

/* ================================================== the article, and its margin */

.article { margin-bottom: var(--space-3xl); }

.article-head { margin-bottom: var(--space-xl); }

.article-kicker {
  margin: 0 0 var(--space-sm);
  font-size: var(--t-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sky);
}

.article-headline {
  margin: 0;
  font: 800 var(--t-display)/1.1 var(--sans);
  letter-spacing: -0.02em;
  max-width: 22ch;
  text-wrap: balance;
}

.article-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-xl);
}

/* On a wide screen everything the collector knows moves into the margin, and
   the text starts at the top of the page instead of below a stack of chrome. */
@media (min-width: 62rem) {
  .article-layout {
    grid-template-columns: 13rem minmax(0, var(--measure));
    gap: var(--space-3xl);
    align-items: start;
  }
}

.article-margin { font-size: var(--t-meta); }
.article-margin dl { margin: 0; }
.article-margin dt {
  font-size: var(--t-label);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.article-margin dd {
  margin: 0 0 var(--space-md);
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.article-margin-id { font-size: var(--t-label); }
.article-margin-out { margin: 0; padding-top: var(--space-xs); border-top: 1px solid var(--rule); }

/* The briefing line under the original link: selectable as text, copied by
   the button when the script has loaded. */
.citation { margin-top: var(--space-md); display: grid; gap: var(--space-2xs); }
.citation label { font-size: var(--t-meta); color: var(--ink-soft); }
.citation-line {
  width: 100%;
  font: var(--t-meta)/1.4 var(--sans);
  padding: var(--space-2xs) var(--space-xs);
  border: 1px solid var(--edge);
  background: var(--sunk);
  color: var(--ink);
}
.citation .button { justify-self: start; }
.citation-status { margin: 0; min-height: 1.4em; font-size: var(--t-meta); color: var(--ink-soft); }

/* The reading surface is LIGHTER than the page. The page recedes; the text
   comes forward. Doing it the other way round — a grey card on white — is why
   so much of this kind of tool feels like a form. */
.article-column {
  background: var(--sheet);
  border: 1px solid var(--rule);
  padding: var(--space-xl) var(--space-xl) var(--space-lg);
}

.article-body {
  margin: 0;
  white-space: pre-wrap;
  font: var(--t-read)/1.8 var(--serif);
  max-width: var(--measure);
  overflow-wrap: break-word;
}
.article-body--absent {
  font-style: italic;
  color: var(--ink-faint);
  font-size: var(--t-ui);
  line-height: 1.6;
}

/* Prose the model wrote, or the operator typed. Same reading treatment. */
.prose {
  margin: 0;
  white-space: pre-wrap;
  font: var(--t-read)/1.8 var(--serif);
  max-width: var(--measure);
  background: var(--sheet);
  border: 1px solid var(--rule);
  padding: var(--space-lg) var(--space-xl);
  overflow-wrap: break-word;
}

/* ================================================================= tally */

/* Seven hand-picked hues for seven reaction types was noise pretending to be
   information. The number is the information; the name is a label. */
.tally {
  margin-top: var(--space-xl);
  padding-top: var(--space-md);
  border-top: 1px solid var(--rule);
}

.tally-head {
  margin: 0 0 var(--space-sm);
  font: 500 var(--t-label)/1 var(--sans);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.tally-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md) var(--space-lg);
}

.tally-item { display: flex; align-items: baseline; gap: var(--space-2xs); }
.tally-num {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--ink);
}
.tally-label { font-size: var(--t-meta); color: var(--ink-faint); }
.tally-item--total .tally-num { color: var(--sky-deep); }

/* ================================================================ sections */

section.section { margin-top: var(--space-3xl); }

.section-head {
  margin: 0 0 var(--space-md);
  font: 700 var(--t-head)/1.2 var(--sans);
  letter-spacing: -0.015em;
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  flex-wrap: wrap;   /* a heading carrying a count and a price must wrap, not overflow */
}

/* The Schedule screen nests blocks two deep — "Every day" over four collectors —
   so it needs a second heading rank. Without this every heading sits at 28px
   and the page reads flat. */
.section-head--minor { font-size: var(--t-sub); }
.section-count {
  font: 400 var(--t-meta)/1 var(--sans);
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.section-note {
  margin: var(--space-md) 0 0;
  max-width: 62ch;
  font-size: var(--t-meta);
  line-height: 1.65;
  color: var(--ink-faint);
}

/* ================================================================= plates */

.plates {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-lg);
}

.plate { margin: 0; }
.plate img {
  display: block;
  width: 100%;
  height: 11rem;
  object-fit: cover;
  background: var(--sunk);
  border: 1px solid var(--rule);
}
.plate figcaption {
  margin-top: var(--space-xs);
  font-size: var(--t-meta);
  color: var(--ink-faint);
  line-height: 1.5;
}
.plate--link {
  border: 1px solid var(--rule);
  background: var(--sheet);
  padding: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  align-items: flex-start;
}
.plate--link a { font-size: var(--t-meta); overflow-wrap: anywhere; }
.plate-alt { margin: 0; font-size: var(--t-meta); color: var(--ink-faint); }

/* ============================================================= discussion */

/* Comments are indented and ruled, never marked with a coloured bar. A reply
   sits further in; that is what a reply looks like on paper. */
.discussion { list-style: none; margin: 0; padding: 0; }

.discussion-item {
  padding: var(--space-md) 0;
  border-top: 1px solid var(--rule);
  max-width: var(--measure);
}
.discussion-item:first-child { border-top: none; padding-top: 0; }
.discussion-item--reply { margin-left: var(--space-xl); }

.discussion-author {
  margin: 0 0 var(--space-2xs);
  font-weight: 600;
  font-size: var(--t-meta);
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
}

.discussion-text {
  margin: 0;
  white-space: pre-wrap;
  font: var(--t-ui)/1.7 var(--serif);
  overflow-wrap: break-word;
}

.discussion-meta {
  margin: var(--space-xs) 0 0;
  display: flex;
  gap: var(--space-md);
  font-size: var(--t-label);
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* ========================================================= correspondence */

/* Not a chat. The question is a line in the interface's voice; the answer is
   reading material and is set like everything else worth reading. */

.correspondence {
  margin: var(--space-2xl) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

.turn-who {
  margin: 0 0 var(--space-xs);
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  display: flex;
  gap: var(--space-sm);
}
.turn-who time { font-variant-numeric: tabular-nums; letter-spacing: 0.04em; }

.turn--asked { margin-left: clamp(0rem, 6vw, 5rem); }
.turn--asked .turn-text {
  margin: 0;
  font-size: var(--t-ui);
  line-height: 1.6;
  color: var(--ink-soft);
  padding-left: var(--space-md);
  border-left: 1px solid var(--rule);
}

.turn--answered .turn-text {
  margin: 0;
  white-space: pre-wrap;
  font: var(--t-read)/1.8 var(--serif);
  max-width: var(--measure);
  background: var(--sheet);
  border: 1px solid var(--rule);
  padding: var(--space-lg) var(--space-xl);
  animation: settle 420ms var(--ease) both;
}

@keyframes settle {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* An empty state that teaches the screen rather than announcing its own
   emptiness. */
.opening {
  border: 1px solid var(--rule);
  background: var(--sheet);
  padding: var(--space-xl);
}
.opening > p { margin: 0 0 var(--space-md); color: var(--ink-soft); }
.opening-list { margin: 0; }
.opening-list dt {
  font-weight: 600;
  font-size: var(--t-meta);
  margin-top: var(--space-md);
}
.opening-list dd {
  margin: var(--space-2xs) 0 0;
  color: var(--ink-soft);
  font-size: var(--t-meta);
  line-height: 1.6;
}
.opening-example {
  margin: var(--space-lg) 0 0;
  padding-top: var(--space-md);
  border-top: 1px solid var(--rule);
  font: italic 400 var(--t-ui)/1.6 var(--serif);
  color: var(--ink-faint);
}



/* ================================================================= roster */

.roster { margin: var(--space-xl) 0 0; }
.roster-head {
  margin: 0 0 var(--space-sm);
  font: 500 var(--t-label)/1 var(--sans);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.roster-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}
.roster-item {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-xs);
  padding: var(--space-2xs) var(--space-sm);
  border: 1px solid var(--rule);
  background: var(--sheet);
  font-size: var(--t-meta);
}
.roster-name { font-weight: 500; }
.roster-count {
  font-variant-numeric: tabular-nums;
  font-size: var(--t-label);
  color: var(--ink-faint);
}
.roster-item--collecting { border-style: dashed; }
.roster-item--error { border-color: var(--rust); background: var(--rust-wash); }

/* =============================================================== dossiers */

.index--dossiers .index-item { padding: var(--space-xl) 0; }

.dossier-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  flex-wrap: wrap;
}

.dossier-name {
  margin: 0;
  font: 650 var(--t-head)/1.2 var(--sans);
  letter-spacing: -0.015em;
}
.dossier-name a { color: var(--ink); text-decoration: none; }
.dossier-name a:hover { color: var(--sky-deep); text-decoration: underline; }

.dossier-leaning {
  margin: var(--space-md) 0 0;
  max-width: var(--measure);
  font: var(--t-ui)/1.7 var(--sans);
  color: var(--ink-soft);
}
.dossier-trouble {
  margin: var(--space-md) 0 0;
  max-width: 62ch;
  font-size: var(--t-meta);
  color: var(--rust);
}
.dossier-pending {
  margin: var(--space-md) 0 0;
  font-size: var(--t-meta);
  color: var(--ink-faint);
}

/* Figures are read, not admired. No oversized hero numerals. */
.figures {
  margin: var(--space-lg) 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-lg) var(--space-2xl);
}
.figures--wide { margin-top: var(--space-xl); }
.figure { display: flex; flex-direction: column-reverse; gap: var(--space-2xs); }
.figure dt {
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.figure dd {
  margin: 0;
  font: 600 var(--t-sub)/1 var(--sans);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.tags {
  list-style: none;
  margin: var(--space-lg) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}
.tag {
  padding: var(--space-2xs) var(--space-sm);
  background: var(--sunk);
  font-size: var(--t-meta);
  color: var(--ink-soft);
}

/* ============================================================ small parts */

.label {
  display: inline-block;
  padding: 0.1em 0.5em;
  background: var(--sunk);
  color: var(--ink-soft);
  font: 500 var(--t-label)/1.5 var(--sans);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* State is a word, in a tinted ground. Not a coloured square bullet. */
.status {
  display: inline-block;
  padding: 0.1em 0.5em;
  font: 500 var(--t-label)/1.5 var(--sans);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--sunk);
  color: var(--ink-soft);
}
.status--ok    { background: var(--moss-wash); color: var(--moss); }
.status--error { background: var(--rust-wash); color: var(--rust); }

.empty {
  margin: 0;
  padding: var(--space-xl);
  border: 1px dashed var(--edge);
  background: var(--sheet);
  color: var(--ink-soft);
  font-size: var(--t-meta);
  line-height: 1.7;
  max-width: 62ch;
}

.pager {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  margin-top: var(--space-xl);
}
.pager-count {
  font-size: var(--t-meta);
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* The results' own heading: where a search or a page change lands focus. */
.results-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm) var(--space-md);
  margin: 0 0 var(--space-lg);
}
.results-count {
  margin: 0;
  font: 600 var(--t-ui)/1.3 var(--sans);
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.results-skip { font-size: var(--t-meta); }

/* The masthead is sticky, so a fragment target scrolled to the very top would
   sit underneath it, focused but hidden. Leave room for the tallest masthead
   (the wrapped phone and 200 % zoom one). */
#results, #pagination, .index-title a[id] { scroll-margin-top: 10rem; }

/* ============================================================== controls */

button, .button {
  display: inline-block;
  font: 500 var(--t-meta)/1.2 var(--sans);
  padding: 0.65rem 1.1rem;
  border: 1px solid var(--edge);
  background: var(--sheet);
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
  transition: border-color 140ms var(--ease), background-color 140ms var(--ease), color 140ms var(--ease);
}
button:hover, .button:hover { border-color: var(--ink-soft); color: var(--ink); }

.button--primary, button.go {
  background: var(--sky);
  border-color: var(--sky);
  color: oklch(98.5% 0.008 70);
}
.button--primary:hover, button.go:hover {
  background: var(--sky-deep);
  border-color: var(--sky-deep);
  color: oklch(98.5% 0.008 70);
}

button:active:not(:disabled), .button:active { transform: translateY(1px); }

button:disabled, button[disabled] {
  background: var(--sunk);
  border-color: var(--rule);
  color: var(--ink-faint);
  cursor: not-allowed;
}

button.danger { color: var(--rust); border-color: var(--rust); background: var(--sheet); }
button.danger:hover { background: var(--rust-wash); }
button.link {
  border: none;
  background: none;
  color: var(--rust);
  padding: 0;
  font-size: var(--t-meta);
  text-decoration: underline;
  white-space: nowrap;
}

input[type=text], input[type=password], input[type=number],
input[type=search], select, textarea {
  font: var(--t-meta)/1.5 var(--sans);
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--edge);
  background: var(--sunk);
  color: var(--ink);
  width: 100%;
  border-radius: 0;
}
input:hover, select:hover, textarea:hover { border-color: var(--ink-faint); }
textarea { min-height: 11rem; resize: vertical; }
::placeholder { color: var(--ink-faint); opacity: 1; }

label {
  display: block;
  margin-bottom: var(--space-2xs);
  font-size: var(--t-meta);
  color: var(--ink-soft);
}

/* The filter bar on Collected: a row of fields on a rule, not a card. */
.sift {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  align-items: flex-end;
  padding-bottom: var(--space-lg);
  margin-bottom: var(--space-xl);
  border-bottom: 1px solid var(--rule);
}
.sift-field { flex: 1 1 11rem; }
.sift-field--wide { flex: 2 1 18rem; }
.sift-actions { display: flex; gap: var(--space-xs); flex: 0 0 auto; }

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  align-items: center;
  padding-bottom: var(--space-lg);
  margin-bottom: var(--space-xl);
  border-bottom: 1px solid var(--rule);
}
.toolbar-note {
  flex: 1 1 20rem;
  margin: 0;
  font-size: var(--t-meta);
  color: var(--ink-faint);
  line-height: 1.6;
}
.toolbar-note strong { color: var(--rust); font-weight: 600; }
.toolbar-label { font-size: var(--t-meta); color: var(--ink-faint); }
.toolbar-label:not(:first-child) { margin-left: var(--space-sm); }


/* ==========================================================================
   Operator components.

   Dashboard, Runs, Schedule, Sources, Accounts and the sign-in gate were not
   in this pass's scope. Their markup is untouched; these rules re-express the
   classes they use on the new tokens so those screens stay coherent instead of
   inheriting a half-replaced palette. They are deliberately quiet — when those
   screens are redesigned, this whole block goes.
   ========================================================================== */

h1 { font: 800 var(--t-title)/1.1 var(--sans); letter-spacing: -0.018em; margin: 0 0 var(--space-xs); }
h1.headline { font-size: var(--t-display); }
h2.section, h3.sub {
  font: 650 var(--t-sub)/1.2 var(--sans);
  color: var(--ink);
  margin: var(--space-2xl) 0 var(--space-md);
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
}
h3.sub { font-size: var(--t-ui); margin-top: var(--space-xl); }

.eyebrow {
  margin: 0 0 var(--space-xs);
  font-size: var(--t-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sky);
}
.subtitle {
  margin: 0 0 var(--space-xl);
  max-width: 58ch;
  color: var(--ink-soft);
  font-size: var(--t-meta);
  line-height: 1.6;
}

.decks { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-lg); align-items: start; }
@media (max-width: 52rem) { .decks { grid-template-columns: 1fr; } }

.deck, .panel {
  background: var(--sheet);
  border: 1px solid var(--rule);
  padding: var(--space-lg);
  margin-bottom: var(--space-md);
}
.panel.paper { padding: var(--space-xs) var(--space-lg); }
.deck-head { display: flex; align-items: baseline; gap: var(--space-sm); flex-wrap: wrap; }
.deck-head h2 { margin: 0; font: 650 var(--t-sub)/1.2 var(--sans); }
.deck-tag {
  font: 500 var(--t-label)/1.5 var(--sans);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.deck-tag.cost { color: var(--sky); }
.deck-form { display: flex; flex-direction: column; gap: var(--space-md); }

.readouts { display: flex; gap: var(--space-xl); margin: var(--space-lg) 0; flex-wrap: wrap; }
.readout b {
  display: block;
  font: 600 var(--t-head)/1 var(--sans);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.015em;
}
.readout b.stamp { font-size: var(--t-ui); }
.readout span {
  display: block;
  margin-top: var(--space-2xs);
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.deck-note {
  margin: var(--space-md) 0 0;
  max-width: 60ch;
  font-size: var(--t-meta);
  line-height: 1.65;
  color: var(--ink-faint);
}
.deck-note .warn, .warn { color: var(--rust); display: block; margin-top: var(--space-2xs); }

/* The pre-flight cost meter: the same arithmetic as the CLI's estimate, shown
   before the button rather than after the spend. */
.meter { margin: var(--space-lg) 0 var(--space-2xs); }
.meter-track {
  height: 0.5rem;
  background: var(--sunk);
  border: 1px solid var(--rule);
  overflow: hidden;
}
.meter-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--sky);
  transition: width 160ms var(--ease);
}
.meter.over .meter-fill { background: var(--rust); }
.meter-line {
  margin: var(--space-xs) 0 0;
  font-size: var(--t-ui);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.meter.over .meter-line { color: var(--rust); }

/* Alerts, like notices, get a border and a ground — never a side stripe. */
.alert {
  margin: var(--space-lg) 0 0;
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--sky);
  background: var(--sky-wash);
  font-size: var(--t-meta);
  line-height: 1.6;
  max-width: 68ch;
}

table { width: 100%; border-collapse: collapse; font-size: var(--t-meta); }
th, td {
  text-align: left;
  padding: var(--space-sm) var(--space-md) var(--space-sm) 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
th {
  color: var(--ink-faint);
  font: 500 var(--t-label)/1.4 var(--sans);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
tr:last-child td { border-bottom: none; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.table-wrap { overflow-x: auto; }
/* A URL or an error message is one unbreakable token; left alone it pushed
   the table past its container and the last columns off the screen, with the
   scrollbar 180 rows further down. */
.table-wrap td { overflow-wrap: anywhere; }

.tier {
  display: inline-block;
  padding: 0.1em 0.5em;
  background: var(--sunk);
  color: var(--ink-soft);
  font: 500 var(--t-label)/1.5 var(--sans);
  letter-spacing: 0.06em;
}
.tier.paid { background: var(--sky-wash); color: var(--sky-deep); }

.state {
  font: 500 var(--t-label)/1.5 var(--sans);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.state.ok { color: var(--moss); }
.state.error { color: var(--rust); }

pre.log {
  margin: 0;
  padding: var(--space-md);
  background: var(--sunk);
  border: 1px solid var(--rule);
  color: var(--ink);
  overflow: auto;
  max-height: 62vh;
  font: 0.8125rem/1.6 ui-monospace, "Cascadia Mono", Consolas, "DejaVu Sans Mono", monospace;
  white-space: pre-wrap;
  word-break: break-word;
}
pre.log.setup { margin-top: var(--space-sm); user-select: all; }

.row { display: flex; gap: var(--space-md); flex-wrap: wrap; align-items: flex-end; }
.row > * { flex: 1 1 10rem; }
.row > .shrink { flex: 0 0 auto; }
.checkbox { display: flex; align-items: center; gap: var(--space-xs); padding-bottom: var(--space-sm); }
.checkbox input { width: auto; }
.checkbox label { margin: 0; }
.row-actions { display: flex; gap: var(--space-md); align-items: baseline; }
.row-actions form, form.inline { display: inline; }

.gate { max-width: 24rem; margin: var(--space-3xl) auto; }

/* The old list styles, still used by the dashboard's recent-items panel. */
.post-list { list-style: none; padding: 0; margin: 0; }
.post-list li { border-bottom: 1px solid var(--rule); padding: var(--space-md) 0; }
.post-list li:last-child { border-bottom: none; }
.post-list > li > a { color: var(--ink); font: 550 var(--t-ui)/1.4 var(--sans); text-decoration: none; }
.post-list > li > a:hover { color: var(--sky-deep); text-decoration: underline; }
.post-meta {
  margin-top: var(--space-xs);
  display: flex;
  gap: var(--space-md);
  flex-wrap: wrap;
  font-size: var(--t-meta);
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.muted { color: var(--ink-faint); }
.small { font-size: var(--t-meta); }
.mono { font-family: ui-monospace, Consolas, monospace; font-size: 0.8125rem; }
.stamp { font-variant-numeric: tabular-nums; }

/* ================================================== merged from the pass */

/* A column of form controls. `.deck-form` is the old name for the same thing
   and is kept as an alias so the screens still using it keep their rhythm when
   the operator-components block below is finally deleted. */
.stack,
.deck-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* The raw config-file editors on Sources: plain forms, one under another, with
   nothing but space between them. */
.file-editor { margin-top: var(--space-xl); }
.file-editor button { margin-top: var(--space-sm); }

/* Inside a toolbar everything centres on one line; .checkbox's bottom padding
   exists to baseline-align it in a .row and lifts it off-centre here. */
.toolbar .checkbox { padding-bottom: 0; }

/* Section prose has no bottom margin, so a table directly after it collides
   with the explanatory sentence and reads as a caption. */
.section-note + .table-wrap { margin-top: var(--space-lg); }

/* The comments form on Profiles follows a table with no separation of its own.
   Scoped to the form itself: an earlier draft scoped this to `.section
   .deck-form`, which would also have pushed the dashboard's three collector
   forms down. */
#comments-form { margin-top: var(--space-xl); }

/* Neutral status. Declared rather than left implicit, because profiles.html and
   pages.html both emit it and a class with no rule is indistinguishable from a
   typo when someone next reads the sheet. */
.status--idle { background: var(--sunk); color: var(--ink-soft); }

/* A list of items belonging to one entry — the posts under a topic. It drops
   the index's own top rule and indents, so it reads as part of its parent
   rather than as a second index nested inside the first. */
.index--nested {
  border-top: none;
  margin: var(--space-lg) 0 0;
  padding-left: var(--space-lg);
  border-left: 1px solid var(--rule);   /* 1px: a hairline, not an accent stripe */
}
.index--nested .index-item { padding: var(--space-sm) 0; border-bottom: none; }
.index--nested .index-title { font-size: var(--t-ui); }
.index--nested .index-meta { margin-top: var(--space-2xs); }

/* ============================================================== narrow */

/* On a phone the sheet's generous side padding eats the measure — 2rem each
   side of a 430px screen leaves barely 40 characters. The reading surface
   keeps its ground and its border; it just stops wasting the width. */
@media (max-width: 40rem) {
  .page { padding-left: var(--space-md); padding-right: var(--space-md); }
  .masthead-inner { padding-left: var(--space-md); padding-right: var(--space-md); }
  /* Eleven links do not fit a phone in one row; a strip that scrolls sideways
     beats the three-row block they wrapped into. */
  .masthead-nav {
    flex-wrap: nowrap;
    overflow-x: auto;
    min-width: 0;
    flex-basis: 100%;
    padding-bottom: var(--space-2xs);
  }
  .masthead-nav a { white-space: nowrap; }
  .colophon { padding-left: var(--space-md); padding-right: var(--space-md); }

  .article-column,
  .prose,
  .opening,
  .turn--answered .turn-text {
    padding-left: var(--space-md);
    padding-right: var(--space-md);
  }

  .empty { padding: var(--space-lg) var(--space-md); }

  /* Send sits under the box rather than squeezing it to a stub. */

  .figures { gap: var(--space-md) var(--space-lg); }
}

/* ================================================================= motion */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================== citations */

/* A citation carries its source in a tooltip rather than in a list under the
   answer, which was longer than the answer. Ported onto the new tokens: the
   marker is a superscript numeral in the interface face with tabular figures,
   not a monospace run — monospace here would read as machinery inside a
   sentence somebody is reading. */
.cite {
  font: 600 0.7em/1 var(--sans);
  font-variant-numeric: tabular-nums;
  vertical-align: super;
  padding: 0 0.1em;
  text-decoration: none;
  color: var(--ink-faint);
  border-bottom: 1px dotted var(--rule);
  cursor: help;
}
.cite:hover { color: var(--sky-deep); border-bottom-color: var(--sky); }

/* The cited numbers, listed under the answer with their links: the tooltip is
   nothing on a phone. Small and quiet; it is a footnote block, not the text. */
.turn--answered .turn-text .sources {
  margin: var(--space-md) 0 0;
  padding: var(--space-sm) 0 0 2.2em;
  border-top: 1px solid var(--rule);
  font: var(--t-label)/1.5 var(--sans);
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.sources li + li { margin-top: 2px; }
.sources a { color: var(--ink-soft); text-decoration: none; }
.sources a:hover { color: var(--sky-deep); text-decoration: underline; }

/* ---- ask: the history rail's contents ---------------------------------- */
/* The rail's own frame lives with the shell at the end of this sheet; what is
   here is the list inside it, which the shell did not change. */

.thread-list { list-style: none; margin: 0; padding: 0; }
.thread + .thread { margin-top: 2px; }
.thread a {
  display: block; padding: 6px 8px; border-radius: 5px;
  text-decoration: none; color: inherit;
}
.thread a:hover { background: var(--sunk); }
/* The open conversation is marked quietly, in the accent's wash. */
.thread--open a { background: var(--sky-wash); }
.thread-title {
  display: block; font-size: var(--t-label); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.thread-meta {
  display: flex; justify-content: space-between; gap: var(--space-xs);
  font-size: 0.75rem; color: var(--ink-faint); margin-top: 3px;
}

/* Reusing a question is why anyone opens the history. */
.reuse {
  background: none; border: 0; padding: 2px 0 2px var(--space-xs);
  font: inherit; font-size: 0.75rem; color: var(--ink-faint); cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.18em;
}
.reuse:hover { color: var(--sky-deep); }

/* An answer arrives a few words at a time; the box must not jump as it grows.
   (Markdown rendering sets white-space back to normal further down.) */
.turn--answered .turn-text { min-height: 1.4em; }

/* ---- profiles: the report link and the cohort toggle -------------------- */

.dossier-report { margin-left: auto; font-size: var(--t-meta); }
.dossier-cohort { display: inline; }
.dossier-cohort .button { padding: 0.3rem 0.7rem; font-size: var(--t-label); }

/* ---- the connection graph ---------------------------------------------- */

.graph-wrap { margin: 24px 0; }
.graph-legend svg { vertical-align: -1px; }
#graph {
  width: 100%; height: auto; max-height: 78vh;
  color: var(--ink);
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: 10px;
  cursor: grab;
  touch-action: none;   /* pinch and drag belong to the graph, not the page */
  user-select: none;
}
#graph:active { cursor: grabbing; }
#graph text {
  font: 600 11.5px var(--sans);
  fill: var(--ink);
  /* A halo the colour of the sheet keeps names readable across edges. */
  paint-order: stroke;
  stroke: var(--sheet);
  stroke-width: 3px;
  stroke-linejoin: round;
}
#graph a:hover text { fill: var(--sky); }

.graph-node circle { fill: var(--ink); opacity: 0.78; transition: opacity 160ms var(--ease); }
/* People and organisations are told apart by shape of ink, not by hue: the
   page has to stay readable in print too. */
.graph-node--organisation circle { fill: var(--sheet); stroke: var(--ink); stroke-width: 1.6; }

.edge { stroke: var(--sky); }

/* Quiet names carry no label at rest; focus or zoom brings them forward. */
.graph-node--quiet text { opacity: 0; transition: opacity 200ms var(--ease); }
.graph--zoomed .graph-node--quiet text,
.graph--focused .graph-node--quiet.node--on text { opacity: 1; }

/* Focusing one name pushes everything unrelated back. */
.graph--focused .graph-node { opacity: 0.15; }
.graph--focused .graph-node.node--on { opacity: 1; }
.graph--focused .edge { opacity: 0.06; transition: opacity 160ms var(--ease); }
.graph--focused .edge.edge--on { opacity: 1; stroke: var(--sky-deep); }

/* Arrival: dots settle in, then the connections thread themselves. */
/* `backwards`, and keyframes with only a `from`: once the entrance ends the
   animation stops owning opacity, so the focus dimming above can take over. */
@media (prefers-reduced-motion: no-preference) {
  .graph-node {
    transform-box: fill-box; transform-origin: center;
    animation: graph-node-in 480ms var(--ease) backwards;
  }
  .edge { animation: graph-edge-in 700ms var(--ease) backwards; }
}
@keyframes graph-node-in { from { opacity: 0; transform: scale(0.6); } }
@keyframes graph-edge-in { from { opacity: 0; } }

/* ---- offers: a suggestion you can act on -------------------------------- */

.offers {
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: var(--space-sm) var(--space-md);
  margin-top: 6px;
  background: var(--sheet);
}
.offers-head { margin: 0 0 var(--space-xs); font-size: var(--t-label); color: var(--ink-soft); }
.offer {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  grid-template-areas: "what yes no" "why yes no";
  gap: 2px var(--space-xs);
  align-items: center;
  padding: var(--space-xs) 0;
}
.offer + .offer { border-top: 1px solid var(--rule); }
.offer-what { grid-area: what; font-size: var(--t-meta); }
.offer-why { grid-area: why; font-size: var(--t-label); color: var(--ink-faint); }
.offer-yes { grid-area: yes; }
.offer-no { grid-area: no; }
/* Taken, not gone: the reader should see what they accepted. */
.offer--taken { opacity: 0.45; }

/* ---- rendered answers --------------------------------------------------- */

/* The model writes Markdown; the answer is now real markup rather than a
   pre-wrapped block, so it needs ordinary prose spacing. */
.turn--answered .turn-text { white-space: normal; }
.turn--answered .turn-text > :first-child { margin-top: 0; }
.turn--answered .turn-text > :last-child { margin-bottom: 0; }
.turn--answered .turn-text p { margin: 0 0 0.85em; line-height: 1.65; }
/* Subheads sit in the interface voice, above a serif body: smaller than the
   text but unmistakably a heading, by family and weight rather than size. */
.turn--answered .turn-text h3,
.turn--answered .turn-text h4,
.turn--answered .turn-text h5 {
  margin: 1.4em 0 0.5em;
  font: 600 var(--t-ui)/1.3 var(--sans);
  letter-spacing: 0.01em;
}
.turn--answered .turn-text ul,
.turn--answered .turn-text ol { margin: 0 0 0.9em; padding-left: 1.4em; }
.turn--answered .turn-text li { margin-bottom: 0.35em; line-height: 1.6; }
.turn--answered .turn-text hr {
  border: 0; border-top: 1px solid var(--rule); margin: 1.6em 0 1.1em;
}
.turn--answered .turn-text code {
  font-family: var(--mono); font-size: 0.9em;
  background: var(--sunk); padding: 1px 4px; border-radius: 3px;
}

/* ---- stance: the words a position was read from ------------------------- */

/* The quotation is somebody's sentence: it stays in plain ink, on a quiet
   wash, and the stance is said in a word in the byline — not painted onto
   the quote and not hung on an edge stripe. */
.stance-quote {
  margin: var(--space-sm) 0 0;
  padding: var(--space-sm) var(--space-md);
  background: var(--sunk);
  border-radius: 6px;
}
.stance-quote p {
  margin: 0; font: 400 var(--t-meta)/1.6 var(--serif);
}
.stance-quote cite {
  display: block; margin-top: var(--space-2xs);
  font-size: var(--t-label); font-style: normal; color: var(--ink-faint);
}
.stance-word { font-weight: 600; }
.stance-word--support { color: var(--moss); }
.stance-word--oppose { color: var(--rust); }
.stance-word--mixed { color: var(--ink-soft); }


/* The line that says what the answer is waiting on. It pulses so that a long
   wait still looks like work rather than a page that has stopped. */
.stage {
  color: var(--ink-soft);
  font-style: italic;
  animation: stage-pulse 1.6s ease-in-out infinite;
}

/* The same line after the answer has arrived, while the deep lane checks it. */
.stage--trailing { margin: var(--space-sm) 0 0; font-size: var(--t-meta); }

@keyframes stage-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

@media (prefers-reduced-motion: reduce) {
  .stage { animation: none; }
  button:active:not(:disabled), .button:active { transform: none; }
}

/* Fingers are wider than cursors. */
@media (pointer: coarse) {
  .rail-toggle { width: 2.75rem; height: 2.75rem; }
  .compose-send, .compose-depth { min-height: 2.75rem; }
  .reuse { padding: var(--space-xs) var(--space-2xs) var(--space-xs) var(--space-xs); }
}


/* The hidden attribute loses to any author rule that sets display -- .button
   sets inline-block, .to-latest set block -- so `hidden` did nothing on the
   Stop button or the jump-to-latest pill and both showed on a page with no
   answer streaming at all. This is the standard defensive rule and belongs
   near the top of any sheet that uses the attribute. */
[hidden] { display: none !important; }

/* Present for a screen reader, absent for everyone else. The composer's label
   is carried visually by its placeholder; the label still has to exist. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ==================================================== chat: reach and control

   The interaction patterns every mature chat interface converged on, expressed
   in this design's own tokens rather than borrowed from its look. What is
   adopted is behaviour: the input is always reachable, the answer can be
   stopped and copied, and the page does not fight a reader who scrolls up. */

/* The composer stays within reach. It used to sit after the conversation, so
   a long thread meant scrolling to the bottom before you could ask anything --
   the single biggest friction here. Sticky rather than fixed, so it still
   belongs to the column and cannot cover the sidebar. */
/* The chat's bottom edge is the composer. .page carries --space-4xl of bottom
   padding, which is right for a screen that ends with content and a colophon
   under it -- and is exactly the empty band left below a sticky input when
   neither follows. */

/* The depth toggle sits beside Send: quiet until pressed, then filled the
   way a chosen thing is. aria-pressed carries the state for styling too. */
.compose-depth {
  border: 1px solid var(--edge);
  border-radius: 8px;
  background: var(--sheet);
  color: var(--ink-soft);
  font: 500 var(--t-meta)/1 var(--sans);
  padding: 0.55em 0.9em;
  cursor: pointer;
  transition: background 140ms var(--ease), color 140ms var(--ease),
              border-color 140ms var(--ease);
}
.compose-depth:hover { border-color: var(--sky); color: var(--sky-deep); }
.compose-depth[aria-pressed="true"] {
  background: var(--sky);
  border-color: var(--sky);
  color: var(--sheet);
}

/* Room for the composer to stick over. Without it the last paragraph of an
   answer sits underneath the input and cannot be scrolled clear of it. */


/* Grown by JS up to a ceiling, so the box is one line for a question and four
   for a pasted paragraph. resize is dropped: the height is now the content's
   business, and a hand-dragged box fights it on the next keystroke. */


/* Copy sits in the answer's own byline, quiet until the answer is hovered --
   present when wanted, invisible while reading. It stays visible on focus so
   it is reachable from the keyboard. */
/* Only .copy. .reuse is left exactly as it was -- always visible at 0.55 --
   because the comment above it says reusing a question is why anyone opens the
   history, and hiding a feature behind hover is not an improvement to it. */
/* Always visible at the same weight as .reuse beside it, not revealed on
   hover. Two reasons: a hover-only control does not exist on a touch screen,
   and an affordance that appears when the pointer happens to pass over it is
   how people never learn it is there. Quiet is enough. */
.turn-who .copy {
  margin-left: auto;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 0.75rem;
  color: var(--ink-faint);
  opacity: 0.55;
  cursor: pointer;
  text-decoration: underline;
  transition: opacity 120ms var(--ease), color 120ms var(--ease);
}
.turn-who .copy:hover,
.turn-who .copy:focus-visible { opacity: 1; color: var(--sky); }

/* Shown only when an answer is growing below the fold. Clicking it is the
   reader choosing to follow again, which is the only time the page should
   move on its own. */

/* Touch: the composer must clear the on-screen keyboard and the home bar. */
@supports (padding: env(safe-area-inset-bottom)) {
  .compose { padding-bottom: calc(var(--space-lg) + env(safe-area-inset-bottom)); }
}

@media (prefers-reduced-motion: reduce) {
  .compose-field textarea { transition: none; }
}


/* ===================================================================== ask

   The chat as an application shell rather than a document.

   ChatGPT and Gemini both arrived at the same structure, and it is the right
   one: the conversation scrolls inside its own pane, the composer is docked
   under it, and neither can cover the other. What is borrowed is that
   structure. The surface it is built from -- cool daylight, Literata for anything
   collected, Golos Text for the chrome -- stays this project's own, because a
   library should not be dressed as a chat product.
   ---------------------------------------------------------------------- */

/* The shell page is the one screen that does not scroll as a document. The
   body becomes a column, the masthead takes the height it needs -- it wraps at
   narrow widths, so it has no fixed height to subtract -- and the shell takes
   exactly what is left. No magic number, and nothing to re-tune when the
   navigation grows another item. */
/* A class set by the chat template, not :has(): the selector was the one
   modern dependency in the stylesheet, and where it is not understood the
   rail loses its left edge and scrolls away with the page. */
body.with-ask {
  height: 100dvh;          /* dvh: on a phone the browser chrome moves, vh lies */
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
body.with-ask .page {
  flex: 1;
  min-height: 0;
  max-width: none;
  margin: 0;               /* flush left: no centring margin survives */
  padding: 0;
}

.ask-shell {
  height: 100%;
  display: grid;
  /* Narrow on purpose. The rail is for recognising a past question, not for
     reading it -- the titles ellipsis anyway -- so every rem it gives back
     goes to the answer, which is the thing anyone is actually here to read. */
  grid-template-columns: minmax(0, 12.5rem) minmax(0, 1fr);
  min-height: 0;
  transition: grid-template-columns 220ms var(--ease);
}

/* Collapsed. The rail keeps its place in the grid at zero width rather than
   being removed from it, so the conversation reflows once, smoothly, instead
   of jumping when a column appears and disappears. */
.ask-shell[data-rail="closed"] { grid-template-columns: 0 minmax(0, 1fr); }
.ask-shell[data-rail="closed"] .ask-history {
  overflow: hidden;
  border-right: 0;
  /* Nothing inside is focusable while it is not visible. */
  visibility: hidden;
}

/* -- the history rail -------------------------------------------------- */

.ask-history {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--rule);
  background: var(--paper);
}
.ask-history-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-2xs);
  padding: var(--space-sm) var(--space-xs) 0 var(--space-sm);
}
.ask-history-head h2 {
  margin: 0;
  font: 500 0.6875rem/1 var(--sans);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* Starting again is the list's first row, in the list's own manner. */
.rail-new {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  margin: var(--space-2xs) var(--space-2xs) 0;
  padding: 6px 8px;
  border-radius: 5px;
  font-size: var(--t-label);
  color: var(--ink-soft);
  text-decoration: none;
}
.rail-new:hover { background: var(--sunk); color: var(--ink); }
.rail-new svg { flex: none; opacity: 0.7; }
/* Its own scroll, so a long history never pushes the conversation around. */
.ask-history-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 var(--space-2xs) var(--space-lg);
}

/* -- the conversation pane --------------------------------------------- */

.ask-main {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}

/* The one element that scrolls. Everything else holds still. */
.ask-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-behavior: smooth;
}

/* One measure, shared by the conversation and the composer, so the input lines
   up with the text it answers instead of floating in its own column. */
.ask-column {
  max-width: 48rem;
  margin: 0 auto;
  padding: var(--space-xl) var(--space-lg);
}

.correspondence {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

/* -- the dock ---------------------------------------------------------- */

.ask-dock {
  flex: none;
  border-top: 1px solid var(--rule);
  background: var(--paper);
}
.ask-dock .ask-column { padding-top: var(--space-md); padding-bottom: var(--space-md); }

/* The field is one object -- box, text and send together -- the way a chat
   composer reads now, rather than an input with a button parked beside it. */
.compose-field {
  display: flex;
  align-items: flex-end;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-sm) var(--space-sm) var(--space-md);
  background: var(--sheet);
  border: 1px solid var(--edge);
  border-radius: 1.25rem;
  transition: border-color 140ms var(--ease), box-shadow 140ms var(--ease);
}
.compose-field:focus-within {
  border-color: var(--sky);
  box-shadow: 0 0 0 3px var(--sky-wash);
}
.compose-field textarea {
  flex: 1 1 auto;
  min-height: 1.75rem;
  max-height: 40dvh;
  border: 0;
  padding: var(--space-2xs) 0;
  background: none;
  color: var(--ink);
  font: var(--t-ui)/1.55 var(--sans);
  resize: none;
  overflow-y: hidden;
}
.compose-field textarea:focus { outline: none; }
.compose-field textarea::placeholder { color: var(--ink-faint); }

.compose-actions { display: flex; align-items: center; gap: var(--space-2xs); }

.compose-send {
  flex: none;
  border: 1px solid var(--sky);
  border-radius: 999px;
  padding: var(--space-2xs) var(--space-md);
  background: var(--sky);
  color: oklch(98.5% 0.008 70);
  font: 500 var(--t-meta)/1.4 var(--sans);
  cursor: pointer;
  transition: background 120ms var(--ease), border-color 120ms var(--ease);
}
.compose-send:hover { background: var(--sky-deep); border-color: var(--sky-deep); }
.compose-send:disabled { background: var(--sunk); border-color: var(--rule); color: var(--ink-faint); }
/* Stop is the same shape in the same place, so the control does not move --
   only what it does changes. */
.compose-send--stop {
  background: var(--sheet);
  border-color: var(--edge);
  color: var(--ink-soft);
}
.compose-send--stop:hover { background: var(--sunk); border-color: var(--ink-faint); }

.compose-hint {
  margin: var(--space-2xs) 0 0;
  font-size: var(--t-label);
  color: var(--ink-faint);
}
/* What the pressed deep toggle costs, said once, under the box it applies to. */
.compose-hint--deep { color: var(--ink-soft); }

/* -- the jump-back pill ------------------------------------------------ */

.to-latest {
  position: absolute;
  left: 50%;
  bottom: var(--space-md);
  transform: translateX(-50%);
  z-index: 4;
  border: 1px solid var(--edge);
  border-radius: 999px;
  padding: var(--space-2xs) var(--space-md);
  background: var(--sheet);
  color: var(--ink-soft);
  font: var(--t-meta)/1.4 var(--sans);
  cursor: pointer;
  box-shadow: 0 2px 10px rgb(0 0 0 / 0.10);
}
.to-latest:hover { color: var(--sky); border-color: var(--sky); }

/* -- the empty state --------------------------------------------------- */

.opening-title {
  margin: 0 0 var(--space-sm);
  font: 700 clamp(1.6rem, 1.2rem + 1.6vw, 2.25rem)/1.15 var(--sans);
  color: var(--ink);
}
.opening-lede {
  margin: 0 0 var(--space-xl);
  max-width: 46ch;
  font: var(--t-ui)/1.6 var(--sans);
  color: var(--ink-soft);
}

/* -- small screens ----------------------------------------------------- */

/* The rail folds away rather than being amputated: the conversation is what
   a phone is for, and the history is a tap away at the top of it. */
@media (max-width: 860px) {
  .ask-shell { grid-template-columns: minmax(0, 1fr); }
  .ask-history {
    border-right: 0;
    border-bottom: 1px solid var(--rule);
    max-height: 40dvh;
  }
  .ask-column { padding-left: var(--space-md); padding-right: var(--space-md); }
}

@media (prefers-reduced-motion: reduce) {
  .ask-scroll { scroll-behavior: auto; }
}


/* -- collapsing the rail ------------------------------------------------ */

/* A chevron, and only a chevron: the rail it points at is right there, and a
   word here would be the widest thing in a column being kept narrow. */
.rail-toggle {
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--ink-faint);
  font: 1.125rem/1 var(--sans);
  cursor: pointer;
  transition: background 120ms var(--ease), color 120ms var(--ease);
}
.rail-toggle:hover {
  background: var(--sunk);
  color: var(--ink);
}

/* The way back in: a drawer handle on the left edge, where the rail went,
   not an orphaned square floating over the conversation. The vertical word
   says what it opens; the chevron says which way it comes. */
.rail-open {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  z-index: 3;
  width: 1.625rem;
  height: auto;
  padding: var(--space-sm) 0;
  display: grid;
  gap: var(--space-2xs);
  place-items: center;
  border: 1px solid var(--rule);
  border-left: 0;
  border-radius: 0 8px 8px 0;
  background: var(--sheet);
  color: var(--ink-soft);
}
.rail-open:hover { color: var(--ink); background: var(--sunk); }
.rail-open-word {
  writing-mode: vertical-rl;
  font: 500 var(--t-label)/1 var(--sans);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.ask-shell[data-rail="open"] .rail-open { display: none; }

@media (max-width: 860px) {
  /* Stacked, the rail collapses upward instead of sideways, and the handle
     sits at the top edge it collapsed into rather than mid-screen. */
  .rail-open {
    top: var(--space-2xs);
    transform: none;
    left: var(--space-2xs);
    border-left: 1px solid var(--rule);
    border-radius: 8px;
    padding: var(--space-2xs) var(--space-xs);
  }
  .rail-open-word { writing-mode: horizontal-tb; }
  .ask-shell[data-rail="closed"] .ask-scroll .ask-column { padding-top: var(--space-2xl); }
  .ask-shell[data-rail="closed"] { grid-template-columns: minmax(0, 1fr); }
  .ask-shell[data-rail="closed"] .ask-history {
    max-height: 0;
    border-bottom: 0;
  }
  .ask-history { transition: max-height 220ms var(--ease); }
}

@media (prefers-reduced-motion: reduce) {
  .ask-shell, .ask-history { transition: none; }
}


/* -- counted facts ------------------------------------------------------ */

/* Numbers the archive counted, shown above the answer that uses them. They are
   deliberately not styled like the answer: this is the database speaking, and
   the difference between a figure that was counted and a figure a model wrote
   is the whole reason for showing it separately. Sans, not the reading serif,
   for the same reason. */
.facts {
  margin: 0 0 var(--space-md);
  padding: var(--space-sm) var(--space-md);
  background: var(--sky-wash);
  border: 1px solid var(--rule);
  border-radius: 10px;
}
.facts-head {
  margin: 0 0 var(--space-2xs);
  font: 500 var(--t-label)/1 var(--sans);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sky-deep);
}
.fact {
  margin: 0;
  font: var(--t-meta)/1.5 var(--sans);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.fact + .fact { margin-top: var(--space-2xs); }

/* M7: the time window navigation and the lines under the result count. */
.window-nav { display: flex; flex-wrap: wrap; gap: var(--space-xs) var(--space-md); margin: 0 0 var(--space-md); font-size: var(--t-meta); }
.window-nav a[aria-current] { color: var(--ink); font-weight: 600; background: var(--sunk); border-radius: 4px; padding: 0 var(--space-2xs) 2px; margin: 0 calc(-1 * var(--space-2xs)); }
.window-line { margin: 0 0 var(--space-xs); font-size: var(--t-meta); color: var(--ink-soft); }

/* M8: collection freshness. Warnings carry ⚠ and words; colour only adds. */
.freshness { margin: 0 0 var(--space-lg); font-size: var(--t-meta); color: var(--ink-soft); }
.freshness-line { margin: 0 0 var(--space-xs); font-size: var(--t-meta); color: var(--ink-soft); }
.fresh-warn { color: var(--rust); font-weight: 600; }
