/* Finish the Line — the press design, tokens verbatim from the handoff.
   Square corners throughout; pills are the only rounded thing. */

:root {
  --ink: #14120f;
  --paper: #fbfaf7;
  --card: #ffffff;
  --muted: #5c584f;
  --muted-2: #6b6862;
  --muted-3: #8d8880;
  --rule: #e4e0d8;
  --rule-light: #eae6dd;
  --rule-lighter: #f0ece3;
  --border-idle: #d9d4ca;
  --blue: #1a5fd0;
  --green: #0f7a3d;
  --green-deep: #0b4a26;
  --green-surface: #eaf6ee;
  --green-surface-2: #f4fbf6;
  --green-border-soft: #9fd6b2;
  --green-chip: #d6efdf;
  --red: #b3261e;
  --red-deep: #7c1a15;
  --red-surface: #fdecec;
  --dim-surface: #faf8f4;
  --dim-border: #ebe7de;
  /* ⚠️ WAS #a49f96, which measured 2.52:1 on paper -- under the 4.5:1 AA floor
     for body text, and the last accessibility failure on the site. His call to
     fix it. #76726c is the LIGHTEST value on the same warm grey that clears
     4.5:1 on all three grounds it sits on (paper 4.58, card 4.78, dim 4.51),
     so the disclaimer stays as washed out as it can be while still being
     readable. Used by the disclaimer and by an eliminated option mid-round. */
  --dim-text: #76726c;
  --chip-idle: #f1ede4;
  --blank-fill: #eef3ff;
  --btn-hover: #f4f1ea;

  --sans: "Fira Sans", Helvetica, Arial, sans-serif;
  --display: "Public Sans", Helvetica, Arial, sans-serif;
  --serif: Literata, Georgia, serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
}

.wrap { max-width: 1000px; margin: 0 auto; padding: 0 clamp(14px, 4vw, 24px) 72px; }
[hidden] { display: none !important; }

/* ---------------------------------------------------------------- top bar */

.topbar { background: var(--card); border-bottom: 1px solid var(--rule); }
.topbar__row {
  max-width: 1000px; margin: 0 auto;
  padding: 14px clamp(14px, 4vw, 24px);
  display: flex; align-items: center; gap: clamp(8px, 2.5vw, 14px); flex-wrap: wrap;
}
.wordmark {
  font-family: var(--display); font-weight: 700; font-size: 18.5px;
  letter-spacing: -.015em; white-space: nowrap;
  display: inline-flex; align-items: flex-end; gap: 4px;
}
.wordmark__blank { display: inline-flex; align-items: flex-end; gap: 4px; }
.wordmark__bar { display: block; width: 36px; height: 2.8px; background: var(--ink); }
.wordmark__dot {
  display: block; width: 6.5px; height: 6.5px; border-radius: 999px;
  animation: caret 1.15s steps(1, end) infinite, dotHue 4.6s steps(1, end) infinite;
}

/* hero-scale wordmark.
   ⛔ `display: flex`, NOT the inline-flex it inherits. The block `<p>` that used
   to follow it was the only thing keeping Play on its own line; with the subhead
   gone, an inline-flex h1 let the button flow up beside the wordmark. The
   heading owns its line, and its own bottom margin is the gap above Play. */
.wordmark--hero { display: flex; font-size: clamp(30px, 8vw, 42px);
  letter-spacing: -.025em; line-height: 1;
  justify-content: center; gap: 14px; flex-wrap: wrap; }
.wordmark--hero .wordmark__blank { gap: 8px; padding-bottom: 4px; }
.wordmark--hero .wordmark__bar { width: clamp(58px, 16vw, 82px); height: 4.5px; }
.wordmark--hero .wordmark__dot { width: 11px; height: 11px; }

/* ----------------------------------------------------------------- shared */

.card {
  background: var(--card); border: 1px solid var(--rule); border-radius: 0;
  box-shadow: 0 20px 50px -30px rgba(20, 18, 15, .35);
}
.eyebrow {
  font-size: 11.5px; font-weight: 600; letter-spacing: .22em;
  text-transform: uppercase; color: var(--blue);
}
.eyebrow--quiet { letter-spacing: .2em; color: var(--muted-2); }

