/* THE PRESTIGE-PRINT TOKEN DICTIONARY. Adopted 2026-09-20 — ops/decisions.md, "the Gemini
   blueprint". The old header said design was out of scope for this slice; it is in scope now.

   The look is a high-end sports ledger or a newspaper, not B2B SaaS: eggshell instead of
   white, stark ink, hard borders, sharp corners, a solid offset shadow instead of a soft
   drop shadow, and MONOSPACE for anything that is a card, a chip count or a sum — because
   chips and cards are tabular data and always were.

   Fonts are SELF-HOSTED (workspace content rules: no fonts.googleapis.com, which is a third
   party watching visitors on a site whose privacy page promises otherwise). Latin subsets
   only, 70KB for both, variable weight so one file covers the range. */

@font-face {
  font-family: 'Playfair Display';
  src: url('/fonts/playfair-display-latin.woff2') format('woff2');
  font-weight: 400 700;
  font-display: swap;
}

@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/jetbrains-mono-latin.woff2') format('woff2');
  font-weight: 400 700;
  font-display: swap;
}

:root {
  /* Grounds. Never pure white — cardstock, not a screen. */
  --bg: #faf9f5;
  --surface: #f4f3ed;
  /* Tiles only. A PLAYING CARD IS WHITE; this is the one place pure white is correct. */
  --card: #fff;

  --ink: #111111;
  --muted: #555555;

  /* TWO BORDER WEIGHTS, and the distinction is load-bearing. `--line-hard` is for
     structural containers — panels, buttons, the things that behave like objects.
     `--line` stays a hairline for rules BETWEEN text. Putting stark ink on every 1px
     border reads as oppressive on a page that is mostly sentences. */
  --line: #d9d6cd;
  --line-hard: #111111;

  /* Felt green, replacing the tech blue. DELIBERATELY DARKER THAN THE #10B981 IN THE
     BLUEPRINT: white on #10B981 measures 1.9:1 and fails AA outright, and this token is
     used as a button fill. #0b6b4f measures 6.4:1 on white and is closer to actual felt. */
  --accent: #0b6b4f;
  --accent-soft: #e6efe9;

  /* Playing-card red. Also darker than the blueprint's #e53935 (3.9:1 on eggshell, under
     AA for text) — #c62828 measures 5.7:1 and still reads as a card suit. */
  --suit-red: #c62828;

  /* Sharp. 2px is the maximum roundness in this system; pills and bubbles are out. */
  --radius: 2px;

  /* Depth is a solid offset, never a blur. */
  --shadow-brutal: 4px 4px 0 var(--ink);

  --serif: 'Playfair Display', Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  --mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', Consolas, 'SF Mono', Menlo, monospace;
  --sans: Inter, -apple-system, 'Segoe UI', system-ui, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 var(--sans);
}

main { max-width: 720px; margin: 0 auto; padding: 32px 20px 64px; }

/* Serif headlines carry the editorial weight; the sans body carries the reading. h3 stays
   sans because at 15px a display serif is decoration, not hierarchy. */
h1 { font-family: var(--serif); font-weight: 700; font-size: 1.875rem; letter-spacing: -0.01em; margin: 0 0 8px; }
h2 { font-family: var(--serif); font-weight: 700; font-size: 1.25rem; margin: 0 0 12px; }
h3 { font-size: 0.9375rem; margin: 0 0 4px; }

.sub { color: var(--muted); margin: 0 0 28px; }
.hint { color: var(--muted); font-size: 0.875rem; margin: 0 0 10px; }

/* A structural container, so it takes the hard border. This is the single change that most
   separates the page from a SaaS card: an object with an edge, not a floating tint. */
.card {
  background: var(--card);
  border: 1px solid var(--line-hard);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 20px;
}

.loading { color: var(--muted); margin: 0; }

/* --- the hand ---------------------------------------------------------- */

.hand-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
/* Card tiles. The SUIT SYMBOL carries the suit; COLOUR is a second signal on top of it, never
   the only one — so the tiles still read in monochrome and for a colour-blind player. Four
   colours rather than two, because telling clubs from spades at 21px on a phone is the read
   itself on boards like hand-001's. Contrast measured on both card faces: 17.8 / 6.5 / 8.2 /
   6.5 on white, worst case 5.26 on the dimmed face. */
.cards { display: inline-flex; gap: 4px; vertical-align: middle; }
.card-tile {
  display: inline-flex;
  align-items: baseline;
  gap: 1px;
  padding: 4px 7px;
  border: 1px solid var(--line-hard);
  border-radius: var(--radius);
  background: var(--card);
  /* Mono. A rank and a suit are data, and the tabular figures stop a board of five tiles
     jittering as the ranks change. */
  font-family: var(--mono);
  font-weight: 700;
  line-height: 1.1;
  box-shadow: none;
}
.card-tile.red { color: #b3261e; }
.card-tile.black { color: #16181d; }
.card-tile.blue { color: #1447b2; }
.card-tile.green { color: #136c37; }
/* The two cards the player is holding are the most poker-looking thing on any of these
   pages, and they were the same size as the board. They lead now. */
.cards.hole .card-tile { font-size: 1.625rem; padding: 9px 12px; border-radius: var(--radius); }
.cards.small .card-tile { font-size: 0.8125rem; padding: 2px 5px; border-radius: var(--radius); }
.card-suit { font-size: .95em; }
.seat, .game { color: var(--muted); font-size: 0.875rem; }
.game { margin: 4px 0 16px; }

/* The hand.
   Laid out as stacked full-width blocks, so nothing sits in a column that a five-card board
   could overflow. The previous version squeezed street, board, action and pot into a grid
   with the board on a fixed 110px, and a turn or river board ran straight over the action
   text. That cannot recur here: no row holds cards and text side by side. */
.hand-view { display: flex; flex-direction: column; gap: 18px; }
.hand-view > h2 { margin: 0; }
.hand-view .game { margin: -14px 0 0; }

/* THE BOARD, ONCE. The marker under each card says which street it arrived on — the job the
   repeated per-street boards used to do, done in five words instead of three extra rows. */
.board-strip { display: flex; flex-direction: column; gap: 6px; }
.strip-label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--muted);
}
.cards.board-cards { display: flex; flex-wrap: wrap; gap: 6px; }
.cards.board-cards .card-tile {
  font-size: 1.375rem;
  padding: 10px 0 9px;
  border-radius: var(--radius);
  width: 46px;
  justify-content: center;
}
.board-marks { display: flex; flex-wrap: wrap; gap: 6px; }
.board-mark {
  width: 46px;
  text-align: center;
  font-size: 0.625rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}

.your-cards { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

.history {
  background: #f4f1ea;
  border-radius: var(--radius);
  padding: 12px 14px;
  margin: 0;
}
.history h3 { margin: 0 0 4px; }
.history p { margin: 0; font-size: 0.9375rem; }

/* The words/shorthand switch. */
.density { display: flex; justify-content: flex-end; margin: -8px 0 10px; }
.density-toggle {
  appearance: none;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 5px 12px;
  min-height: 32px;
  font-size: 0.75rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
}
.density-toggle[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--bg);
}
.density-toggle:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* SHORTHAND hides the scaffolding and nothing else. Never the wait note, never an error, never
   anything the player has to act on — only prose that explains what an experienced reader can
   already see. */
main.shorthand .sub,
main.shorthand #reason-hint,
main.shorthand .pos-last { display: none; }

/* The seats, at the head of the two columns they label. */
.seats { display: flex; align-items: center; gap: 8px; padding-bottom: 2px; }
.seats-gap { flex: 1; }
.seat-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.seat-chip.you { color: var(--accent); }
.btn-disc {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--bg);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0;
}
.pos-last {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.7188rem;
  color: var(--faint, var(--muted));
}

/* The exchange: his moves on one side, yours on the other, and anything that cannot be
   attributed to either of them down the middle. */
.exchange { display: flex; flex-direction: column; }
.street-rule { display: flex; align-items: center; gap: 10px; padding: 13px 0 6px; }
.street-name {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
  flex: none;
}
.street-hair { flex: 1; height: 1px; background: var(--line); }
.street-pot { font-size: 0.8125rem; font-weight: 600; color: var(--muted); flex: none; }

.move { display: flex; margin-bottom: 5px; }
.move .bubble {
  max-width: 80%;
  font-size: 0.875rem;
  line-height: 1.45;
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
}
/* Inline, not stacked: as a block this label added a line to every bubble on the page. It
   stays because alignment and colour say nothing to a screen reader, which gets the moves as
   one flat list and needs each one to name its own actor. */
.move .who {
  font-size: 0.625rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-right: 7px;
}
.move.him { justify-content: flex-start; }
.move.him .bubble { border-bottom-left-radius: 3px; }
.move.you { justify-content: flex-end; }
.move.you .bubble {
  border-bottom-right-radius: 3px;
  background: #eef2fe;
  border-color: var(--accent);
  text-align: right;
}
/* Unattributed moves sit in the middle rather than on a side, because putting them on one
   would be a claim about who made them. */
.move.mid { justify-content: center; }
.move.mid .bubble {
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 0.8125rem;
  padding: 2px 0;
  text-align: center;
  font-style: italic;
}
.move .slot {
  max-width: 80%;
  border: 1px dashed var(--accent);
  border-radius: var(--radius);
  border-bottom-right-radius: 3px;
  padding: 11px 13px;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--accent);
}