.btn {
  font-family: var(--sans); font-size: 17.5px; font-weight: 600;
  border-radius: 999px; cursor: pointer;
  transition: transform .16s cubic-bezier(.2, 1.5, .35, 1), background .16s ease;
}
.btn--primary { padding: 19px 40px; min-width: 230px; background: var(--ink); color: #fff; border: none; }
.btn--primary:hover { transform: translateY(-2px) scale(1.02); background: #000; }
.btn--primary:active { transform: translateY(1px) scale(.985); }
.btn--secondary { padding: 13px 26px; background: #fff; color: var(--ink); border: 1px solid var(--ink); }
.btn--secondary:hover { background: var(--btn-hover); }

.screen { animation: riseIn .45s cubic-bezier(.2, .9, .25, 1) both; }

/* ------------------------------------------------------------------ lobby */

.title-row {
  padding: 34px 0 24px; border-bottom: 1px solid var(--rule);
  display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap;
}
.title-row h1 {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: clamp(27px, 7vw, 36px); line-height: 1.1; letter-spacing: -.02em;
}
.title-row .date { font-size: 17px; color: var(--muted); }

.hero { margin-top: 32px; text-align: center;
  padding: clamp(34px, 7vw, 64px) clamp(18px, 5vw, 40px) clamp(32px, 6vw, 56px); }
.hero .eyebrow { display: block; margin-bottom: 18px; }
/* `.hero__subhead` deleted 2026-09-12 with the sentence it styled. The h1's own
   bottom margin is what now separates the wordmark from Play. */
.hero__date { font-size: 14.5px; font-weight: 600; margin-top: 26px; }
/* The one rule the lobby states, under the button it governs. */
.hero__foot { font-size: 14.5px; color: var(--muted); margin: 10px 0 0; }

.stats {
  max-width: 520px; margin: 38px auto 0; padding-top: 24px;
  border-top: 1px solid var(--rule-light);
  /* One column per cell, however many there are: two since 2026-09-11, when
     Best score went with the points. A fixed three left a blank third. */
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
}
.stat { padding: 0 10px; }
/* ⛔ ONE SIZE, since 2026-09-12. There were two -- 10.5/22px here and 11.5/25px
   under /account -- and the second won only by sitting later in the file. The
   lobby's centred grid is gone with the points, so these are the /account
   values and the only ones. `display: block` matters: /account writes its cells
   as spans, and without it the label, the number and the note run together. */
.stat__label {
  display: block; font-size: 11.5px; font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted-2);
}
.stat__value { display: block; font-family: var(--display); font-size: 25px; font-weight: 700;
  line-height: 1.1; margin: 6px 0; font-variant-numeric: tabular-nums; }
/* ⚠️ --muted-2. --muted-3 measures 3.51:1 here, under AA, and Lighthouse
   flagged ten of these on the game screens. */
.stat__note { display: block; font-size: 12px; color: var(--muted-2); }

/* ------------------------------------------------------------------ arena
   ⭐ THE ROUND IS A READING PAGE, his call 2026-09-12: the same furniture an
   episode page uses. No card, no HUD row, no section headings -- a crumb line,
   a title row whose rule is the progress, the scene, the lines, the blank, and
   the three options as hairline rows. One family reads: Literata. */

/* One small-caps label, shared. ⛔ The deleted arena block held this rule for
   `.miss__badge` and `.panel__who` too -- both sit on the results screen, and
   both rendered as 16px plain sans without it. `.dialogue__speaker` and
   `.strip__label` are gone from the markup and are not restored. */
.panel__who,
.miss__badge,
.option.is-answer .option__mark {
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.round__crumbs { padding: 26px 0 0; margin: 0; font-size: 13.5px; color: var(--muted-2); }
/* The rule below it is the progress bar, so the row itself draws none. */
.title-row--flush { padding: 14px 0 20px; border-bottom: none; }

.bar { width: 100%; background: var(--rule-light); }
.bar--progress { height: 1px; margin-bottom: 36px; }
.bar__fill { height: 100%; background: var(--ink); }
.bar--progress .bar__fill { transition: width .4s ease; }

.round { margin-top: 30px; }

/* ⚠️ WAS --blue AND WAS FIRA SANS. A stage direction is prose nobody can
   click; Literata italic separates it from the dialogue by style rather than
   by hue, and 17px keeps it under the lines it introduces. */
.scene { font-family: var(--serif); font-style: italic; font-size: 17px;
  color: var(--muted-2); margin: 0 0 22px;
  line-height: 1.45; text-wrap: pretty; max-width: 34em; }

/* A line of the script: the speaker in the line, not in a column beside it.
   19px/1.7 is the episode page's measure for its beats, which is the page this
   one is modelled on. */
.line { font-family: var(--serif); font-size: 19px; line-height: 1.7; color: var(--ink);
  margin: 0 0 .8em; max-width: 34em; text-wrap: pretty; }
.line strong { font-weight: 700; }
.line--blank { display: flex; align-items: flex-end; gap: 12px; }
.line--blank strong { color: var(--blue); }

/* ⭐ THE ANSWERED LINE. The blank becomes the words it was standing in for,
   set exactly like the three lines above it -- same face, same measure, same
   speaker-then-text shape -- so the dialogue reads as having finished rather
   than as having been marked. Colour carries the verdict, his call: green on a
   hit, red on a miss. Both are over the AA floor on paper by a wide margin
   (--green-deep 9.95:1, --red-deep 9.98:1 measured), and neither is the only
   signal -- the tick, the cross and the live region all say it too. */
.line--filled { animation: fillIn .26s ease both; }
.line--filled.is-right, .line--filled.is-right strong { color: var(--green-deep); }
.line--filled.is-wrong, .line--filled.is-wrong strong { color: var(--red-deep); }

/* ⛔ THE BLANK IS THE WORDMARK'S OWN DEVICE. `align-items: flex-end` is what
   makes it an underscore rather than a dash, and the 6px lift is the same one
   the mark uses. The dot carries both wordmark animations: it blinks like a
   caret and cycles the four hues. */
.blank { display: flex; align-items: flex-end; gap: 8px; padding-bottom: 6px; }
.blank__bar { display: block; width: 82px; height: 2.8px; background: var(--ink); }
.blank__dot {
  display: block; width: 6.5px; height: 6.5px; border-radius: 999px;
  animation: caret 1.15s steps(1, end) infinite, dotHue 4.6s steps(1, end) infinite;
}

/* The options are rows, like everything else a page lists. 56px of height for
   a thumb; nothing changes width when one is pressed, so nothing shifts. */
.options { margin-top: 34px; border-top: 1px solid var(--rule); }
.option {
  display: flex; align-items: baseline; gap: 14px; width: 100%;
  padding: 16px 2px; min-height: 56px; text-align: left; cursor: pointer;
  background: transparent; border: none; border-bottom: 1px solid var(--rule-light);
  color: var(--ink); transition: background .18s ease, color .18s ease;
}
/* ⛔ THE ANSWERED BOARD LETS TAPS THROUGH. A disabled button dispatches no
   click at all in Chrome and Safari, so during the reveal the three options --
   the biggest target on the page, and the one the finger has just been on --
   swallowed every tap meant to move the round on. Giving up pointer events
   hands the tap to the row behind them, which is where the skip listens. */
.option:disabled { pointer-events: none; }

@media (hover: hover) {
  .option:hover:not(:disabled) { background: var(--btn-hover); }
  .miss__trigger:hover { opacity: .62; }
}
/* ⚠️ --muted-2, not --muted-3: at 19px regular the lighter grey measures
   3.37:1 on paper, under the 4.5:1 AA floor. 4.75:1 here. */
.option__letter { flex: none; font-family: var(--serif); font-size: 19px; color: var(--muted-2); }
.option__text { flex: 1; font-family: var(--serif); font-size: 19px; line-height: 1.7;
  text-wrap: pretty; max-width: 34em; }
.option__mark { flex: none; margin-left: auto; align-self: center; }
.option svg { width: 20px; height: 20px; stroke-width: 2.6; animation: popTick .3s ease both; }

/* ⚠️ Answered states are INK, not fills. A filled slab in a row of hairlines
   was the card's idiom; the colour is the same, it just lands on the type. */
.option.is-correct, .option.is-correct .option__letter { color: var(--green-deep); }
.option.is-correct .option__mark { color: var(--green); }
.option.is-wrong, .option.is-wrong .option__letter { color: var(--red-deep); }
.option.is-wrong .option__mark { color: var(--red); }
.option.is-answer, .option.is-answer .option__letter { color: var(--green-deep); }
.option.is-answer .option__mark { color: var(--green); }
.option.is-dim, .option.is-dim .option__letter, .option.is-dim .option__text { color: var(--dim-text); }

.arena.is-shaking { animation: shakeX .45s cubic-bezier(.36, .07, .19, .97) both; }

/* ---------------------------------------------------------------- results */

/* ⭐ A PAGE, NOT A CARD, since 2026-09-12. The centred slab with a 38px verdict
   on it became a title row like every other page's, and the four-cell strip
   became one score beside the sentence that reads it. */

.score { display: flex; align-items: flex-end; gap: 40px; flex-wrap: wrap;
  padding: 26px 0; border-bottom: 1px solid var(--rule-light); }
.score__label { display: block; font-size: 11.5px; font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted-2); }
/* --display, matching the row stat on /account: the same component, and a
   figure stated as a result is a heading's job, not body text's. */
.score__value { display: block; font-family: var(--display); font-size: 32px; font-weight: 700;
  line-height: 1; margin: 8px 0; font-variant-numeric: tabular-nums; }
/* `.score__note` deleted 2026-09-12 with the "lines finished" it styled: the
   heading above the number already names the unit. */
/* A sentence, so it is set in the reading face like every other sentence. */
.score__lead { font-family: var(--serif); font-size: 18px; line-height: 1.45;
  color: #2b2823; margin: 0; max-width: 34em; }

.miss { border-bottom: 1px solid var(--rule-light); }
.miss__trigger {
  display: flex; align-items: center; gap: 14px; width: 100%;
  padding: 16px 2px; background: none; border: none; cursor: pointer;
  font-family: var(--sans); font-size: 16px; text-align: left; color: var(--ink);
}
.miss__badge {
  flex: none;
  color: var(--red); background: var(--red-surface); padding: 4px 10px; border-radius: 999px;
}
.miss__scene { flex: 1 1 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.miss__scene em { font-family: var(--serif); font-style: italic; }
.miss__chevron { flex: none; transition: transform .2s ease; }
.miss[open] .miss__chevron { transform: rotate(180deg); }
.miss__body { padding: 2px 2px 22px; }
/* Same change as `.scene`, on the results screen's copy of it. */
.miss__scene-full { font-family: var(--serif); font-style: italic; font-size: 15.5px;
  color: var(--muted-2); margin-bottom: 12px; }
.miss__line { font-family: var(--serif); font-size: 16px; line-height: 1.5; color: var(--muted);
  margin: 0 0 6px; max-width: 30em; }
.panel { padding: 13px 14px; margin-top: 8px; }
.panel--right { background: var(--green-surface); border-left: 3px solid var(--green); }
.panel--right .panel__who { color: var(--green); }
.panel--right .panel__text { color: var(--green-deep); }
.panel--wrong { background: var(--red-surface); border-left: 3px solid var(--red); }
.panel--wrong .panel__who { color: var(--red); }
.panel--wrong .panel__text { color: var(--red-deep); text-decoration: line-through; }
.panel__text { font-family: var(--serif); font-size: 16.5px; line-height: 1.5; margin-top: 4px; }

/* ⭐ The share block earns its width, his call 2026-09-12: the grid and the
   button on one side, and on the other the message exactly as it will be sent.
   One button -- Share result -- since the browser's own sheet offers copying. */
.share__grid { display: flex; flex-wrap: wrap; gap: 40px; padding-top: 26px; }
.share__main { flex: 1 1 320px; }
.share__marks { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 16px; }
.mark { width: 22px; height: 22px; }
.mark--hit { background: var(--green); }
.mark--miss { background: #fff; border: 2px solid var(--red); }
.share__note { font-family: var(--serif); font-size: 15.5px; line-height: 1.5; color: #2b2823;
  margin: 0 0 20px; max-width: 32em; }
.share__preview { flex: 1 1 320px; background: var(--card); border: 1px solid var(--rule);
  padding: 20px 22px; }
.share__preview .eyebrow { display: block; margin-bottom: 12px; }
/* ⚠️ `pre-line`, because this is the real message: its line breaks are the
   ones the grid and the link arrive on. */
.share__text { font-family: var(--serif); font-size: 15.5px; line-height: 1.6; color: #2b2823;
  margin: 0; white-space: pre-line; word-break: break-word; }


/* ------------------------------------------------------------------- done */

/* The returning player's page: the same title row, the same rows. */
.done__body { font-family: var(--serif); font-size: 18px; line-height: 1.5;
  color: #2b2823; margin: 22px 0 0; max-width: 34em; }
.recap { margin-top: 26px; padding-bottom: 26px; border-bottom: 1px solid var(--rule-light); }
.recap__line { font-family: var(--serif); font-size: 15.5px; color: #2b2823; margin: 0; }
.actions { margin-top: 28px; display: flex; gap: 10px; flex-wrap: wrap; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.share__fallback {
  display: block; width: 100%; margin: 0 0 14px; padding: 10px 12px;
  font-family: var(--serif); font-size: 15px; line-height: 1.5;
  color: var(--ink); background: #fff; border: 1px solid var(--border-idle);
  border-radius: 0; resize: none;
}

/* -------------------------------------------------------------- messaging */

.notice { max-width: 640px; margin: 56px auto 0; text-align: center; padding: 40px 24px; }
.notice p { color: var(--muted); font-size: 16px; }

/* ------------------------------------------------- narrow: the phone round */

@media (max-width: 640px) {
  /* The progress rule stays in view; there is no HUD row to stick since the
     round became a reading page. */
  .arena .bar--progress { position: sticky; top: 0; z-index: 5; background: var(--paper); }

  /* The round has no card and no column to narrow now; the lines simply get
     the phone's own measure. */
  .wrap { padding-left: 12px; padding-right: 12px; }
  .line, .option__text { font-size: 18px; }
  .scene { font-size: 16.5px; margin-bottom: 16px; }
  .bar--progress { margin-bottom: 20px; }
  .option { padding: 14px 2px; gap: 12px; }

  /* D3: 19 of 52-128 characters is not an identification. The badge is fixed
     width and was eating the row, so the scene goes on its own line under it. */
  .miss__trigger { flex-wrap: wrap; }
  .miss__badge { order: 1; }
  .miss__chevron { order: 2; margin-left: auto; }
  .miss__scene { order: 3; flex: 1 0 100%; white-space: normal; }

  /* Three marks fit any phone; the 12px rule here was for twenty of them. */
  .share__marks { gap: 5px; }

  /* The share block stacks: the preview goes under the button rather than
     beside it. */
  .share__grid { gap: 26px; }
}

/* ------------------------------------------------------------- animations */

@keyframes caret { 0%, 45% { opacity: 1 } 50%, 95% { opacity: .12 } 100% { opacity: 1 } }
@keyframes dotHue {
  0%, 24% { background: #e0202a } 25%, 49% { background: #f2c00e }
  50%, 74% { background: #1a5fd0 } 75%, 100% { background: #7b3fa0 }
}
@keyframes riseIn { from { transform: translateY(14px); opacity: 0 } to { transform: none; opacity: 1 } }
@keyframes shakeX {
  0%, 100% { transform: translateX(0) } 15% { transform: translateX(-9px) }
  30% { transform: translateX(7px) } 45% { transform: translateX(-4px) }
  60% { transform: translateX(3px) } 80% { transform: translateX(-1px) }
}
@keyframes fillIn {
  from { opacity: 0; transform: translateY(5px) } to { opacity: 1; transform: none }
}
@keyframes popTick {
  0% { transform: scale(.7); opacity: 0 } 60% { transform: scale(1.06); opacity: 1 }
  100% { transform: scale(1) }
}

@media (prefers-reduced-motion: reduce) {
  /* ⚠️ THE ANIMATIONS GO, THE PAUSE STAYS. A three-second hold is not motion;
     it is reading time, and the reader who turned motion off needs it just as
     much. Only the movement is dropped -- the filled line still appears, it
     simply does not rise into place. */
  .screen, .arena.is-shaking, .option svg, .line--filled,
  .wordmark__dot, .blank__dot { animation: none !important; }
  /* Still visible, just still. */
  .blank__dot { background: var(--blue); opacity: 1; }
  * { transition-duration: .01ms !important; }
}

/* ------------------------------------------------------------------ account
   Signing in, offered on the lobby and the done screen. Deliberately quiet:
   it sits below the numbers, not above Play, because it is optional and the
   game works without it. */
.account {
  margin-top: 26px; padding-top: 22px;
  border-top: 1px solid var(--rule-light);
  /* ⚠️ Centred inside the lobby's hero card, which is centred; ranged left on
     the results and done pages, which are not. */
  text-align: center;
}
.screen:not(#lobby) .account, .screen:not(#lobby) .actions { text-align: left; justify-content: flex-start; }
.screen:not(#lobby) .account__form { justify-content: flex-start; }
/* ⚠️ The eyebrow is empty on every step but the offer, and an empty inline
   element with a bottom margin would still hold the space. `:empty` collapses
   it, so the code block and the "we sent you a code" step do not sit on a gap
   where a heading used to be. Same for the footnote below. */
.account .eyebrow { display: block; margin-bottom: 10px; }
.account .eyebrow:empty { display: none; }
.account__note {
  font-size: 14.5px; color: var(--muted); margin: 0 0 14px;
}
/* The one line under the form: what signing in does today, as against what the
   email will do tomorrow. Quieter than the note, which carries the offer. */
.account__foot {
  font-size: 13px; color: var(--muted-2); margin: 14px 0 0;
}
.account__foot:empty { display: none; }

/* The one checkbox on the site: the daily email, on /account. The whole label
   is the target rather than the 13px box beside it. */
.check { display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: 15px; }
.check input { width: 17px; height: 17px; accent-color: var(--blue); cursor: pointer; }
.account__form {
  display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;
}
.account__input {
  flex: 1 1 240px; max-width: 320px; min-width: 0;
  padding: 13px 14px; font: inherit; font-size: 15px;
  color: var(--ink); background: #fff;
  border: 1px solid var(--rule); border-radius: 0;
}
.account__input:focus-visible {
  outline: 2px solid var(--ink); outline-offset: -1px; border-color: var(--ink);
}
/* The code field. Wide-tracked digits so a six-figure code reads as six
   separate things, and centred because there is nothing else in it. */
.account__input--code {
  flex: 0 0 auto; width: 100%; max-width: 190px;
  font-family: var(--display); font-size: 21px; font-weight: 700;
  letter-spacing: .32em; text-indent: .32em; text-align: center;
}

.btn--quiet {
  padding: 9px 18px; font-size: 13px;
  background: transparent; color: var(--muted);
  border: 1px solid var(--rule);
}
/* ⚠️ The quiet buttons had NO vertical spacing of any kind. Measured on the
   live page: 0px between the form and them, and the 4.3px between the two was
   an inline whitespace character rather than a gap. It never showed on the
   lobby, where only one of them is ever visible at once; /account's step two
   shows "Use a different address" and "Send it again" together, and they sat
   flush against the code field.

   The row is a flex container so the gap is declared rather than inherited
   from whitespace, and it wraps on a narrow screen instead of overflowing. */
.account__quiet {
  display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;
  margin-top: 14px;
}
/* The lobby has no wrapper -- one button, straight under the form. */
.account > .btn--quiet { margin-top: 14px; }
.btn--quiet:hover { background: var(--btn-hover); color: var(--ink); }

/* The field and its button stack rather than shrink; a 240px input beside a
   button is below the tap target on a narrow phone. */
@media (max-width: 420px) {
  .account__form { flex-direction: column; align-items: stretch; }
  /* ⛔ `flex: none`, and it is not cosmetic. The base rule is `flex: 1 1 240px`,
     whose basis is the MAIN axis -- so the moment the direction flips to column
     that 240px becomes a 240px-TALL input. Measured at 375px: a field four
     lines deep with the placeholder stranded at the bottom of it. */
  .account__input { flex: none; max-width: none; }
  /* The code field keeps its own width and stays centred: stretched to the
     full column its tracked digits drift apart into nothing. */
  .account__input--code { max-width: 190px; align-self: center; }
}

/* An invitation waiting: a dot on the pill, the same blue the wordmark's caret
   uses. ⚠️ On the pill itself, not the avatar, so it reads at any zoom. */
.pill.has-waiting { position: relative; }
.pill.has-waiting::after {
  content: ""; position: absolute; top: -2px; right: -2px;
  width: 9px; height: 9px; border-radius: 999px;
  background: var(--blue); border: 2px solid var(--card);
}

/* ------------------------------------------------------------------- home
   A list of what is here, in the same rows the rest of the site uses. A second
   quiz is another row and nothing else moves. */
.home__lead { font-family: var(--serif); font-size: 18.5px; line-height: 1.5;
  margin: 24px 0 0; max-width: 34em; }
.row--link { text-decoration: none; color: inherit; align-items: center; gap: 14px 24px; }
.row--link:hover .row__go { color: var(--blue-hover, #12459b); }
.row--link:hover .row__arrow { transform: translateX(3px); }
.row--link:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.row__body { flex: 1 1 240px; }
.row__body .row__name { display: block; flex: none; }
.row__line { display: block; margin-top: 6px; font-family: var(--serif); font-size: 16px;
  line-height: 1.5; color: var(--muted); max-width: 34em; }
.row__go { margin-left: auto; display: inline-flex; align-items: center; gap: 7px;
  font-size: 14.5px; font-weight: 600; color: var(--blue); white-space: nowrap; }
.row__arrow { transition: transform .15s ease; }

/* The wordmark is a link home wherever it is not already home. A site mark
   that does not go home is the anomaly.
   ⛔ THESE SAT IN THE OLD HOME-PAGE BLOCK and went with it on 2026-09-12: the
   wordmark then rendered as a default blue underlined link on /friends,
   /account, /me and all 237 Study pages, because the site sets no global `a`
   colour. Second rule lost this way -- see `.visually-hidden`. */
.topbar__home { text-decoration: none; color: inherit; display: inline-block; }
.topbar__home:hover .wordmark__dot { background: var(--blue-hover, #12459b); }
.topbar__home:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* The Friends lobby's footer. Small and washed out, his call 2026-09-07 —
   present without competing with anything on the screen above it.
   ⚠️ `--dim-text` is 4.58:1 on paper, over the AA floor by the smallest margin
   the palette allows; measured, not estimated.
   ⛔ Also deleted with the home block on 2026-09-12, which left the disclaimer
   as 16px ink body copy under the record. */
.disclaimer {
  max-width: 58ch; margin: 30px auto 0;
  font-size: 11.5px; line-height: 1.65; color: var(--dim-text);
  text-align: center; text-wrap: pretty;
}

/* ------------------------------------------------- the nav and the account
   His decision, 2026-09-09: the top bar becomes a section, an action, and you.
   Study, the list, the account and Play were four items in a bar that grew
   with every page added. */

.topbar__nav { margin-left: auto; display: flex; align-items: center; gap: clamp(12px, 3vw, 20px); }
.nav__link { font-size: 14.5px; color: var(--muted); text-decoration: none; white-space: nowrap; }
.nav__link:hover { color: var(--ink); }
/* The section you are in, marked on the bar rather than only in the title. */
.nav__link[aria-current="page"] {
  color: var(--ink); font-weight: 600;
  padding-bottom: 2px; border-bottom: 2px solid var(--blue);
}
.nav__link--play { font-weight: 600; color: var(--blue); }

.account-pill { position: relative; }
.pill {
  display: flex; align-items: center; gap: 10px;
  padding: 5px 6px 5px 13px; border-radius: 999px;
  background: #fff; border: 1px solid var(--border-idle);
  cursor: pointer; font: inherit;
  transition: border-color .16s ease, box-shadow .16s ease;
}
.pill:hover, .pill[aria-expanded="true"] {
  border-color: var(--ink);
  /* The same hard shadow the mode cards and the quiz cards use. */
  box-shadow: 0 2px 0 var(--ink);
}
.pill:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.pill__rules { display: flex; flex-direction: column; gap: 3px; }
.pill__rules i { display: block; width: 15px; height: 1.6px; background: var(--ink); }
.pill__avatar {
  display: grid; place-items: center; width: 28px; height: 28px; border-radius: 999px;
  background: var(--chip-idle); color: var(--muted-2);
  font-family: var(--display); font-size: 13px; font-weight: 700; line-height: 1;
}
/* Signed in, and only ever after the account has answered -- never rendered
   this way on first paint. */
.pill__avatar.is-in { background: var(--ink); color: #fff; }

/* ⛔ SQUARE. A pill is a button; a panel is not. */
.menu {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 40;
  min-width: 252px; background: #fff; border: 1px solid var(--rule);
  box-shadow: 0 24px 50px -26px rgba(20, 18, 15, .45);
}
.menu__who { padding: 13px 18px; border-bottom: 1px solid var(--rule-lighter); }
.menu__who b { display: block; font-size: 14.5px; font-weight: 600; word-break: break-all; }
.menu__who span { display: block; margin-top: 2px; font-size: 12.5px; color: var(--muted-2); }
.menu__item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 13px 18px; border: 0; border-bottom: 1px solid var(--rule-lighter);
  background: none; font: inherit; font-size: 14.5px; color: var(--ink);
  text-align: left; text-decoration: none; cursor: pointer;
}
.menu__item:last-child { border-bottom: 0; }
.menu__item:hover, .menu__item:focus-visible { background: var(--dim-surface); outline: none; }
.menu__item:focus-visible { box-shadow: inset 2px 0 0 var(--blue); }
/* ⚠️ --muted-2, not --muted-3. The count is a line a reader reads, and
   --muted-3 measures 3.37:1 against this surface. */
.menu__count { margin-left: auto; font-size: 13px; color: var(--muted-2); }
.menu__item--quiet { background: var(--dim-surface); color: var(--muted); }

@media (max-width: 480px) {
  /* The bar must not wrap at 375px, so the section label goes and the pill
     carries the account on its own. Play stays: it is the action. */
  .topbar__nav { gap: 12px; }
  .nav__link:not(.nav__link--play):not([aria-current="page"]) { display: none; }
}

/* ----------------------------------------------- rows: the page vocabulary
   Written for /account and /me, and now the shape every page uses for a list:
   a section head over a 2px ink rule, then hairline rows. The game screens and
   the home page read these too.

   /account, /me
   His decision, 2026-09-09: signing in was a quiet block on three game screens,
   and once you were in the site could tell you your address and nothing else. */

.account-card { max-width: 620px; margin-top: 28px; padding: 28px 30px 30px; }
/* ⚠️ 17.5px, not 17px. The scale in :root has no 17 -- it goes 16, 17.5, 18.5
   -- and this was the one size on the site sitting between two of its steps. */
.account-card__lead { font-family: var(--serif); font-size: 17.5px; line-height: 1.5;
  margin: 10px 0 0; }
.account-card__aside { font-size: 14.5px; color: var(--muted); margin: 14px 0 0; }
.account-card__foot { margin: 22px 0 0; padding-top: 16px;
  border-top: 1px solid var(--rule-light); font-size: 14.5px; color: var(--muted); }
.account-help { max-width: 620px; margin: 14px 0 0; font-size: 13.5px; color: var(--muted); }
.who--address { word-break: break-all; }

.browser-stats { max-width: 620px; margin-top: 28px; padding: 20px 22px;
  background: var(--dim-surface); border: 1px solid var(--dim-border); }
.browser-stats h2 { margin: 0 0 14px; font-family: var(--display); font-size: 15.5px; }

/* A section of rows: one per quiz, one per browser. */
.rows { margin-top: 40px; }
.rows__head { display: flex; align-items: baseline; gap: 14px; padding-bottom: 10px;
  border-bottom: 2px solid var(--ink); }
.rows__head h2 { margin: 0; font-family: var(--display); font-size: 19px; }
.rows__note { margin-left: auto; font-size: 13.5px; color: var(--muted-2); }
a.rows__note { color: var(--blue); text-decoration: none; }
a.rows__note:hover { text-decoration: underline; }
.rows__lead { margin: 14px 0 0; font-size: 14.5px; color: var(--muted); max-width: 60ch; }
.rows__actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }

.row { display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  padding: 18px 0; border-bottom: 1px solid var(--rule-light); }
.row__name { font-family: var(--display); font-size: 21px; flex: 1 1 100%; }
.row--device .row__name { font-size: 16px; flex: 1 1 auto; }
.row__meta { margin-left: auto; font-size: 13.5px; color: var(--muted-2); }
.row__stats { display: flex; flex-wrap: wrap; gap: 26px; flex: 1 1 auto; }
.row--round { padding: 12px 0; gap: 10px 20px; }
.row--round .row__day { flex: 1 1 190px; font-size: 14.5px; }
.row--round .row__quiz { font-size: 14.5px; color: var(--muted-2); }
/* The mode arrives named ("Dead Ross"), not as an id, so nothing to tidy. */
.row--round .row__score { margin-left: auto; font-size: 14.5px; color: var(--muted-2);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.row--round .row__score b { font-family: var(--display); font-size: 17.5px; color: var(--ink);
  margin-right: 6px; }
/* The current browser, named without naming a user agent. */
.chip--here { display: inline-block; margin-left: 8px; padding: 2px 9px; border-radius: 999px;
  background: var(--blank-fill); color: var(--blue); font-family: var(--sans);
  font-size: 11.5px; font-weight: 600; }

/* The saved-episodes card. ⚠️ Used by /me, which is the ONLY place it lives
   now -- the duplicate on /account was removed 2026-09-10, his call, because
   the pill already links here. Deleting this with it would have taken the
   styling off the page that still uses it. */
.saved-card { margin-top: 40px; padding: 22px 24px 24px; }
.saved-list { margin-top: 16px; }
.saved-list a {
  display: block; padding: 5px 0;
  border-bottom: 1px solid var(--rule-lighter);
  font-size: 14.5px; color: var(--ink); text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.saved-list a:last-child { border-bottom: 0; }
.saved-list a:hover { text-decoration: underline; }
.saved-list .num { color: var(--muted-2); margin-right: 8px; }

.danger { margin-top: 48px; padding: 22px 24px 24px;
  background: var(--red-surface); border: 1px solid var(--red); }
.danger h2 { margin: 0 0 10px; font-family: var(--display); font-size: 17.5px; color: var(--red-deep); }
.danger p { margin: 0 0 16px; font-size: 14.5px; color: var(--red-deep); max-width: 62ch; }
.btn--danger { padding: 11px 22px; background: #fff; color: var(--red-deep);
  border: 1px solid var(--red); }
.btn--danger:hover { background: #fff5f5; }
.btn--danger.is-armed { background: var(--red); color: #fff; }

/* /me's three-cell tally. */
.tally { display: flex; flex-wrap: wrap; gap: 26px; margin: 24px 0 8px;
  padding-bottom: 18px; border-bottom: 1px solid var(--rule-light); }
.tally__cell b { display: block; font-family: var(--display); font-size: 27px; line-height: 1.1;
  font-variant-numeric: tabular-nums; }
.tally__cell span { display: block; font-size: 13.5px; color: var(--muted-2); }