/* The bar that keeps the hand on screen after the real one has scrolled away. Its height is
   mirrored by BAR_HEIGHT in app.js, which the scroll maths depends on — change both. */
.hand-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  min-height: 52px;
  max-height: 62vh;
  overflow-y: auto;
  background: rgba(250, 249, 246, .97);
  border-bottom: 1px solid var(--line);
  padding: 7px 20px;
}
/* `hidden` has to beat the layout mode, or the bar ships permanently visible. */
.hand-bar[hidden] { display: none !important; }
.bar-inner {
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.bar-top { display: flex; align-items: center; gap: 9px; }
.bar-gap { flex: 1; }
.bar-board, .bar-you { display: inline-flex; align-items: center; }
/* YOUR cards are HELD, the board is DEALT. The board sits in an even row; your two overlap and
   lift, the way a hand you are holding does. It is the same distinction in every place cards
   appear, and it needs no label to carry it. */
/* The player's own two cards lift off the page — a solid offset, never a blur. */
.bar-you .card-tile { box-shadow: 2px 2px 0 var(--ink); }
.bar-you .card-tile:first-child { transform: rotate(-4deg); }
.bar-you .card-tile:last-child { transform: rotate(3deg); margin-left: -4px; }

.bar-facts {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 0.7188rem;
  color: var(--muted);
}
.bar-odds {
  font-weight: 700;
  color: #8a4b09;
  background: #f7ecdb;
  padding: 1px 5px;
  border-radius: var(--radius);
}
.bar-pos { font-variant: small-caps; letter-spacing: .03em; }

.bar-more > summary {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--accent);
  cursor: pointer;
  list-style: none;
  padding: 2px 0;
}
.bar-more > summary::-webkit-details-marker { display: none; }
.bar-more > summary::before { content: "▸ "; }
.bar-more[open] > summary::before { content: "▾ "; }
.bar-digest {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 4px 0 2px;
  max-height: 34vh;
  overflow-y: auto;
}
.digest-row {
  display: grid;
  grid-template-columns: 52px 46px 1fr;
  gap: 7px;
  font-size: 0.7188rem;
  line-height: 1.35;
  align-items: baseline;
}
.digest-street { text-transform: uppercase; letter-spacing: .07em; color: var(--muted); font-size: 0.625rem; }
.digest-pot { color: #8a4b09; font-weight: 600; }
.digest-act { color: var(--ink); }
.cards.bar-cards { gap: 3px; }
.cards.bar-cards .card-tile {
  font-size: 0.8125rem;
  padding: 3px 5px;
  border-radius: var(--radius);
  box-shadow: none;
}
.bar-street, .bar-price, .bar-none {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
  white-space: nowrap;
}
.bar-price { font-weight: 700; color: var(--ink); }

@media (max-width: 400px) {
  /* The price used to be dropped here, back when the bar was one cramped row. It is not
     droppable: Raj's requirement is that the money is readable WHILE thinking, without
     scrolling. The facts row wraps instead. */
  .hand-bar { padding-left: 14px; padding-right: 14px; }
  .bar-facts { font-size: 0.6875rem; gap: 6px; }
}

.decision { border-top: 2px solid var(--ink); padding-top: 14px; }
.decision p { margin: 0 0 4px; }
.ask-figs { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.ask-big { font-size: 1.625rem; font-weight: 700; letter-spacing: -.01em; }
.ask-odds {
  font-size: 0.8125rem;
  font-weight: 600;
  color: #8a4b09;
  background: #f7ecdb;
  padding: 3px 8px;
  border-radius: var(--radius);
  white-space: nowrap;
}
.legal, .stacks, .price { color: var(--muted); font-size: 0.875rem; }
/* Chip stacks are sums, so they set in mono like every other number in this system.
   Tabular figures matter here specifically: these values change between streets and a
   proportional face makes the column shuffle sideways as they do.

   `.price` IS DELIBERATELY NOT IN THIS RULE. The class means two different things in the
   two stylesheets — the stakes line here, and the whole pricing SECTION on the landing page
   — so adding it set every sentence in that section, terms and all, in monospace. The
   landing page proved it in one screenshot. */
.stacks { font-family: var(--mono); font-variant-numeric: tabular-nums; }

@media (max-width: 520px) {
  .move .bubble, .move .slot { max-width: 88%; }
  .ask-big { font-size: 1.4375rem; }
}

/* --- the input --------------------------------------------------------- */

textarea {
  width: 100%;
  /* NOT `font: … inherit`. On a textarea `inherit` resolves against the element's OWN
     user-agent font, which is monospace — so every transcript box in this app has been
     rendering in monospace, on every page, since this file was written. Found on the coach
     screen 2026-09-17 and fixed here rather than per-page, because it was never a coach
     bug. Named explicitly so a future `font:` shorthand cannot quietly bring it back. */
  font-family: -apple-system, "Segoe UI", system-ui, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  resize: vertical;
  background: #fff;
  color: inherit;
}
textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

.voice-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 12px;
}
.voice-controls[hidden], #discard-recording[hidden], .voice-privacy[hidden] {
  display: none !important;
}
.voice-button { background: var(--accent); }
.voice-button::before { content: "●"; margin-right: 8px; }
.voice-button.recording { background: #b3261e; }
.voice-button.recording::before { content: "■"; }
#voice-status { color: var(--muted); font-size: 0.875rem; }
.voice-privacy { margin-top: -4px; }

.actions { display: flex; align-items: center; gap: 14px; margin-top: 14px; }

/* A pressed, physical control: ink border, sharp corner, uppercase with the letter-spacing
   a newspaper gives a standfirst. The border is not decoration — it is what keeps the shape
   readable when `.primary` swaps the fill to felt green. */
button {
  font: 700 15px/1.2 var(--sans);
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 13px 24px;
  min-height: 44px;
  border: 1px solid var(--line-hard);
  border-radius: var(--radius);
  background: var(--ink);
  color: #fff;
  cursor: pointer;
}
button:disabled { background: var(--muted); cursor: progress; }

#status { color: var(--muted); font-size: 0.875rem; }

/* --- the result -------------------------------------------------------- */

/* The coach's take: the first thing read, and the only thing some players will read. */
.coach { margin: 0 0 20px; }
.coach h2 { margin-bottom: 8px; }
.coach p { margin: 0 0 6px; font-size: 1.0625rem; line-height: 1.5; }

.breakdown-cat { margin: 0 0 18px; }
.breakdown-cat h3 { font-size: 0.875rem; margin: 0 0 6px; }

/* THE TOTAL'S RULES WENT WITH THE NUMBER (Raj, 2026-09-17 — ops/decisions.md). Nothing
   renders .total, .total-n or .total-max any more, on any page. */

.cats { list-style: none; margin: 0; padding: 0; }
.cats > li { padding: 12px 0; border-top: 1px solid var(--line); }
.cat-head { display: flex; justify-content: space-between; gap: 16px; font-size: 0.9375rem; }
.cat-label { font-weight: 600; }
/* WAS .cat-score, and it keeps that styling exactly: the category now carries a word
   ("yes" / "partly" / "not yet") where it used to carry a mark. */
.cat-state { color: var(--muted); white-space: nowrap; }

.detail { margin: 8px 0 0 0; padding-left: 12px; border-left: 3px solid var(--line); }
.detail h4 { margin: 0 0 3px; font-size: 0.8125rem; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em; }
.detail ul { margin: 0; padding-left: 18px; font-size: 0.875rem; }
.detail li { margin: 2px 0; }
.detail.heard { border-left-color: #7a9a6f; }
.detail.gap { border-left-color: #c08a3e; }
.detail.maybe { border-left-color: #b4553f; }
.cost { margin: 6px 0 0; font-size: 0.8125rem; color: var(--muted); }

/* Collapsed detail. Native <details>, so it is keyboard-reachable and announced without
   any JavaScript behind it. Only the LONG lists live in here — never anything that
   explains why a category lost points. */
.more { margin-top: 8px; }
.more > summary {
  cursor: pointer;
  font-size: 0.8125rem;
  color: var(--muted);
  padding: 3px 0;
  min-height: 24px;
}
.more > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.more[open] > summary { margin-bottom: 6px; }
.more .detail { margin-top: 6px; }

.missed { margin-top: 20px; padding-top: 16px; border-top: 2px solid var(--ink); }
.missed p { margin: 0; }

.unscorable { margin: 0; }
.provisional { color: var(--muted); font-size: 0.8125rem; margin: 20px 0 0; }

footer { color: var(--muted); font-size: 0.8125rem; text-align: center; }

/* --- the launch surface: landing, gate, hand navigation ----------------- */
/* Added 2026-09-02 for the Saturday alpha. Same restraint as the rest of the file: this
   is legibility and hierarchy, not a design pass. The one thing it does insist on is
   that the honest section reads as prominently as the sales pitch, because on this
   product that section IS the pitch. */

.lede { margin-bottom: 28px; }
.lede h1 { font-size: 2rem; line-height: 1.2; margin-bottom: 12px; }
.lede .sub { font-size: 1.0625rem; margin-bottom: 20px; }
.lede-actions { flex-wrap: wrap; }

button.primary { background: var(--accent); }
/* Links that act as buttons. Same target size as a real one — 44px, thumb-sized. */
.primary-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 12px 24px;
  border-radius: var(--radius);
  background: var(--ink);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
}
.ghost {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--muted);
  text-decoration: underline;
}
.primary-link:focus-visible, .ghost:focus-visible, button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.plain { margin: 0; padding-left: 20px; }
.plain li { margin: 0 0 8px; }
.spaced { margin-top: 22px; }

/* The "what you are actually buying" block. Marked rather than tucked away: it is the
   section a buyer is most likely to be annoyed about not having read. */
.plain-truth { border-left: 4px solid var(--ink); }

input[type="text"] {
  font: 16px inherit; /* 16px exactly — anything smaller makes iOS zoom on focus. */
  padding: 12px 14px;
  min-height: 44px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  color: inherit;
  flex: 1 1 180px;
  min-width: 0;
}
input[type="text"]:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ONE SCROLLABLE ROW, not a wrapping block. At fifteen hands this wrapped to three rows on
   desktop and four on a phone, so the pills pushed the hand itself below the fold before a
   player had read anything. Matches the coach page's strip. */
.hands {
  display: flex;
  gap: 6px;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: thin;
  scroll-snap-type: x proximity;
  margin-bottom: 16px;
  padding-bottom: 6px;
}
.hands .hand-link { flex: 0 0 auto; scroll-snap-align: start; }

/* FIFTEEN PILLS IN A 375px VIEWPORT. Roughly 1,350px of row in a 375px window, so twelve hands
   sit off-screen and nothing said so — the row ended mid-word ("Hand 4, Ha…") and read as
   broken rather than scrollable. Found in the 2026-09-18 CET at phone width; the scrolling
   itself always worked.

   A MASK, not an overlay element: it needs no extra node, cannot intercept a tap on the pill
   underneath, and degrades to today's hard edge where unsupported.

   Scoped to narrow widths on purpose. The row does not overflow on a desktop, and a permanent
   fade over a row that fits would be signalling content that is not there. */
@media (max-width: 640px) {
  .hands {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
  }
}
.hand-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  font-size: 0.875rem;
  font-weight: 600;
  text-decoration: none;
}
.hand-link.current { background: var(--ink); color: #fff; border-color: var(--ink); }

/* A TOP RULE, NOT A LEFT ACCENT BAR — the same correction made to .plain-truth on the landing
   page. design-brain.md names "rounded-card-with-left-accent-border (the shadcn default)" as an
   anti-pattern to never ship, and this one sat on the TRAINER: the page a paying player
   actually uses. Fixing it on the marketing page and leaving it here would have been the
   half-repair this repo keeps recording. */
.gate { border-top: 3px solid var(--accent); }
.gate .actions { flex-wrap: wrap; }

.checking { font-size: 1.5rem; }

footer a { color: var(--muted); }

/* Visible to a screen reader, not to the eye. For the label on the code box, where a
   visible label beside a placeholder would just be the same word twice. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --- the player loop ---------------------------------------------------- */
/* Added 2026-09-02: the result needs somewhere to go next, and the whole thing has to
   work at a width where a phone keyboard is already taking half the screen. */

.hand-count { color: var(--muted); font-size: 0.8125rem; margin: -14px 0 24px; }

/* The two ways forward, under the result. Separated from the score above so they read as
   "what now" rather than as part of the breakdown. */
.result-actions {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  flex-wrap: wrap;
  gap: 10px;
}

/* "Try this hand again" is a real <button> because it does something on this page rather
   than going anywhere. Quieter than the primary action, same 44px target. */
button.secondary {
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--line);
}
button.secondary:hover { border-color: var(--ink); }

/* --- narrow phones ------------------------------------------------------ */
/* 375px is the floor this is designed for, and at that width the old padding plus the
   card border left the transcript box under 300px wide. */
@media (max-width: 430px) {
  main { padding: 20px 14px 48px; }
  .card { padding: 16px 14px; border-radius: var(--radius); }

  /* The hand strip runs to the screen edge so it reads as scrollable rather than clipped. */
  .hands { margin-left: -14px; margin-right: -14px; padding-left: 14px; padding-right: 14px; }

  h1 { font-size: 1.5rem; }
  .lede h1 { font-size: 1.625rem; }

  /* Full-width, stacked, thumb-reachable. Side-by-side at this width gives two buttons
     that are each too narrow to read and too close together to hit. */
  .actions { flex-direction: column; align-items: stretch; gap: 10px; }
  .actions button,
  .actions .primary-link,
  .actions .ghost { width: 100%; justify-content: center; text-align: center; }
  /* The status line reads as a caption under the button rather than a squeezed column. */
  #status { text-align: center; }

  .voice-controls { align-items: stretch; }
  .voice-controls button { width: 100%; }
  #voice-status { text-align: center; }

  /* The board is the one thing here with a real risk of pushing the page sideways: five
     card tiles in a row inside a fixed grid column. `.board` already wraps; the tiles
     themselves did not, so a five-card river could still overflow its cell. The street
     layout above this breakpoint is already handled at 520px — nothing is restated here.
     A page that scrolls horizontally on a phone is the bug players notice first. */
  .cards { flex-wrap: wrap; }
  .card-tile { flex: 0 0 auto; }

  .cat-head { font-size: 0.875rem; }
}

/* --- the wait ----------------------------------------------------------- */
/* Grading takes as long as it takes. The page's job is to make that legible: something
   moving, a count, and a change of message if it runs long. */

.progress { display: inline-flex; align-items: center; gap: 8px; }

/* THE HIDDEN STATE HAS TO WIN, EXPLICITLY.
   The browser's own `[hidden] { display: none }` is a UA rule, so ANY author rule setting
   `display` beats it — including the one directly above. The result was a spinner that never
   went away: the markup carried `hidden`, JavaScript set `hidden = true` on every completion
   path, and the element stayed on screen anyway, next to a button that had finished. Found
   in Raj's first saved-progress pilot, 2026-09-02.
   `.progress[hidden]` outranks `.progress` on specificity, so this holds wherever it sits. */
.progress[hidden] { display: none !important; }

/* The wait note, same treatment. A <p> is block by default so the UA rule would hold on its
   own — but "it would have been fine anyway" is what was true of the spinner too, right up
   until an author rule was added above it. Stated explicitly so it stays true. */
.wait-note { margin: 10px 0 0; }
.wait-note[hidden] { display: none !important; }

.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* Motion is a preference some people set for a medical reason. The indicator still has to
   indicate, so it pulses in place instead of spinning. */
@media (prefers-reduced-motion: reduce) {
  /* IT STILL HAS TO INDICATE. `animation: none` would be the easy reading of the
     preference and the wrong one: the person who set it still needs to know something is
     happening. Spinning is replaced by a slow opacity pulse — no movement, no rotation,
     still alive. The ring keeps its accent arc so it does not read as a static dot. */
  .spinner { animation: pulse 1.6s ease-in-out infinite; border-top-color: var(--accent); }
  @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
}

/* Tabular figures so the number does not jitter the line as it counts past 9. */
.elapsed {
  color: var(--muted);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  min-width: 3ch;
}

/* The example thought, inside the coach's take. Quoted and set apart, because it is a
   sentence the player might have said rather than a sentence the app is asserting. */
.coach p.example {
  border-left: 3px solid var(--line);
  padding-left: 12px;
  color: var(--ink);
}

/* --- accounts, consent and progress ------------------------------------- */

.account-bar { margin: 0 0 12px; font-size: 0.8125rem; min-height: 20px; }
.account-link { color: var(--accent); }

/* The consent control. The checkbox is 20px and the whole row is a hit target, because a
   consent decision must not be a thing you miss with your thumb. */
.consent-row { display: flex; align-items: flex-start; gap: 10px; margin: 4px 0 8px; }
.consent-row input[type="checkbox"] {
  width: 20px;
  height: 20px;
  margin: 2px 0 0;
  flex: 0 0 auto;
  accent-color: var(--accent);
}
.consent-row label { cursor: pointer; }

/* Destructive, and it looks it. Not red-on-red — the border carries the warning so the
   label stays readable, including for a colour-blind reader. */
button.danger {
  background: var(--card);
  color: #b3261e;
  border: 1px solid #b3261e;
  font-weight: 600;
}
button.danger:hover { background: #fdf3f2; }

/* The one thing to work on. Same shape as the early signal below it, and first on the page,
   because it is what somebody opens this page to find out. */
.leak { margin-bottom: 20px; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
.leak h3 { font-size: 0.875rem; margin: 0 0 6px; }
.leak-name { margin: 0 0 4px; font-size: 1.0625rem; font-weight: 600; }

.signal { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line); }
.signal h3, .recent h3 { font-size: 0.875rem; margin: 0 0 6px; }
.recent { margin-top: 20px; }

/* What he did, street by street, on one wrapping line. The evidence the player reasons from,
   so it sits in the bar itself rather than behind the digest's disclosure. */
.bar-story {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 9px;
  font-size: 0.7188rem;
  line-height: 1.4;
}
.story-who {
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.story-item { display: inline-flex; align-items: baseline; gap: 4px; }
.story-street {
  font-size: 0.5938rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
}
.story-act { color: var(--ink); }

/* The hand counter and the way onward, on one line. */
.hand-count { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.next-hand {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--accent);
  white-space: nowrap;
  padding: 6px 0;
  min-height: 32px;
  display: inline-flex;
  align-items: center;
}

/* --- accessibility corrections, 2026-09-19 audit --------------------------- */

/* Your cards get a caption like the board does, so they stack rather than sit in a row. */
.your-cards { flex-direction: column; align-items: flex-start; gap: 6px; }

/* 44px is the floor for a touch target. The pill stays visually small; the padding does the
   reaching, so the look does not change and the thumb still lands. */
.density-toggle { min-height: 44px; padding: 11px 14px; }
footer a { display: inline-block; padding-block: 12px; }

/* The fourteen most-tabbed controls on the page were taking the browser default ring, which
   sits on top of an existing 1px border and reads as "slightly darker", not "focused". */
.hand-link:focus-visible,
.next-hand:focus-visible,
footer a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius);
}

/* At 200% browser zoom the cockpit grew to 60% of the viewport and sheared the hole cards off
   the right edge. It scrolls inside itself now, and the row may shrink rather than overflow. */
.hand-bar { max-height: 34vh; }
.bar-top { min-width: 0; flex-wrap: wrap; }
.bar-you, .bar-board { min-width: 0; flex-wrap: wrap; }

/* --- 2026-09-19 UX pass ---------------------------------------------------- */

/* The fixed cockpit was covering whatever the browser scrolled to. "Start recording" sat
   underneath it and the tap landed on the bar, so the microphone -- the low-friction way in
   for somebody who freezes at a blank box -- was unclickable. */
html { scroll-padding-top: 150px; }
#reason, #hand-detail, #result { scroll-margin-top: 150px; }

/* Opaque. At .97 the page text ghosted through it and the "$337 to call" heading was sliced in
   half at the bar's edge. */
.hand-bar { background: var(--bg); }

/* The cockpit is read while thinking, so it stops being the smallest type on the page. */
.bar-facts { font-size: 0.8125rem; }
.bar-price { font-size: 0.8438rem; }
.bar-story, .digest-row { font-size: 0.7812rem; }
.story-street, .digest-street { font-size: 0.6875rem; }
.bar-street, .story-who { font-size: 0.7188rem; }

/* SHORTHAND drops the wordy tail and KEEPS the seats. Hiding the whole line removed position
   from the cockpit entirely -- for the only person who turns shorthand on. */
main.shorthand .pos-tail { display: none; }

/* His line, restated above the answer box. */
.page-story { padding-top: 2px; }
#hand-detail .exchange { margin-top: -4px; }

/* WHAT HAPPENED, one row per street. Streets and pots hold their own column so the eye can run
   down them; the moves sit in order on one line, his and yours told apart by colour rather than
   by a repeated name. */
.street-table { display: flex; flex-direction: column; gap: 2px; }
.st-row {
  display: grid;
  grid-template-columns: 86px 1fr;
  gap: 4px 10px;
  align-items: baseline;
  padding: 5px 0;
  border-top: 1px solid var(--line);
}
.st-row:first-child { border-top: 0; }
.st-left { display: flex; align-items: baseline; gap: 7px; }
.st-name {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}
.st-pot { font-size: 0.7812rem; font-weight: 700; color: #8a4b09; }
.st-seq { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 6px; font-size: 0.8438rem; }
.st-dot { color: var(--line); }
.st-move.you { color: var(--accent); }
.st-move.mid { color: var(--muted); font-style: italic; }
.st-who { font-size: 0.625rem; letter-spacing: .09em; text-transform: uppercase; opacity: .75; }

@media (max-width: 400px) {
  .st-row { grid-template-columns: 1fr; gap: 1px; padding: 6px 0; }
}

/* THE HAND AS TWO COLUMNS. Chess game review, not a poker replayer: one column per player, one
   row per move, the money running down the right. Three ways to read one table. */
.ht {
  display: grid;
  grid-template-columns: 58px 1fr 1fr 48px;
  column-gap: 8px;
  align-items: baseline;
  font-size: 0.8438rem;
}
.ht-h {
  font-size: 0.6562rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  padding-bottom: 5px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
}
.ht-h.ht-y { color: var(--accent); }
.ht-h.ht-pot { justify-content: flex-end; }
.ht-last {
  font-size: 0.5938rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  opacity: .8;
}
main.shorthand .ht-last { display: none; }

.ht > div { padding: 3px 0; }
.ht-rule { grid-column: 1 / -1; border-top: 1px solid var(--line); padding: 0 !important; }
.ht-street {
  font-size: 0.6562rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
}
.ht-v .ht-move { color: var(--ink); }
.ht-y .ht-move { color: var(--accent); }
.ht-move.ht-none { color: var(--muted); font-style: italic; }
.ht-pot { text-align: right; font-weight: 700; color: #8a4b09; font-size: 0.7812rem; }

@media (max-width: 400px) {
  .ht { grid-template-columns: 50px 1fr 1fr 44px; column-gap: 6px; font-size: 0.8125rem; }
}

/* Skip link: visible only when focused, and it has to sit above the fixed cockpit. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 40;
  background: var(--ink);
  color: var(--bg);
  padding: 12px 16px;
  border-radius: 0 0 var(--radius) 0;
  font-size: 0.875rem;
}
.skip-link:focus { left: 0; }

/* --- DESKTOP: the hand and the answer side by side ------------------------------------
   At 1440x900 this page was the phone layout with 760px of dead space: a 680px column, 2.6
   screens of scrolling and a pinned cockpit, inside a window where half the pixels were empty.
   Scoped to #page so the landing, coach and sign-in pages that share this stylesheet are
   untouched. */
@media (min-width: 1000px) {
  main#page {
    max-width: 1180px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: 28px;
    align-items: start;
  }
  main#page > #gate { grid-column: 1 / -1; }
  main#page > #hand { grid-column: 1; margin-bottom: 0; }
  main#page > #reason { grid-column: 2; }
  main#page > #result { grid-column: 2; }
  main#page > #hand-detail { grid-column: 1 / -1; }

  /* Nothing scrolls away, so there is nothing for a pinned cockpit to rescue. */
  .hand-bar { display: none !important; }

  /* The textarea no longer has to be tall enough to survive a scroll away from the hand. */
  #reason textarea { min-height: 260px; }
}

/* The hand strip bleeds to the screen edge so the pills do not stop short of it. Bleeding on the
   RIGHT as well made the document 14px wider than the viewport, which is a horizontal scroll on
   the whole page at 375px — measured: scrollWidth 389 against clientWidth 375, and removing this
   one margin put it back to 375. The left bleed does the visual job on its own. */
.hands { margin-right: 0; }
