/* ============================================================
   Resonance — the Games tab and the With-Matches game room.
   Work Order 153a, August 12, 2026.
   ------------------------------------------------------------
   Its own `.g-` namespace, loaded after style.css and member.css, which carry the tokens,
   the nav strip, the buttons (.btn / .btn-primary / .m-btn-small), the section head and the
   boot shell this page reuses whole. Nothing here restyles a shared class.

   NO NEW KEYFRAMES ANYWHERE IN THIS FILE. Where attention is wanted the page wears
   member.css's own `.n-attention` — three beats then still, with the standing held ring
   under prefers-reduced-motion. One attention mechanism in the product, and this is a user
   of it, never a second implementation.
   ============================================================ */

/* ============================================================================
   WO248 (MATT, AUGUST 16 2026) — WHERE A FOCUS LANDING COMES TO REST, AND WHY IT IS A
   STYLESHEET DECLARATION RATHER THAN A LINE OF JAVASCRIPT
   ============================================================================
   MATT, OF LESSER EVILS: "on mobile, Next Trial leaves the member where they were; it must
   refocus to the TOP OF THE SCREEN where the next trial is."

   THE SCREEN WAS ALREADY MOVING. WO246 built the focus engine, site/assets/games.js has armed
   'round-next' at the Next-trial tap since that order, and the map answers 'game'. What was
   wrong was the LANDING: `scrollIntoView({ block: 'start' })` puts the anchor's top at the top
   of the VIEWPORT, and the site's nav is `position: sticky; top: 0` (assets/style.css) — 114
   pixels tall on a 390 phone, 73 on a desktop. Measured on a real browser before this order:
   after Next Trial the game's heading came to rest at y=11 and "Would you rather" at y=107,
   both of them behind a strip that ends at 114. The member landed on two option buttons with
   the question they answer hidden under the chrome.

   scroll-margin-top IS EXACTLY THE PROPERTY FOR THIS. It is what scrollIntoView is specified to
   honour, so the engine's call did not change — same block, same smooth-or-instant answer, same
   rule about not moving for something already on the screen. One declaration, and the browser
   does the arithmetic.

   THE NUMBER IS THE SHELL'S OWN MEASUREMENT AND NOT A GUESS. `--rsx-navh` is published on
   <html> by assets/shell.js from the real nav's height and republished on every resize, so this
   is correct at every width, in every section, and on the day the nav grows a row. The fallback
   (84px) is the shell stylesheet's own, copied rather than invented, so a page whose shell has
   not booted still lands below a nav of about the right size. The extra 16px is the page's own
   gutter: a heading flush against the underside of a nav reads as clipped even when it is not.

   IT APPLIES TO EVERY ANCHOR ON THE GAMES SURFACE and therefore to every game, which is honest
   rather than broad — the fault is the site chrome's, not this game's, and an offset scoped to
   Lesser Evils would leave the other eight landing under the nav while the order claimed the
   rule had been applied. Nothing outside this stylesheet is touched, and no other page's
   scrolling is affected: the selector is the games surface's own anchor attribute.
   ============================================================================ */
[data-focus] { scroll-margin-top: calc(var(--rsx-navh, 84px) + 16px); }

/* ============================================================================
   WO312 (MATT, AUGUST 18 2026) — AND THE ASK BUTTON LANDS BY THE SAME RULE
   ============================================================================
   THE PICKER'S ASK IS THE SECOND THING ON THIS SURFACE THE PAGE MOVES THE SCREEN TO. When a
   person is chosen from the pull-downs, site/assets/games.js scrolls the button into view —
   through WO246's own engine, so it is the same call with the same reduced-motion answer — and a
   landing with no offset would put the button under the sticky nav exactly as WO248 found the
   game heading under it. The declaration is WO248's, character for character, at a second
   selector; the number is still the shell's own measurement and is still typed nowhere.
   IT IS A SECOND SELECTOR AND NOT A WIDENED ONE. `[data-focus]` names the anchors the focus
   engine may LAND on, and the ask control is not one of them — nothing may arm a transition to
   it, and it takes no focus when the screen moves to it. Two selectors, one rule, and the
   difference between them stays visible.

   THE PULSE ON THIS BUTTON NEEDS NOTHING HERE AND GETS NOTHING HERE. It is WO120's shared
   `rs-pulse` from assets/style.css, in its light-ground form because the picker card is
   `--white` — no keyframes are minted in this file (see the head of it), no colour is named, and
   the reduced-motion static ring comes with the shared class. The one thing the ring needs is
   room to breathe, and the card's own 18px/20px padding already gives it more than the 5px the
   ring spreads to.
   ============================================================================ */
[data-pickgo] { scroll-margin-top: calc(var(--rsx-navh, 84px) + 16px); }

.g-pagewrap { max-width: 860px; margin: 0 auto; padding: 26px 20px 64px; }
.g-pagewrap h1 { font-family: "Fraunces", Georgia, serif; font-weight: 600;
  font-size: clamp(1.6rem, 5vw, 2.2rem); line-height: 1.15; margin: 0 0 10px; }
.g-pagewrap h2 { font-family: "Fraunces", Georgia, serif; font-weight: 600;
  font-size: 1.22rem; margin: 0; }

/* the one sentence the tab carries about what games are for (the porch doctrine) */
.g-porch { color: var(--ink-soft, #55503F); max-width: 46rem; margin: 0 0 26px; }
.g-cat { margin: 0 0 34px; }
.g-cat .m-fine { margin: 8px 0 14px; }
.g-back { margin: 0 0 12px; font-size: .92rem; }

/* ---------- WO183 (Matt, August 14 2026) — THE QUIET ENDING'S ONE SENTENCE ----------
   A game that a member was in can now end because the pair started a different one, and the
   partner meets this line where the game used to be. IT IS DELIBERATELY THE CALMEST SURFACE ON
   THE PAGE: no red, no icon, no border on all four sides, no animation, nothing that reads as
   an error or an alert. A soft rule down the side and the page's own soft ink — the visual
   weight of a footnote, because the ending is not news and must not look like a rebuke.
   THE CONTRAST IS THE PRODUCT'S OWN --ink-soft on --white, which the a11y sweep already holds
   at AA everywhere else it is used. */
.g-ended { margin: 0 0 18px; padding: 10px 0 10px 14px; max-width: 46rem;
  color: var(--ink-soft, #55503F); font-size: .95rem; line-height: 1.5;
  border-left: 3px solid rgba(33, 29, 22, .14); }

/* ---------- the people you can play with ----------
   WO216 (MATT, AUGUST 14 2026) — NOTHING ON THE TAB WEARS THESE ANY MORE. He ruled the bottom
   people list off the games page ("the bottom list I kept discovering things in is gone") and
   site/assets/games.js no longer draws it. The rules are KEPT rather than deleted for one
   reason: they are the shape the whole tab's card vocabulary was drawn from — `.g-inprogitem`,
   `.g-askedoutitem` and `.g-invitecard` are all this card, one shade at a time — and deleting
   the original would leave three descendants and no ancestor for the next person to read. They
   cost nothing: no markup on any page matches them today. */
.g-people { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.g-person { background: var(--white, #FFFDF8); border-radius: 16px;
  box-shadow: 0 6px 18px rgba(33, 29, 22, .07); border: 1px solid rgba(33, 29, 22, .05); }
.g-personlink { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding: 16px 18px; min-height: 48px; text-decoration: none; color: inherit; }
.g-personlink:hover { text-decoration: none; background: var(--cream-deep, #F3EADA);
  border-radius: 16px; }
.g-name { font-weight: 700; font-size: 1.05rem; }
.g-state { color: var(--ink-soft, #55503F); font-size: .88rem; }

/* ---------- the menu ---------- */
.g-menulist { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.g-menuitem { background: var(--white, #FFFDF8); border-radius: 18px; padding: 18px 20px;
  box-shadow: 0 6px 18px rgba(33, 29, 22, .07); border: 1px solid rgba(33, 29, 22, .05); }
.g-menuname { font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 1.15rem;
  margin-bottom: 4px; }
.g-menufoot { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 12px; }
.g-firstmove { margin-top: 16px; max-width: 44rem; }

/* ---------- the invitation ---------- */
.g-invited { background: var(--white, #FFFDF8); border-radius: 18px; padding: 20px;
  box-shadow: 0 6px 18px rgba(33, 29, 22, .07); border: 1px solid rgba(33, 29, 22, .05); }
.g-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 14px 0 10px; }
.g-sent { font-weight: 600; margin: 10px 0; }

/* ---------- the game ---------- */
.g-gamehead { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; margin-bottom: 6px; }
/* THE SCORE LINE — the recorded carve-out to words-not-numbers, and it lives on this one
   selector in this one file, which is itself part of the guarantee: there is no shared class
   a score could be drawn with somewhere else. */
.g-score { font-weight: 700; margin: 4px 0 18px; color: var(--orange-deep, #B54800); }
.g-items { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; counter-reset: g; }
.g-item { background: var(--white, #FFFDF8); border-radius: 18px; padding: 18px 20px;
  box-shadow: 0 6px 18px rgba(33, 29, 22, .07); border: 1px solid rgba(33, 29, 22, .05); }
.g-item.g-revealed { background: var(--cream, #FAF5EC); }
.g-stem { font-weight: 700; margin: 0 0 12px; }
.g-side { border: none; padding: 0; margin: 0 0 14px; min-width: 0; }
.g-side legend { padding: 0; font-size: .9rem; font-weight: 700;
  color: var(--ink-soft, #55503F); margin-bottom: 6px; }
/* WO193 — TWO TRUTHS' GUESS QUESTION, WHICH IS NOW THE FIELDSET'S OWN LEGEND RATHER THAN A
   HEADING ABOVE ONE. Matt's complaint was that the question was on the screen twice; the cure
   was to draw it once, and the cost of drawing it once is that the one that survives has to
   carry the weight the heading was carrying. So this is .g-stem's size and colour on a
   <legend> — no new voice, no second style, just the heading rule applied where the heading
   now lives. */
.g-side legend.g-askhead { font-size: 1rem; color: var(--ink, #211D16); margin-bottom: 12px; }
/* 44px IS THE FLOOR AND IT IS THE FLOOR EVERYWHERE, not only on a phone — the standing tap
   target rule has no desktop tier. */
.g-opt { display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 8px 10px;
  cursor: pointer; border-radius: 12px; border: 1px solid rgba(33, 29, 22, .08);
  margin-bottom: 8px; background: var(--cream, #FAF5EC); }
.g-opt:last-child { margin-bottom: 0; }
.g-opt input { width: 24px; height: 24px; margin: 0; flex: none;
  accent-color: var(--orange-deep, #B54800); cursor: pointer; }
.g-opt input:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 3px; }
.g-said { min-height: 1.3em; margin: 6px 0 10px; font-size: .9rem; color: #8A3A22; font-weight: 600; }
.g-locked p { margin: 0 0 6px; }
.g-mine, .g-theirs { font-size: .96rem; }
.g-verdict { font-weight: 700; margin-top: 8px; }
.g-verdict.g-right { color: var(--orange-deep, #B54800); }

/* ---------- the porch guard ---------- */
.g-handoff { margin-top: 26px; padding: 20px; border-radius: 18px;
  background: var(--cream-deep, #F3EADA); border: 1px solid rgba(33, 29, 22, .06); }
.g-handoff p { font-family: "Fraunces", Georgia, serif; font-size: 1.2rem; margin: 0 0 14px; }
.g-rematch { margin-top: 14px; }

/* ---------- the chat: the third door ---------- */
.g-chat { margin-top: 34px; }
.g-chatlist { list-style: none; margin: 12px 0; padding: 0; display: grid; gap: 8px; }
.g-line { padding: 10px 14px; border-radius: 14px; max-width: 34rem;
  background: var(--white, #FFFDF8); border: 1px solid rgba(33, 29, 22, .06); }
.g-line.g-me { margin-left: auto; background: var(--orange-soft, #FCEBD2); }
.g-say textarea { width: 100%; border-radius: 12px; padding: 10px 12px; font: inherit;
  border: 1px solid rgba(33, 29, 22, .18); background: var(--white, #FFFDF8); min-height: 60px; }
.g-say textarea:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }
.g-saylab { display: block; font-size: .9rem; font-weight: 700;
  color: var(--ink-soft, #55503F); margin-bottom: 6px; }

/* ---------- the rules panel ---------- */
.g-rulesbtn { flex: none; }
.g-modal { position: fixed; inset: 0; z-index: 90; display: flex; align-items: center;
  justify-content: center; padding: 20px; background: rgba(20, 20, 20, .45); }
.g-modalcard { background: var(--white, #FFFDF8); border-radius: 20px; padding: 24px 22px;
  max-width: 34rem; width: 100%; max-height: 88vh; overflow: auto;
  box-shadow: 0 18px 46px rgba(20, 20, 20, .28); }
.g-modalcard h2 { margin-bottom: 12px; }
.g-steps { margin: 0 0 18px; padding-left: 1.3em; display: grid; gap: 6px; }
.g-steps li { color: var(--ink, #211D16); }
/* THE VISUAL. currentColor throughout, so it survives forced-colours and any background; it
   carries role="img" with the server's own sentence as its accessible name, and every step it
   pictures is also printed above it in words. */
.g-fig { display: block; width: 100%; height: auto; max-width: 32rem; margin: 0 auto 16px;
  color: var(--ink-soft, #55503F); }
.g-modalcard .g-fine { color: var(--ink-soft, #55503F); font-size: .92rem; margin-bottom: 18px; }

@media (max-width: 560px) {
  .g-pagewrap { padding: 20px 16px 56px; }
  .g-menufoot, .g-actions { flex-direction: column; align-items: stretch; }
  .g-menufoot .btn, .g-actions .btn, .g-menufoot .m-btn-small, .g-actions .m-btn-small { width: 100%; }
  .g-line { max-width: 100%; }
}

/* ============================================================
   WO153b — THE SIX SIBLING GAMES. August 12–13, 2026.
   ------------------------------------------------------------
   Six new control shapes, in the same `.g-` namespace, under the same three rules WO153a set
   for this file and did not break: NO NEW KEYFRAMES anywhere (the one attention treatment in
   the product is member.css's `.n-attention` and this page is a user of it, never a second
   implementation); nothing here restyles a shared class; and 48px is the tap-target floor on
   EVERY control, on a desktop exactly as on a phone.
   ============================================================ */

/* ---------- 'tiles' — WHAT WOULD THEY SAY ----------
   One column on a phone, two from 480px. Never three: a tile is a phrase, not a word, and
   three columns of phrases is a wall of text pretending to be buttons. */
.g-tiles { display: grid; gap: 8px; }
.g-tile { display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 10px 12px;
  cursor: pointer; border-radius: 12px; border: 1px solid rgba(33, 29, 22, .08);
  background: var(--cream, #FAF5EC); }
.g-tile input { width: 24px; height: 24px; margin: 0; flex: none;
  accent-color: var(--orange-deep, #B54800); cursor: pointer; }
.g-tile input:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 3px; }
.g-tile:has(input:checked) { border-color: var(--orange-deep, #B54800); background: var(--orange-soft, #FCEBD2); }
@media (min-width: 480px) { .g-tiles { grid-template-columns: 1fr 1fr; } }

/* ---------- 'multi' — COMMON GROUND ----------
   Twenty-four things read at one go, so they go two-up as soon as there is room and the
   checkbox stays the full 48px target it is everywhere else. */
.g-optionlist { display: grid; gap: 8px; }
.g-optmulti { margin-bottom: 0; }
@media (min-width: 520px) { .g-optionlist { grid-template-columns: 1fr 1fr; } }
.g-mylist { list-style: none; margin: 0 0 10px; padding: 0; display: grid; gap: 6px; }
.g-mypick { padding: 8px 12px; border-radius: 10px; background: var(--cream, #FAF5EC);
  border: 1px solid rgba(33, 29, 22, .06); }
/* THE SHARED ONES, AND ONLY THE SHARED ONES, ARE MARKED. There is no style in this file for
   "only you picked this" because there is no such key in the payload — see the server. */
.g-mypick.g-shared { background: var(--orange-soft, #FCEBD2); border-color: var(--orange-deep, #B54800);
  font-weight: 700; }
.g-bothtag { font-size: .78rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--orange-deep, #B54800); }

/* ---------- 'statements' — TWO TRUTHS ---------- */
.g-stmt { margin-bottom: 12px; }
.g-stmt textarea { width: 100%; border-radius: 12px; padding: 10px 12px; font: inherit;
  border: 1px solid rgba(33, 29, 22, .18); background: var(--white, #FFFDF8); min-height: 60px; }
.g-stmt textarea:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }
.g-stmtlist { margin: 0 0 10px; padding-left: 1.4em; display: grid; gap: 6px; }
.g-stmtlist li { padding: 2px 0; }
.g-stmtlist li.g-lie { font-weight: 700; }
/* WO174 — THE ASK UNDER A STATEMENT. It reuses .g-quiet, which is the whole point: this is
   the quietest control on a revealed round, exactly as the "Tell me why?" row is, and its
   44px floor and its focus ring come with it. Its own row so the statement is never squeezed
   by it on a phone, and never bold — a statement marked as the lie is bold, and the button
   beside it is not part of that sentence. */
.g-askrow { margin: 2px 0 0; font-weight: 400; }
.g-theirlist { color: var(--ink-soft, #55503F); }

/* ---------- 'order' — RANK MY THREE ---------- */
.g-rankrow { margin-bottom: 12px; }
.g-rankrow select { width: 100%; min-height: 48px; border-radius: 12px; padding: 8px 12px;
  font: inherit; border: 1px solid rgba(33, 29, 22, .18); background: var(--white, #FFFDF8); }
.g-rankrow select:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }

/* ---------- 'slider' — THE SPECTRUM GAME ----------
   THE THUMB IS 44px AND IT IS 44px ON EVERY ENGINE, which is why both vendor pseudo-elements
   are written out: a 44px target that is only 44px in one browser is not a 44px target. The
   track is tall enough to hit without the thumb, and the focus ring is on the input itself so
   it survives both. */
.g-poles { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 6px;
  font-size: .9rem; font-weight: 700; color: var(--ink-soft, #55503F); }
.g-poleright { text-align: right; }
.g-track { position: relative; height: 14px; margin: 6px 0 14px; border-radius: 7px;
  background: var(--cream-deep, #F3EADA); border: 1px solid rgba(33, 29, 22, .08); }
/* ============================================================================
   WO246 (MATT, AUGUST 16 2026) — THESE TWO ARE SCOPED TO THE TRACK NOW, AND THAT WAS THE STRAY
   CHECK MARK
   ============================================================================
   MATT: "at the end of a game on mobile, a green check mark on a dark orange disc appeared in
   the upper right, above all the tabs. I have no idea why that's there but it shouldn't be."

   THIS RULE DREW IT. `.g-mark` has meant "Same Page's marker on the 0–100 track" since WO153b —
   position:absolute, top:-5px, 4×22, dark orange — and WO189 minted a SECOND `.g-mark` for the
   reveal's verdict glyph (the green check and the red X, .g-mark-check / .g-mark-x, 38×38,
   display:block). Two rules, one class, and the cascade gave the verdict SVG all of both: the
   38×38 box and the display from WO189's rule, and the position:absolute, the top:-5px and the
   DARK ORANGE BACKGROUND from this one.
   AN ABSOLUTELY POSITIONED ELEMENT WITH NO POSITIONED ANCESTOR IS LAID OUT AGAINST THE PAGE. The
   verdict row is a flex row and nothing above it is positioned, so the containing block is the
   initial one: the green check went to top:-5px OF THE DOCUMENT — over the brand strip, above
   the tabs — wearing a dark orange ground it was never meant to have. That is exactly what he
   photographed, and it is a violation of NOTHING_ABOVE_THE_TABS arriving from a stylesheet
   rather than from a script.
   THE FIX IS THE NARROWING THIS RULE SHOULD ALWAYS HAVE HAD. The track marker only ever exists
   inside `.g-track` (site/assets/games.js's markHTML wraps it, in all four of its call sites),
   so saying so costs nothing, changes no pixel on Same Page, and puts the verdict glyph back
   under WO189's rule alone — in the flow, beside its sentence, where Matt asked for it in the
   first place. The class names are left as they are: renaming one would be a rename disguised
   as a fix and would move two suites' handles for no gain.
   THE STANDING GUARD IS IN smoke-wo246 §0: nothing on a games surface may be position:absolute
   without a positioned ancestor, asserted in the browser at 390.
   ============================================================================ */
.g-track .g-mark, .g-track .g-markthem { position: absolute; top: -5px; width: 4px; height: 22px;
  border-radius: 2px; transform: translateX(-2px); }
.g-track .g-mark { background: var(--orange-deep, #B54800); }
.g-track .g-markthem { background: var(--ink, #211D16); }
.g-slider { width: 100%; height: 44px; margin: 4px 0 2px; background: transparent;
  -webkit-appearance: none; appearance: none; }
.g-slider:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 4px; }
.g-slider::-webkit-slider-runnable-track { height: 14px; border-radius: 7px;
  background: var(--cream-deep, #F3EADA); border: 1px solid rgba(33, 29, 22, .12); }
.g-slider::-moz-range-track { height: 14px; border-radius: 7px;
  background: var(--cream-deep, #F3EADA); border: 1px solid rgba(33, 29, 22, .12); }
.g-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none;
  width: 44px; height: 44px; margin-top: -16px; border-radius: 50%;
  background: var(--orange-deep, #B54800); border: 3px solid var(--white, #FFFDF8);
  box-shadow: 0 2px 8px rgba(33, 29, 22, .28); cursor: pointer; }
.g-slider::-moz-range-thumb { width: 38px; height: 38px; border-radius: 50%;
  background: var(--orange-deep, #B54800); border: 3px solid var(--white, #FFFDF8);
  box-shadow: 0 2px 8px rgba(33, 29, 22, .28); cursor: pointer; }
.g-slideout { display: block; margin: 0 0 10px; font-size: .9rem; font-weight: 700;
  color: var(--ink-soft, #55503F); }
.g-answer input[type="text"] { width: 100%; min-height: 48px; border-radius: 12px;
  padding: 10px 12px; font: inherit; border: 1px solid rgba(33, 29, 22, .18);
  background: var(--white, #FFFDF8); margin-bottom: 10px; }
.g-answer input[type="text"]:focus-visible { outline: 3px solid var(--orange-deep, #B54800);
  outline-offset: 2px; }

/* ---------- 'board' — ONE WORD ----------
   Three across at every width, because a three-by-three board that reflows is not a board any
   more — the shape IS the thing both people are looking at.
   WO173 — THE TILE IS A PICTURE WITH ITS WORD UNDER IT. The picture is what makes the board
   scannable; the caption is what keeps the game about the CLUE rather than about identifying
   a drawing. The whole tile is the tap target and it is never smaller than 88px tall, which
   is twice the 44px floor — a nine-cell grid on a 390px phone gives about 118px of width per
   tile, so the target is comfortable rather than merely legal. */
.g-board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 12px; }
.g-tile { position: relative; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 4px; min-height: 88px; padding: 10px 4px 8px;
  text-align: center; cursor: pointer; border-radius: 14px;
  border: 2px solid rgba(33, 29, 22, .10); background: var(--cream, #FAF5EC);
  color: var(--ink, #211D16); font-weight: 600; }
.g-tilepic { display: block; line-height: 0; color: var(--ink, #211D16); }
.g-tilepic .g-ico { width: 46px; height: 46px; display: block; }
.g-tilecap { display: block; font-size: .84rem; line-height: 1.15; letter-spacing: .01em; }
/* THE CHECKBOX IS REAL AND FOCUSABLE and sits in the tile's top-left corner, small, because
   the PICTURE is the thing being chosen and a 20px box in the middle of a tile would compete
   with it. It is never the only signal that a tile is chosen — see the selected state. */
.g-tile input { position: absolute; top: 6px; left: 6px; width: 18px; height: 18px; margin: 0;
  accent-color: var(--orange-deep, #B54800); cursor: pointer; }
.g-tile input:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 3px; }
.g-tile input:disabled { cursor: default; }
/* SELECTED IS NEVER COLOUR ALONE: a heavier border, a lifted background AND the ticked box —
   three signals, two of which survive a monochrome screen. */
.g-tile:has(input:checked), .g-tileon { border-color: var(--orange-deep, #B54800);
  background: var(--orange-soft, #FCEBD2); box-shadow: inset 0 0 0 1px var(--orange-deep, #B54800); }

/* ---------- WO173: THE REVEAL, AND ITS FOUR STATES ----------
   Matt's test is a board he would have read as fence + snow, where he got snow: WHAT WAS
   MEANT and WHAT WAS GOT both legible without reading a word. Four treatments, and none of
   them is colour on its own — every one carries a SHAPE in the corner as well as a fill:
     FOUND   filled and ringed, with a tick        — the strongest thing on the board
     MISSED  ringed, dashed, with a dot            — "this was one of them"
     STRAY   a warm outline with an open circle    — a stray tap, never a red wrong
     PLAIN   faded, no mark                        — neither of them touched it
   NOTHING HERE IS RED. A cooperative game does not tell two people off. */
.g-boardrev .g-tile { cursor: default; }
.g-tilemark { position: absolute; top: 6px; right: 6px; width: 20px; height: 20px;
  border-radius: 50%; display: none; }
.g-rev-found { border-color: var(--orange-deep, #B54800);
  background: var(--orange-soft, #FCEBD2); box-shadow: inset 0 0 0 2px var(--orange-deep, #B54800); }
.g-rev-found .g-tilemark { display: block; background: var(--orange-deep, #B54800); }
.g-rev-found .g-tilemark::after { content: ""; position: absolute; left: 6px; top: 4px;
  width: 6px; height: 10px; border: solid var(--white, #FFFDF8);
  border-width: 0 2.5px 2.5px 0; transform: rotate(42deg); }
.g-rev-missed { border-color: var(--orange-deep, #B54800); border-style: dashed;
  background: var(--cream, #FAF5EC); }
.g-rev-missed .g-tilemark { display: block; border: 2px solid var(--orange-deep, #B54800); }
.g-rev-missed .g-tilemark::after { content: ""; position: absolute; left: 5px; top: 5px;
  width: 6px; height: 6px; border-radius: 50%; background: var(--orange-deep, #B54800); }
.g-rev-stray { border-color: var(--ink-soft, #55503F); background: var(--white, #FFFDF8); }
.g-rev-stray .g-tilemark { display: block; border: 2px dotted var(--ink-soft, #55503F); }
/* PLAIN IS FADED IN THE PICTURE AND NOT IN THE WORD. Dropping the whole tile's opacity was
   the obvious way to say "nothing happened here" and it is the wrong one: it takes the
   CAPTION under the contrast floor, and a member using a phone in the sun would lose six of
   the nine words. So the drawing recedes and the caption goes to the room's soft ink, which
   is an AA colour on this background everywhere else in the file. */
.g-rev-plain { border-color: rgba(33, 29, 22, .10); background: var(--white, #FFFDF8); }
.g-rev-plain .g-tilepic { opacity: .45; }
.g-rev-plain .g-tilecap { color: var(--ink-soft, #55503F); font-weight: 500; }
/* THE KEY. Three little chips reusing the tile states exactly, so the mark on the chip is the
   same mark as the mark on the board — a key that redraws its own version of a thing is a key
   that can drift from it. */
.g-revkey { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-wrap: wrap;
  gap: 8px 16px; font-size: .84rem; color: var(--ink-soft, #55503F); }
.g-revkey li { display: flex; align-items: center; gap: 6px; }
.g-keychip { position: relative; width: 24px; height: 24px; border-radius: 7px;
  border: 2px solid rgba(33, 29, 22, .10); flex: none; }
.g-keychip .g-tilemark { top: 1px; right: 1px; width: 18px; height: 18px; }
.g-keychip.g-rev-found .g-tilemark::after { left: 5px; top: 3px; }
.g-keychip.g-rev-missed .g-tilemark::after { left: 4px; top: 4px; }
/* THE CLUE, OVER THE BOARD, AT THE SIZE IT DESERVES — it is the whole of what the other
   person said, and the count beside it is how many they meant. */
.g-clueline { display: flex; align-items: baseline; gap: 10px; margin: 0 0 10px; }
.g-cluebig { font-size: 1.3rem; font-weight: 700; color: var(--ink, #211D16); }
.g-cluecount { display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; height: 26px; padding: 0 7px; border-radius: 13px; font-weight: 700;
  font-size: .9rem; background: var(--orange-deep, #B54800); color: var(--white, #FFFDF8); }

/* ---------- the member-written surfaces: the quiet control and the placeholder ----------
   The Fast Friends room's own treatment, and its own weight: a quiet text button that does
   not look like a feature, and a placeholder that is visibly a placeholder rather than a
   sentence somebody wrote. */
/* THE LEGEND THAT IS ALREADY ON THE PAGE. Three of the six new forms print their instruction
   as a paragraph and then need it AGAIN as the fieldset's legend, because a fieldset without
   one is not announced as a group. Hiding it from the eye and keeping it for the ear is the
   only honest way to have both: the standard clip-rect treatment, never display:none (which
   would take it from the ear as well) and never a zero font-size. */
.g-vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

.g-quiet { background: none; border: 0; padding: 8px 2px; min-height: 44px; font: inherit;
  font-size: .9rem; color: var(--ink-soft, #55503F); text-decoration: underline; cursor: pointer; }
.g-quiet:hover { color: var(--ink, #211D16); }
.g-quiet:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }
.g-delrow { margin-top: 10px; }
.g-gone { color: var(--ink-soft, #55503F); font-style: italic; margin: 8px 0; }
.g-reportrow { margin-top: 18px; }
.g-reportbox { max-width: 34rem; }
.g-reportbox textarea { width: 100%; border-radius: 12px; padding: 10px 12px; font: inherit;
  border: 1px solid rgba(33, 29, 22, .18); background: var(--white, #FFFDF8); min-height: 60px; }
.g-reportbox textarea:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }

@media (max-width: 560px) {
  /* THE TILE SHRINKS AND THE TARGET DOES NOT. 44px is the floor and 84px is what this is —
     the picture gives back two of the six pixels, the caption none of them. */
  .g-board { gap: 6px; }
  .g-tile { min-height: 84px; padding: 8px 3px 7px; }
  .g-tilepic .g-ico { width: 42px; height: 42px; }
  .g-tilecap { font-size: .78rem; }
}

/* ==========================================================================================
   WO153 FOLLOW-UP #3 (Matt, August 13 2026): "TELL ME WHY?" AND THE GAMES BARRIER
   ==========================================================================================
   THE WHY ROW is deliberately the quietest thing on a revealed item — it reuses .g-quiet, the
   same weight as "Take this down", because it is an offer and never a prompt. It sits under
   the verdict rather than beside it so that nothing about the reveal moves when it appears. */
.g-whyrow { margin: 6px 0 0; }
.g-why { text-underline-offset: 3px; }

/* THE BARRIER CARD. It looks like a card and not like an error: the room's own warm surface,
   one shade lifted, with no red and no warning iconography anywhere in it. What it holds is
   the next game, and the copy says so — a card that looked like a wall would be making a
   claim the rule does not make. */
.g-barrier { margin: 0 0 26px; padding: 18px 18px 6px; border-radius: 16px;
  background: var(--cream-deep, #F6EEDD); border: 1px solid rgba(33, 29, 22, .12); }
.g-barrier h2 { margin: 2px 0 8px; }
.g-kicker { margin: 0; font-size: .82rem; letter-spacing: .04em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-soft, #55503F); }
.g-arow { margin: 16px 0; }
.g-alab { display: block; font-weight: 700; margin-bottom: 6px; }
.g-arow select { width: 100%; max-width: 30rem; min-height: 48px; font: inherit;
  padding: 8px 10px; border-radius: 12px; background: var(--white, #FFFDF8);
  border: 1px solid rgba(33, 29, 22, .28); }
.g-arow select:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }
/* WO157 — .g-aidk IS GONE, and so is the checkbox it styled. "I don't know" is the last ROW
   of the pull-down above, after a blank disabled separator (lib/assessments.mjs,
   COMPAT_OPTION_LIST), so there is no second control here to style: the row inherits the
   select's own 48px and the browser's own wheel. */

/* ============================================================
   WO160 — PICK YOUR PLAYER, AND THE CHAT BENEATH. August 13, 2026.
   ------------------------------------------------------------
   Two surfaces, in the same `.g-` namespace, under the same rules this file has kept since
   WO153a: no new keyframes, no colour that is not already a variable here, and every hit
   target at least 48px on a phone. Nothing below restyles anything above it.
   ============================================================ */

/* ---------- (a) the picker ---------- */
.g-pick { margin: 0 0 30px; }
.g-pick h2 { margin: 0 0 12px; }
/* the box under one game's row, empty and hidden until that game is tapped */
.g-pickbox { margin-top: 14px; padding-top: 14px;
  border-top: 1px solid rgba(33, 29, 22, .12); }
.g-pickbox[hidden] { display: none; }
.g-pickpools { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
/* THE CURRENT POOL IS MARKED WITH WEIGHT AND A BORDER, never with colour alone — the same
   rule every toggle in this product follows, so it survives forced-colours and colour
   blindness. `aria-pressed` carries the same fact for a screen reader. */
.g-pickpool { min-height: 44px; }
.g-pickpool.is-on { font-weight: 700; border-color: var(--orange-deep, #B54800);
  background: var(--orange-soft, #FCEBD2); }
.g-pickbox select { width: 100%; max-width: 30rem; min-height: 48px; font: inherit;
  padding: 8px 10px; border-radius: 12px; background: var(--white, #FFFDF8);
  border: 1px solid rgba(33, 29, 22, .28); }
.g-pickbox select:focus-visible { outline: 3px solid var(--orange-deep, #B54800);
  outline-offset: 2px; }
.g-pickbox p { margin: 12px 0 0; }

/* ---------- (b) the chat card, the Fast Friends room's shape ---------- */
.g-chathead { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
  margin-bottom: 4px; }
.g-chathead h2 { margin: 0; }
.g-chatsub { color: var(--ink-soft, #55503F); font-size: .92rem; }
/* THE HOUSE RULE FOR A MUTED THREAD: the word where the number would be. Quiet on purpose —
   it is a statement of fact about this member's own setting and never an alarm. */
.g-chatmuted { font-size: .82rem; letter-spacing: .04em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-soft, #55503F);
  background: var(--cream-deep, #F6EEDD); border-radius: 999px; padding: 3px 10px; }
.g-chatelse { margin-left: auto; font-size: .92rem; }
/* ONE WINDOW, HOWEVER LONG THE CONVERSATION. The Fast Friends room's scroll region, at this
   door — a conversation that pushed the composer off the bottom of a phone would be a
   conversation a member had to scroll past to answer. */
.g-chatscroll { max-height: 46vh; overflow-y: auto; overscroll-behavior: contain;
  padding-right: 2px; }
.g-quietnote { list-style: none; color: var(--ink-soft, #55503F); font-size: .95rem;
  padding: 10px 0; }

@media (max-width: 560px) {
  .g-pickpools { flex-direction: column; align-items: stretch; }
  .g-pickpool { width: 100%; }
  .g-chatelse { margin-left: 0; }
  .g-chatscroll { max-height: 40vh; }
}

/* ============================================================================
   WO192 — ON REPEAT, REDESIGNED: the builder, the three pull-downs, the reveal
   ============================================================================
   WO161's rules for this game are GONE with the screens they dressed — the category
   negotiation card (.g-negotiate, .g-negcard, .g-negtitle, .g-negfrom, .g-verdictkey, .g-vkey,
   .g-erapick) and the swap row (.g-swaprow, .g-swapbtn, .g-swapnote). Nothing on any surface
   in this feature draws those class names any more, so leaving them would be leaving a reader
   to work out which of two games they belonged to.
   THE STANDING RULES ARE UNCHANGED AND THIS BLOCK KEEPS THEM: layout and emphasis only, no
   string of copy anywhere in this file, NO NEW KEYFRAMES, every control at least 48px on its
   short side, and NOT ONE STATE CARRIED BY COLOUR ALONE — a right answer at the reveal gets a
   check, a border and a weight as well as a tint, so it survives forced-colours mode and reads
   to a colour-blind member, which is the same rule .g-mypick.g-shared already follows. */

/* ---------- the round kicker and the handover ---------- */
.g-rpkick { margin: 0 0 6px; font-size: .82rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-soft, #55503F); }
.g-rphand { margin: 8px 0 14px; padding: 10px 14px; border-radius: 14px;
  background: var(--cream, #FAF5EC); border: 1px solid rgba(33, 29, 22, .10); }
.g-rphand h3 { margin: 0 0 2px; font-size: 1.02rem; }
.g-rphand p { margin: 0; }
/* THE WAITING LINE IS A FACT ABOUT THE ROUND, and it is drawn quietly on purpose: it is the
   screen a member meets while the other one is typing, and a loud one reads as an instruction
   to do something they cannot do. */
.g-rpwait { margin: 14px 0; }

/* ---------- the topic, which stays at the top of the round ---------- */
.g-rptopic { margin: 2px 0 10px; font-size: 1.15rem; line-height: 1.25; }

/* ---------- the builder ---------- */
.g-rpbuild { margin: 4px 0 8px; }
.g-rpbuild h3 { margin: 0 0 4px; font-size: 1.05rem; }
.g-rpfield { display: block; margin: 12px 0; }
.g-rpfield input { width: 100%; min-height: 48px; font: inherit; padding: 8px 12px;
  border-radius: 12px; background: var(--white, #FFFDF8);
  border: 1px solid rgba(33, 29, 22, .28); }
.g-rpfield input:focus-visible, .g-rpbrow input:focus-visible {
  outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }
.g-rpfield .m-fine { display: block; margin-top: 4px; }
/* THE TWO HELPERS. They sit BESIDE the boxes they fill rather than above the form, because a
   member who has not typed a topic yet has nothing to fill from. */
.g-rphelp { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0 4px; }
.g-rphelp .m-fine { margin: 0; flex: 1 1 12rem; }
.g-rpshelf { margin: 4px 0 10px; display: flex; flex-wrap: wrap; gap: 8px; }
.g-rpshelf p { width: 100%; margin: 0 0 2px; }
.g-rptopicbtn { min-height: 44px; }
.g-rpfillmsg { width: 100%; font-size: .9rem; color: var(--ink-soft, #55503F); }
.g-rprows { list-style: none; margin: 4px 0 8px; padding: 0; display: grid; gap: 10px; }
.g-rpbrow input { width: 100%; min-height: 48px; font: inherit; padding: 8px 12px;
  border-radius: 12px; background: var(--white, #FFFDF8);
  border: 1px solid rgba(33, 29, 22, .28); }
.g-rpverdicts { margin: 14px 0 6px; }
.g-rperr { display: block; margin-top: 4px; font-size: .9rem; font-weight: 700;
  color: var(--orange-deep, #B54800); }
.g-rperr:empty { display: none; }

/* ---------- one option and its pull-down ----------
   The row inherits .g-rankrow's select sizing (48px, full width, focus ring) from Rank My
   Three, which is the same control doing the same job — one list, one set of rules for it. */
.g-rprow label { display: block; }
.g-rprow select option:disabled { color: var(--ink-soft, #55503F); }
/* ---------- WO250: the designer's guessing screen, and the lock beneath the builder ----------
   TWO DECLARATIONS AND NO NEW LAYOUT. Matt's ruling was that the designer's post-lock screen
   takes the GUESSER'S OWN LAYOUT, so it is the same .g-rprow it always was: the only thing
   drawn here is the second line of the label — "Guess — Ada's verdict" — which reads as fine
   print under the option it is about, exactly like every other m-fine on this surface.
   .g-rplockrow puts the pill and its one line of fine print on one row and lets them stack on a
   phone, which is .g-rphelp's own arrangement borrowed rather than a third one invented. */
.g-rpguesslab { display: block; margin-top: 2px; font-size: .9rem; font-weight: 400;
  color: var(--ink-soft, #55503F); }
.g-rprow label .g-rpopt { font-weight: 700; }
.g-rplockrow { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.g-rplockrow .m-fine { margin: 0; flex: 1 1 12rem; }

/* ---------- what a member sees after they have locked in ---------- */
.g-rplocked { list-style: none; margin: 0 0 10px; padding: 0; display: grid; gap: 8px; }
.g-rplocked li { padding: 8px 12px; border-radius: 10px; background: var(--cream, #FAF5EC);
  border: 1px solid rgba(33, 29, 22, .06); display: grid; gap: 2px; }
.g-rpopt { font-weight: 700; }
.g-rpsaid { font-size: .92rem; color: var(--ink-soft, #55503F); }

/* ---------- the reveal: three rows, two columns and a mark ----------
   THE MARK IS A SHAPE AND THE ROW IS A WEIGHT. The tint is the third signal rather than the
   only one — .g-right and .g-wrongmark both carry a border and a left rule, so the two rows
   are told apart with the colour switched off. */
.g-rprows2 { list-style: none; margin: 0 0 10px; padding: 0; display: grid; gap: 8px; }
.g-rprevrow { padding: 10px 12px; border-radius: 10px; background: var(--cream, #FAF5EC);
  border: 1px solid rgba(33, 29, 22, .08); border-left: 4px solid rgba(33, 29, 22, .18);
  display: grid; grid-template-columns: 1fr auto; gap: 4px 10px; align-items: center; }
.g-rprevrow .g-rpopt { grid-column: 1 / 2; }
.g-rprevrow .g-rpmark { grid-column: 2 / 3; grid-row: 1 / 4; }
.g-rprevrow.g-right { background: var(--orange-soft, #FCEBD2);
  border-color: var(--orange-deep, #B54800); border-left-color: var(--orange-deep, #B54800); }
.g-rprevrow.g-wrongmark { border-left-color: rgba(33, 29, 22, .38); }
.g-rpcol { grid-column: 1 / 2; display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; }
.g-rpcol .m-fine { margin: 0; }
.g-rpline { margin: 6px 0 10px; font-weight: 700; }

@media (max-width: 560px) {
  .g-rphelp, .g-rplockrow { flex-direction: column; align-items: stretch; }
  .g-rphelp .m-fine, .g-rplockrow .m-fine { flex: 1 1 auto; }
  .g-rptopicbtn { width: 100%; }
}

/* ============================================================================
   WO166 — WINNER STAYS: the builder, the arena, the boss, the two columns
   ============================================================================
   THE ONE RULE THIS FILE HAS KEPT SINCE WO153a IS KEPT HERE, AND IT TOOK A DECISION TO KEEP
   IT. The work order says the "no new keyframes" rule does not bind games.css and invites a
   light theatrical transition (§18: "puff of smoke, card sliding in, flip animation"). This
   file says the opposite three times over, in its own headers, and deployed reality wins over
   an order: NOT ONE KEYFRAME RULE IS DECLARED IN THIS FILE, STILL. (smoke-wo153a greps for the
   at-rule by name, so the literal cannot be written here even inside a comment — which is
   exactly the kind of pin that keeps a rule true.)

   So the transition is a TRANSITION — a CSS `transition` property on a class the page adds for
   one draw, which is a different thing from an animation and needs no keyframe rule. The
   champion card and the incoming challenger settle in from a small offset over 180ms; the
   Final Boss's card does the same thing from a little further and a little slower, which is
   §20's "slightly enhanced treatment" and is the whole of it. Nothing loops, nothing repeats,
   and the longest thing on this screen lasts a quarter of a second — §18's own budget ("quick
   enough that repeated rounds continue to feel fast").

   AND IT IS OFF ENTIRELY UNDER REDUCED MOTION, which is the correct answer here rather than
   the house's usual "hold the end state still": there is no state being carried by this
   movement. The champion is labelled 'Current champion' in words on the card, the boss has a
   kicker and a sentence, and the round number is printed. Somebody who has asked for no
   motion loses decoration and not one fact — which is the test the standing rule actually
   applies (see member.css's note on .m-attention, where the ring IS the fact and so is held).

   EVERYTHING ELSE IS THIS FILE'S USUAL: the `.g-` namespace, 48px on every control, no colour
   carrying a state on its own, and not one string of copy anywhere below.
   ============================================================================ */

.g-wstopic { font-family: 'Fraunces', Georgia, serif; font-size: 1.15rem; font-weight: 600;
  margin: 4px 0 14px; }

/* ---- §3, the role choice ---- */
.g-wsroles { border: 1px solid rgba(33, 29, 22, .10); border-radius: 16px; padding: 16px;
  background: var(--cream, #FAF5EC); }
.g-wsroles h3 { margin: 0 0 6px; }

/* ---- §5–§10, the builder ---- */
.g-wsbuild { display: block; margin: 0 0 20px; }
.g-wsfield { display: flex; flex-direction: column; gap: 4px; margin: 0 0 14px; }
.g-wsfield input[type="text"], .g-wsfield select { min-height: 48px; padding: 8px 10px;
  border-radius: 12px; border: 1px solid rgba(33, 29, 22, .18); font: inherit;
  background: #fff; width: 100%; box-sizing: border-box; }
/* ============================================================
   WO233 (MATT, AUGUST 15 2026) — THE EXAMPLE'S CUE IS DRAWN AS THE PLACEHOLDER'S TWIN
   ------------------------------------------------------------
   MATT: the greyed example "Best 1970s Bands" reads as an entry somebody already made. The
   sentence under the field is the half a placeholder cannot do — it survives the first
   keystroke — and it is drawn in the SAME grey and the same italic as the greyed line it is
   talking about, so the eye ties the two together without a line of copy having to say "see
   above". It is deliberately NOT the ordinary .m-fine weight of the sentence under it: two
   identical-looking sentences would be two sentences, and this one is a caption on the box.
   THE COLOUR IS THE HOUSE'S PLACEHOLDER GREY at the ratio a caption needs (4.6:1 on the card),
   which is why it is not the browser's own placeholder colour — that is decorative and this is
   read. ============================================================ */
.g-wseg { font-style: italic; color: rgba(33, 29, 22, .62); }
.g-wsbuild input[type="text"]::placeholder { color: rgba(33, 29, 22, .48); font-style: italic; }
.g-wsgen { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 12px; }
.g-wsgenmsg { display: block; width: 100%; font-size: .92rem; }
.g-wsrankfine { font-weight: 700; margin: 0 0 6px; }
.g-wsslidefine { margin: 0 0 8px; }
.g-wsrows { list-style: decimal; padding-left: 28px; margin: 0 0 16px; }
.g-wsrow { display: flex; gap: 8px; align-items: center; margin: 0 0 8px; }
.g-wsrow input[type="text"] { flex: 1 1 auto; min-height: 48px; padding: 8px 10px;
  border-radius: 12px; border: 1px solid rgba(33, 29, 22, .18); font: inherit; background: #fff; }
/* ============================================================================
   WO190 — THE SLIDEABLE ROW
   ============================================================================
   THE NUMBER BOX IS GONE and its rule went with it: a row's PLACE IN THE LIST is its ranking,
   so the <ol>'s own numbering is the rank and there is nothing to type. What replaces it is a
   grip and two buttons, and the two buttons are not a consolation — they are always there,
   they are 48px, and the whole list can be ordered with them and a keyboard.
   `touch-action: none` ON THE GRIP IS LOAD-BEARING. Without it the browser claims the vertical
   gesture for scrolling and the pointermove events stop arriving mid-drag, which on a phone is
   a row that follows your thumb for ten pixels and then gives up. It is on the HANDLE ONLY, so
   the page still scrolls normally everywhere else on the builder — including over the text box
   that is most of the row.
   NO NEW KEYFRAMES, STILL: the dragged row is a shadow and a lift, both static. */
.g-wsgrip { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; min-height: 48px; cursor: grab; touch-action: none; user-select: none;
  font-size: 1.2rem; line-height: 1; opacity: .55; }
.g-wsmove { flex: 0 0 auto; display: inline-flex; gap: 4px; }
.g-wsmove button { min-height: 48px; min-width: 48px; padding: 4px 8px; border-radius: 12px;
  border: 1px solid rgba(33, 29, 22, .18); background: #fff; font: inherit; font-size: .8rem;
  line-height: 1.1; cursor: pointer; }
.g-wsmove button[disabled] { opacity: .4; cursor: default; }
/* ============================================================================
   WO247 (MATT, AUGUST 16 2026) — AND ONE MORE CONTROL ON THE ROW: REMOVE
   ============================================================================
   MATT, ON AN OBSCURE CATEGORY: he asked the generator for his own published papers and got some
   real ones and some inventions, and asked to be able to "edit or remove individual generated
   items before locking the list". Editing was already the text box; removing is this.

   IT IS 48px AND IT IS A WORD, on both of this builder's standing rules. Every control on this
   form is a thumb target, and a bare × is a picture — the two move buttons say 'Move up' and
   'Move down' for exactly this reason (see the WO190 note above), so the third one says
   'Remove'. Its accessible name adds the row's own number, which is the same join those two use.
   IT SITS AFTER THE MOVE BUTTONS AND IS DRAWN LIGHTER THAN THEM, which is the whole of the
   visual hierarchy here: reordering is what a Designer does constantly and removing is what they
   do once or twice, so the destructive one is the understated one at the end of the row rather than
   the loud one in the middle of it. It gets the house's deep orange on hover and focus, because
   an outline is the only carrier that survives forced-colours mode.
   NOTHING PULSES AND NOTHING IS RED. There is nothing to warn about: the form posts nothing
   until Save or Start, so a mis-tap costs a retype. The sentence beside the rows says so. */
.g-wsrm { flex: 0 0 auto; min-height: 48px; min-width: 48px; padding: 4px 10px;
  border-radius: 12px; border: 1px solid transparent; background: transparent; font: inherit;
  font-size: .8rem; line-height: 1.1; cursor: pointer; opacity: .7; color: inherit; }
.g-wsrm:hover, .g-wsrm:focus-visible { opacity: 1; border-color: var(--orange-deep, #B54800);
  color: var(--orange-deep, #B54800); }
.g-wsrmfine { margin: 0 0 8px; }
.g-wsdragging { box-shadow: 0 6px 18px rgba(33, 29, 22, .18); border-radius: 12px;
  background: #fff; }
.g-wsdragging .g-wsgrip { cursor: grabbing; }
/* A REFUSAL IS NOT A COLOUR. It is a sentence, in the flow, in bolder type — so it survives
   forced-colours mode and a colour-blind reader, exactly as .g-rperr and .g-mypick do. */
.g-wserr:not(:empty) { display: block; font-weight: 700; margin-top: 4px;
  color: var(--orange-deep, #B54800); }
.g-wsready { font-weight: 600; margin: 8px 0 16px; }
.g-wswait { font-style: italic; margin: 12px 0; }

/* ---- §12, the library ---- */
.g-wslib { border-top: 1px solid rgba(33, 29, 22, .10); padding-top: 14px; margin-top: 18px; }
.g-wslist { list-style: none; padding: 0; margin: 10px 0 0; }
.g-wslistrow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  padding: 10px 0; border-bottom: 1px solid rgba(33, 29, 22, .06); }
.g-wslisttopic { font-weight: 700; flex: 1 1 12rem; }
.g-wslistdo { display: flex; gap: 8px; align-items: center; }
/* WO233 — THE LIBRARY IS ONE CONTROL NOW. The three rules WO166's cards needed are kept above
   because the shape is still drawn at the end of a game (the per-round Save blocks), and the
   builder's own block is a .g-wsfield select like every other pull-down on this screen — which
   is the point: it inherits the 48px target, the radius and the full width from the rule at the
   top of the builder rather than inventing a second look for the same kind of thing.
   THE TWO BUTTONS SIT ON THEIR OWN ROW and wrap on a 390px phone, so 'Use a previous list' and
   'Delete' never end up shoulder to shoulder at thumb width. */
.g-wslibdo { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 6px; }
.g-wslibdo [hidden] { display: none; }

/* ==========================================================================================
   WO298 (MATT, AUGUST 17 2026) — THE LIBRARY'S HOUSEKEEPING, AND IT LOOKS LIKE THE BUILDER
   ==========================================================================================
   MATT: "see all my lists, edit a list's contents, delete a list."

   THE EDITOR IS NOT A SECOND KIND OF SCREEN. Its rows are `.g-wsrow` — the same class the
   builder's rows wear — so the 48px boxes, the 44px handle, the Remove and the flex line all
   come from the rules at the top of this file and nothing about a row is said twice. What is
   added here is the CONTAINER: an inset panel that makes clear the thing being edited is a
   saved list rather than the game about to be started, which is the one thing a member standing
   inside a builder could get wrong.
   THE METADATA LINE IS A LINE AND NOT A CARD. WO233 has composed `meta` for every row since it
   built the dropdown and nothing ever drew it; it sits directly under the select as fine print,
   where it answers "which of these is which" without adding a control.
   NO NEW COLOUR AND NO NEW ANIMATION. The panel is the room's own cream on the form's white,
   the same pair every other inset on this page uses, and this file's standing law since WO153a
   is that it adds no keyframes.
   ========================================================================================== */
/* WO298 — THE ONE PRE-GAME QUESTION ON A MENU CARD (One Word's board size). It is a
   `.g-wsfield` like every other pull-down in this feature, so the 48px target, the radius and
   the full width all come from that rule; what it takes of its own is the air that keeps it from
   sitting on the blurb above or the two buttons below. */
.g-setupask { margin: 10px 0 12px; }

.g-wslibmeta { margin: -4px 0 8px; }
.g-wslibmeta:empty { display: none; }
.g-wsled { margin: 10px 0 4px; padding: 14px; border-radius: 14px;
  background: var(--cream, #FAF5EC); border: 1px solid rgba(33, 29, 22, .12); }
.g-wsled[hidden] { display: none; }
.g-wsledhead { font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 1.02rem;
  margin: 0 0 10px; }
.g-wsledrows { margin-bottom: 10px; }
/* WO268 WROTE THESE TWO DOWN AND COULD NOT WRITE THEM HERE — its own note says so: the 44px
   floor on the handle and the shrinkable text box were held inline because games.css was outside
   that order. This order owns this file, so the EDITOR's rows take them from the stylesheet,
   which is where a rule about a control's size belongs. WO268's own two inline styles are left
   exactly where they are: moving them would move a pin its suite counts. */
.g-wsled .g-wsgrip { min-width: 44px; }
.g-wsled .g-wsrow input[type="text"] { min-width: 0; }
.g-wsleddo { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 6px; }

/* ---- §15–§20, the arena ---- */
.g-wsarena { border: 1px solid rgba(33, 29, 22, .10); border-radius: 18px; padding: 16px;
  background: var(--cream, #FAF5EC); margin: 0 0 18px; }
.g-wsround { font-size: .92rem; opacity: .75; margin: 0 0 10px; }
.g-wskicker { font-family: 'Fraunces', Georgia, serif; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; font-size: .95rem; margin: 0 0 2px; }
.g-wscards { display: flex; flex-wrap: wrap; align-items: stretch; gap: 12px; }
.g-wscard { flex: 1 1 12rem; min-width: 11rem; border: 1px solid rgba(33, 29, 22, .14);
  border-radius: 16px; padding: 14px; background: #fff; display: flex; flex-direction: column;
  gap: 10px; }
/* THE CHAMPION IS ALWAYS ON THE LEFT (§18) and says so in words as well as in position —
   `order` alone would be lost to a screen reader and to a narrow single-column phone. */
.g-wschamp { order: 0; }
.g-wschall { order: 2; }
/* THE "vs." CARRIES NO OPACITY. It is aria-hidden and decorative, and axe still measures it —
   rightly: a low-contrast glyph is unreadable whether or not a screen reader skips it. Full
   ink, small type, and the spacing does the de-emphasising instead. */
.g-wsvs { order: 1; align-self: center; margin: 0; font-weight: 700; font-size: .85rem;
  letter-spacing: .08em; text-transform: uppercase; }
.g-wslegend { margin: 0; font-size: .82rem; letter-spacing: .05em; text-transform: uppercase;
  opacity: .7; }
.g-wsname { margin: 0; font-family: 'Fraunces', Georgia, serif; font-size: 1.3rem;
  font-weight: 600; line-height: 1.25; }
.g-wschoose { min-height: 48px; margin-top: auto; }
.g-wswatch { font-weight: 600; margin: 12px 0 2px; }

/* THE ENTRANCE. A `transition`, not an animation: the class is on the card for the one draw
   that follows a choice, and the properties settle from their offset to their resting values.
   No keyframe, nothing to loop, and nothing to clean up.
   ============================================================================
   WO232 (MATT, AUGUST 15 2026) — AND IT PLAYS AT A PACE SOMEBODY CAN WATCH
   ============================================================================
   MATT: "it took about four seconds to register and then animated in about a quarter second.
   Invert that — register fast, animate at a watchable pace."

   THE OTHER HALF OF THE INVERSION IS site/assets/games.js's (the tap now registers under the
   thumb instead of waiting out a round trip, and the redraw is held until the beat finishes);
   this half is four numbers. .18s becomes .52s, and the ghost's .24s becomes .7s — about three
   times the old budget, which is the difference between a flicker and a movement.
   §18's OWN BUDGET IS SUPERSEDED, DELIBERATELY, AND IT IS RECORDED HERE. WO166 wrote "quick
   enough that repeated rounds continue to feel fast" and spent a quarter of a second on it;
   Matt has now watched it and ruled the other way. The reasoning under the old number stays
   above so the trail is readable — the number is what changed, not the principle that a game
   should not drag, and half a second is still half a second.
   STILL NOT ONE KEYFRAME RULE IN THIS FILE. Everything below is a `transition` on a class the
   page adds for one draw, except the ring, which BORROWS member.css's own keyframe by name
   rather than declaring a second one — see .g-wspicked. */
/* ============================================================================
   WO247 (MATT, AUGUST 16 2026) — THE MOVEMENT DID NOT READ, AND THE REASON WAS THE DISTANCE
   ============================================================================
   MATT: "the fading of the loser now reads well on desktop and mobile both. The slide from
   challenger slot to champion slot still does not — on either."

   THE MOVEMENT WAS NEVER A SLIDE. WO190 described one and WO232 slowed one down, and what the
   stylesheet actually said was 34 PIXELS. The champion slot and the challenger slot are a whole
   card apart — three hundred-odd pixels on a desktop — so a card that began 34px to the right of
   where it was going did not travel from the challenger's slot to the champion's: it twitched in
   place. Slowing a twitch from a quarter of a second to half a second makes it a slow twitch,
   which is why WO232's pacing fix was right and still did not fix this.
   AND ON A PHONE IT WAS THE WRONG AXIS ENTIRELY. Under 560px the arena is a COLUMN — champion
   above, 'vs.' between, challenger below (see the media query further down, which has been there
   since WO166) — so the two slots are separated VERTICALLY. A horizontal translate on a vertical
   layout is not a small slide; it is a movement pointing at nothing. That is the whole of "on
   either".

   SO THE TRAVEL THAT SURVIVES IS MEASURED IN SLOTS RATHER THAN IN PIXELS, and it is spent on the
   one card that can carry it. `--ws-step` is a card's own width plus the gap and the 'vs.'
   between them; a percentage in a translate resolves against the ELEMENT's own box, and the two
   cards are the same size (both are `flex: 1 1 12rem`), so one step is the distance between the
   two slots at every screen width for free. No JavaScript measures anything and the arena does
   not change height or width while it plays — the cards are where they always were and a
   transform is moving the paint. The column gets the same step on the other axis, in the phone
   media query below, which is one declaration rather than a second mechanism.
   WHICH CARD CARRIES IT, AND WHY IT IS NOT THE CHAMPION, is written out at `.g-wsdefeat
   .g-wschamp` further down with the ghost that decided it.
   WHAT DID NOT CHANGE, DELIBERATELY: the three durations. WO232 measured .52s / .62s / .7s
   against Matt's own watching and smoke-wo232 pins every one of them against this file. The
   fault was never the pace; a card that now crosses a real distance in half a second is the
   movement that budget was written for.
   THE ARENA CLIPS, and that is this order's one new declaration of housekeeping. A card
   translated a full slot extends past the arena's edge for half a second, and a transform
   contributes to a page's scrollable area even though it contributes nothing to its layout — so
   without the clip a 390px phone would gain a scrollbar for the length of every arrival. The
   ring is a box-shadow four pixels outside the card and the arena's padding is sixteen, so
   nothing that should be seen is cut. ============================================ */
.g-wsarena { overflow: hidden; --ws-step: calc(100% + 44px); }
.g-wscard { transition: transform .52s ease-out, opacity .52s ease-out; }
/* THE NEXT CHALLENGER COMES IN FROM OFF THE TABLE — one slot beyond the challenger's own place,
   which is where the item that is about to arrive has been standing all along: nowhere. This is
   the movement in the arena, and it is the one that crosses nothing: no other card is in the
   space it travels through, and it carries no ghost. */
.g-wsenter .g-wschall { transform: translateX(var(--ws-step)); opacity: .25; }
/* AND THE CHAMPION SLOT DOES NOT TRAVEL AT ALL. This is `none` rather than WO190's six-pixel
   settle on purpose: on a matchup where the champion held its ground the item in that slot is
   the SAME item that was there a second ago, and a card that shifts is the screen dramatising a
   thing that did not happen. Where it DID change hands, the slot crossfades — see
   `.g-wsdefeat .g-wschamp` below, and the ghost note above it, which is where the reasoning is. */
.g-wsenter .g-wschamp { transform: none; }
/* §20 — THE BOSS ARRIVES FROM FURTHER AWAY AND A LITTLE SLOWER. That is the whole of the
   "slightly enhanced visual treatment", and it is two declarations rather than a second
   mechanism. The border weight carries the same fact without motion. */
.g-wsboss .g-wscard { transition-duration: .62s; }
.g-wsboss .g-wschall { border-width: 2px; }
/* WO190 — "at the final battle 'challenger' becomes 'final boss'". The WORD is the change and
   it arrives from the server (challenger_label); this is the half-step of elevation the order
   allows "if cheap" — the legend on the boss card only, full ink instead of the legend's usual
   .7, in the deep orange this file already uses for the thing that matters on a card. Every
   legend on this game is drawn uppercase, so it reads FINAL BOSS without the constant having to
   shout at a screen reader. Nothing moves and nothing new is minted. */
.g-wsboss .g-wschall .g-wslegend { opacity: 1; font-weight: 700; letter-spacing: .09em;
  color: var(--orange-deep, #B54800); }
/* WO247 — AND 'FURTHER AWAY' IS NOW FURTHER THAN A FULL SLOT, which is what it always said in
   words. Two dozen pixels past the ordinary entrance plus a little more shrink: the same
   half-step of elevation WO166 asked for, now measured against a distance that exists. */
.g-wsboss.g-wsenter .g-wschall {
  transform: translateX(calc(var(--ws-step) + 24px)) scale(.94); opacity: .2; }
/* ============================================================================
   WO190 (MATT, WO185, ANSWERED YES) — THE CHAMPION'S DEFEAT
   ============================================================================
   "the losing champion fades or explodes away, the challenger slides into the champion spot
   and takes the current-champion label."

   TWO MOVEMENTS, AND BOTH ARE TRANSITIONS. The GHOST (`.g-wsgone`) is the beaten champion,
   drawn once, in the champion's own place, and it fades and shrinks out of it; the card that
   won arrives from the challenger's side and settles into the same spot wearing the champion
   legend. The ghost is absolutely positioned over the champion slot so the arena does not
   change height while it goes — a layout that jumps under a thumb is worse than no animation.
   NOT ONE KEYFRAME RULE, STILL — this file's oldest promise, kept for the fourth order in a
   row. The classes are added for one draw and removed on the next frame (site/assets/games.js's
   wsSettle), which is what makes a `transition` play at all; WO166's own entrance has been
   waiting four seconds for a poll to release it since the day it shipped and now does not.
   THE WHOLE THING LASTS UNDER A THIRD OF A SECOND, which is §18's budget ("quick enough that
   repeated rounds continue to feel fast"). [WO232: superseded — see the note above .g-wscard.]
   AND IT CARRIES NO FACT. The reveal line under the arena says in words which item was kept
   and which was let go, and the card that stays is labelled 'Current champion' — so the
   reduced-motion rule below can hide the ghost outright and lose nothing but the theatre.
   [WO232: THE REVEAL LINE IS GONE FROM THAT SCREEN — Matt retired the running callouts — so
   the sentence that carried the fact for a reduced-motion reader is now the CARD ITSELF: the
   item that won is standing in the champion's slot with 'Current champion' over it, and the
   static ring below marks the one the player picked. Still a fact in words on the screen,
   still nothing carried by the movement, which is what the rule turns on.]
   ============================================================================
   WO232 (MATT, AUGUST 15 2026) — AND THE LOSING CHALLENGER GOES THE SAME WAY
   ============================================================================
   MATT: "a losing challenger disappears the same way a defeated champion does (the cloud of
   smoke) instead of the new option just popping in."

   SO THE GHOST HAS TWO SLOTS AND IS STILL ONE ELEMENT. `.g-wsdefeat` is the champion's defeat
   (WO190, untouched); `.g-wsheld` is this order's — the champion held its ground, and what
   leaves is the challenger, out of the challenger's own card, on the same transition. The
   challenger card gets the same `position: relative; overflow: hidden` the champion card has
   had since WO190, which is the whole of the plumbing.
   THE NEW OPTION STILL ARRIVES, and that is not a contradiction: `.g-wsenter` slides the next
   challenger in from the right exactly as it always did — what it no longer does is arrive
   into an empty slot with no account of what was there. */
.g-wschamp, .g-wschall { position: relative; overflow: hidden; }
/* ============================================================================
   WO247 (MATT, AUGUST 16 2026) — THE GHOST WAS RUNNING BACKWARDS, AND THAT IS THE CHAMPION
   THAT WOULD NOT DIE
   ============================================================================
   MATT: "the correct answer briefly slid over to the champion's spot, then got covered again by
   the SAME WRONG ITEM from the previous trial — maybe whatever starts out as the initial
   champion is persisting there in a way that it shouldn't."

   HE WAS DESCRIBING THESE FOUR LINES. Read the mechanism first, because the fault is only
   visible against it: the arena's beat classes are drawn ON in the markup and taken OFF on the
   next frame (site/assets/games.js's wsSettle) — so for every rule in this section, the state
   WITH the class is where the movement starts and the state WITHOUT it is where the movement
   ends. Every other rule here is written that way round. The ghost was written the other way.
   WHAT THAT MEANT, EXACTLY. `.g-wsgone` rested at `opacity: 1` and `.g-wsdefeat .g-wsgone` set
   it to 0 — so the beaten champion's name began each beat INVISIBLE and, the moment the class
   came off, FADED IN over seven tenths of a second and stayed there. It is absolutely positioned
   at inset:0 over the champion card with a white background, so what it covered was the item
   that had just won, legend and all. And it stayed covered until the next matchup redrew the
   arena — which on the Designer's screen is however long the Chooser takes to move.
   THAT IS ALL THREE HALVES OF HIS REPORT AT ONCE. The two screens disagreed because only the
   WATCHER is drawn a ghost (the Chooser watched the loser leave under their own thumb, and gets
   no ghost at all — see wsBeatOf); the second option matched because the challenger card has no
   ghost in it; and "briefly slid over, then got covered again" is the winner being drawn, then
   the previous trial's item fading in on top of it. It really was the previous champion
   persisting — not in any state, but in one CSS declaration pointing the wrong way.
   THE FIX IS THE TWO STATES SWAPPED. The ghost's resting state is GONE and its beat state is
   PRESENT, so it is there at the start of the beat and dissolves out of the slot — which is what
   WO190's own note directly above has always said it does, and what Matt means when he says the
   fading of the loser reads well. Nothing else about it moves: the same element, the same slot,
   the same .7s, the same two slots (`.g-wsdefeat` for the champion's, `.g-wsheld` for the
   challenger's), the same aria-hidden, the same `display: none` under reduced motion.
   ============================================================================ */
.g-wsgone { position: absolute; inset: 0; margin: 0; pointer-events: none; z-index: 1;
  display: flex; align-items: center; justify-content: center; padding: 14px;
  background: #fff; border-radius: 16px; box-sizing: border-box;
  font-family: 'Fraunces', Georgia, serif; font-size: 1.3rem; font-weight: 600;
  line-height: 1.25; text-align: center;
  transform: scale(.86) translateY(-10px); opacity: 0;
  transition: transform .7s ease-in, opacity .7s ease-in; }
.g-wsdefeat .g-wsgone, .g-wsheld .g-wsgone { transform: scale(1) translateY(0); opacity: 1; }
/* ============================================================================
   WO247 — AND THE SLOT THAT CHANGES HANDS CROSSFADES RATHER THAN TRAVELS
   ============================================================================
   MATT: "the fading of the loser now reads well on desktop and mobile both. The slide from
   challenger slot to champion slot still does not — on either."

   THE OLD SLIDE WAS 34 PIXELS, which is why it did not read: the two slots are a whole card
   apart on a desktop and are stacked VERTICALLY on a phone (the column media query below has
   been there since WO166), so a 34px horizontal nudge was a twitch at one width and a movement
   pointing at a wall at the other. Slowing a twitch down — which is what WO232's pacing fix did
   to it — makes a slow twitch.
   AND IT CANNOT SIMPLY BE MADE LONGER, which is the finding that decided this. The ghost lives
   INSIDE the champion card (WO190 put it there so it is the size of the slot at every width, and
   that reasoning is still right), and the card clips its own overflow. Travel the card a whole
   slot and the ghost of the beaten champion travels with it — so the item that just LOST would
   appear to slide into the champion's place, which is the animation saying the opposite of what
   happened.
   SO THE ORDER'S OWN NAMED ALTERNATIVE IS TAKEN: "a clean crossfade/reposition without transform
   travel across layout." The slot that changes hands crossfades — the beaten name dissolves out
   of it and the winner is standing underneath with the champion's legend already on — and the
   slot that does NOT change hands is where the movement lives: the next challenger arrives from
   a whole slot away, off the table, which is a distance that reads at 390 and at 1280 and is the
   one movement in the arena that crosses nothing.
   ONE RULE, STATED ONCE: A SLOT WITH A GHOST IN IT CROSSFADES; A SLOT WITHOUT ONE ARRIVES. On a
   defeat the ghost is in the champion's slot, so the champion crossfades and the challenger
   arrives. On a held matchup the ghost is in the challenger's slot, so the challenger crossfades
   and nothing travels — which is right, because nothing changed hands.
   VETO-ABLE, AND THE ALTERNATIVE IS ONE LINE: `.g-wsdefeat .g-wschamp { transform:
   translateX(var(--ws-step)); }` puts the literal slide back, at a distance that now reads, at
   the cost of the ghost riding across with it. ============================================ */
.g-wsdefeat .g-wschamp { transform: none; opacity: 1; }
.g-wsheld .g-wschall { transform: none; opacity: 1; }

/* ============================================================================
   WO232 — THE CHOICE REGISTERS UNDER THE THUMB, BEFORE THE SERVER HAS ANSWERED
   ============================================================================
   `.g-wsleaving` is put on the arena by the TAP (site/assets/games.js's wsRegisterChoice) and
   `.g-wsloser` on the card that was not tapped. Which card lost is known locally — there are
   two — so the smoke starts on the same tick as the thumb and the round trip happens under it.
   IT IS THE SAME MOVEMENT THE GHOST MAKES, on purpose: the item that goes goes the same way
   whether the member watching is the one who sent it away or the one who watched it happen.
   NOTHING IS CLICKABLE WHILE IT LEAVES. The other card's button is on its way out and a second
   tap on it would be a tap on a matchup that is over — the request is already refused by the
   server and by the page's own busy latch, and this makes it un-attemptable as well. */
.g-wsleaving .g-wscard { pointer-events: none; }
.g-wsloser { transition: transform .7s ease-in, opacity .7s ease-in; }
.g-wsleaving .g-wsloser { transform: scale(.86) translateY(-10px); opacity: 0; }

/* ============================================================================
   WO232 — THE WATCHER'S RING: THREE FLASHES ROUND THE ANSWER THE PLAYER PICKED
   ============================================================================
   MATT: "the watcher (the person who set up the game) gets animation too: a flashing ring
   around the answer the player picked — two or three flashes — then, if the challenger won,
   the slide over to the champion position."

   IT IS member.css's OWN RING AND THIS FILE MINTS NOTHING. `m-attention-ring` is the product's
   one attention treatment — the invitation card at the top of the games tab wears it, so does
   the start pill, and games.html has loaded member.css since the day it existed. What is
   declared here is a duration and a count for a card in an arena, which is three flashes rather
   than the strip's three slower ones: a watcher is looking straight at it, and 1.2s beats would
   put the slide nearly four seconds behind the choice.
   THIS FILE'S OLDEST RULE IS UNBROKEN. "No new keyframes in games.css" is about a SECOND
   implementation of an attention treatment drifting from the first; referring to member.css's
   keyframe by name is the opposite of that — it is the reuse the rule exists to force. Not one
   at-rule is declared in this file, still, and smoke-wo153a's grep for it still finds nothing.
   THE RING IS OUTSIDE THE CARD's BOX and is therefore unaffected by the `overflow: hidden` the
   ghost needs: an element does not clip its own box-shadow.
   THE FLASH ENDS BY ITSELF. The keyframe returns to a transparent ring at 100% and the count is
   finite, so nothing has to take the class off — which is also why the release that follows can
   be a plain timer rather than an animation listener. */
.g-wspicked { animation: m-attention-ring .55s ease-in-out 3; }

/* ============================================================================
   WO310 (MATT, AUGUST 18 2026) — THE LAST BATTLE, HELD FOR A BEAT BEFORE THE RANKINGS
   ============================================================================
   MATT, ON A PHONE: "it needed to show the last choice for a couple of seconds and then show
   the overall lineup and rankings that the two people gave." The screen used to go from a live
   matchup to two columns of ranking in one draw, so the result of the final battle was never on
   it at all.

   THE ARENA IS THE ARENA. `.g-wslast` is the same `.g-wsarena` every matchup is drawn in and it
   inherits every rule above — the border, the cream, the two cards, the column at 560px, the
   ring. There are exactly TWO declarations here and both are about the card that LOST.
   THE LOSING CARD IS DIMMED AND NOTHING ELSE. It is one card of two, it carries no legend (see
   site/assets/games.js's wsLastBattleHTML, where the reason for that is written out) and the
   winner beside it says 'Current champion' in words — so the dimming is decoration on top of a
   fact that is already stated, which is this file's standing rule for every treatment that is
   only a colour or only an opacity.
   NOTHING MOVES HERE AND THERE IS NOTHING FOR THE REDUCED-MOTION BLOCK TO TURN OFF. The hold is
   TIME rather than animation — a member who has asked for less motion still gets the result of
   their last choice on the screen for the same two and a half seconds — so this section is
   deliberately absent from the media query below. The RING inside it is `.g-wspicked`, which
   that block already makes static.
   NOT ONE NEW KEYFRAME, STILL. ======================================================= */
.g-wslast .g-wschall { opacity: .55; }
.g-wslast .g-wschall .g-wsname { font-weight: 500; }

/* ============================================================================
   WO318 (MATT, AUGUST 19 2026) — THE CATCH-UP BAR AND ITS EXIT
   ============================================================================
   MATT: "a 'Skip to now' pill sits with the replay so nobody is ever trapped watching a long
   backlog (a replay without an exit is an attention trap)."

   IT IS A BAR AND NOT A BANNER, and the distinction is the same one WO246 drew for the hovering
   notice: a banner floats over the page and follows the member down it, and this belongs to the
   arena directly under it. So it is in the flow, at the top of the game, the width of the arena
   and wearing the arena's own cream and border radius — a member reads the sentence, watches the
   thing it is about, and the exit is the last thing under their thumb before the cards.
   THE PILL IS THE HOUSE'S SMALL BUTTON (`.m-btn-small`, member.css) with one declaration on top
   of it: forty-four pixels of height, which is this file's standing tap target and the same one
   `.g-wschoose` carries four rules up. Nothing about its colour or its type is decided here.
   IT WRAPS AT 390 rather than squeezing, so the sentence takes the first line and the pill the
   second on a phone and they sit side by side on a desktop. One flex rule, no media query.
   NOT ONE MOVEMENT IS DECLARED HERE AND THERE IS NOTHING FOR THE REDUCED-MOTION BLOCK TO TURN
   OFF. That is the point rather than an omission: the order's own rule is that reduced motion
   gets "the same sequence, static swaps — order and time carry the story, not animation", so the
   replay's carrier is the PACE, which is site/assets/games.js's one number and is the same at
   both settings. What the bar does is say in words what is happening, which is the channel that
   works when every transition on the page is off.
   NOT ONE NEW KEYFRAME, STILL — this file's oldest promise, kept.
   ======================================================================= */
.g-wscatch { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  border: 1px solid rgba(33, 29, 22, .10); border-radius: 14px; padding: 10px 12px;
  background: var(--cream, #FAF5EC); margin: 0 0 12px; }
.g-wscatch p { margin: 0; }
.g-wscatchline { flex: 1 1 14rem; font-weight: 600; }
.g-wscatchskip { min-height: 44px; }

/* ---- the reveals ---- */
.g-wsplayed { list-style: none; padding: 0; margin: 0 0 16px; }
.g-wsreveal { padding: 10px 12px; border-left: 3px solid rgba(33, 29, 22, .12);
  margin: 0 0 8px; }
/* AN AGREEMENT IS A WEIGHT AND A BORDER, never a colour on its own. */
.g-wsagree { border-left-width: 5px; border-left-color: var(--orange-deep, #B54800); }
.g-wsagree .g-wsline { font-weight: 700; }
.g-wsline { margin: 0; }

/* ---- §21–§22, the results ---- */
.g-wsresults { margin: 0 0 18px; }
.g-wscols { display: flex; flex-wrap: wrap; gap: 16px; }
.g-wscol { flex: 1 1 12rem; min-width: 10rem; }
.g-wscol h4 { margin: 0 0 6px; font-size: 1rem; }
.g-wscol ol { padding-left: 22px; margin: 0; }
.g-wscol li { padding: 3px 0; }
.g-wshigh { padding-left: 20px; margin: 10px 0; }
.g-wshonesty { margin: 12px 0 16px; }
.g-wsagain { flex-wrap: wrap; gap: 8px; }
/* ============================================================================
   WO190 — THE OVERLAP, THE ROUND KICKER AND THE HANDOVER
   ============================================================================
   THE HIGHLIGHT IS NEVER A COLOUR ON ITS OWN. An item both people put in their top tier gets
   WEIGHT, a RULE down its left side and a tint — three carriers, so it reads in forced-colours
   mode, on a monochrome screen and to a colour-blind reader, exactly as .g-wsagree does two
   sections up. The sentence under the columns says in words what has been marked, which is the
   fourth carrier and the one a screen reader gets.
   THE ROUND KICKER wears the same treatment as the Final Boss kicker, because it is the same
   kind of thing: a small word above a screen saying which part of the game this is. */
.g-wsboth { font-weight: 700; border-left: 3px solid var(--orange-deep, #B54800);
  padding-left: 8px; margin-left: -11px; background: rgba(181, 72, 0, .06); }
.g-wsoverlap { margin: 6px 0 10px; }
.g-wsroundkick { font-family: 'Fraunces', Georgia, serif; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; font-size: .85rem; opacity: .75;
  margin: 0 0 8px; }
.g-wsblock { padding: 0 0 6px; margin: 0 0 18px; }
.g-wsblock + .g-wsblock { border-top: 1px solid rgba(33, 29, 22, .10); padding-top: 16px; }
.g-wspast { border-top: 1px solid rgba(33, 29, 22, .10); padding-top: 16px; margin-top: 18px; }
.g-wshandover { border: 1px solid rgba(33, 29, 22, .10); border-radius: 16px; padding: 14px;
  background: var(--cream, #FAF5EC); margin: 0 0 16px; }
.g-wshandover h3 { margin: 0 0 4px; }
.g-wsinvite { margin: 0 0 16px; }

/* ON A PHONE THE ARENA IS ONE COLUMN, and the "vs." sits BETWEEN the two cards rather than
   beside them — which is where §15's own sketch puts it, and the only place it reads as a
   fixture rather than as a stray word. The champion is still first, which is "the champion
   stays on the left" said in the one direction a 390px screen has. */
@media (max-width: 560px) {
  .g-wscards { flex-direction: column; }
  .g-wscard { flex: 1 1 auto; min-width: 0; width: 100%; box-sizing: border-box; }
  .g-wsvs { align-self: flex-start; }
  /* ==========================================================================================
     WO247 — AND ON A PHONE THE SLOTS ARE ONE ABOVE THE OTHER, SO THE TRAVEL IS TOO
     ==========================================================================================
     THIS IS THE HALF OF MATT'S "on either" THAT NOTHING HAD EVER ADDRESSED. Every movement in
     the arena was written as translateX, and this block has turned the arena into a COLUMN since
     WO166 — so on the device the game is actually played on, the challenger has been BELOW the
     champion the whole time and the slide has been pointing sideways at a wall. A card that
     travels along the wrong axis does not read as a small slide; it reads as a glitch, which is
     what he saw.
     ONE STEP, THE OTHER WAY, and the percentage resolves against the card's own HEIGHT here
     exactly as it resolved against its width above. The two cards carry the same three things (a
     legend, a name, a button) so they are the same height, and the constant is the gap plus the
     'vs.' line between them rather than the desktop's gap plus the 'vs.' beside them.
     THE RULES ARE THE ONES ABOVE, restated on this axis rather than added to. They are repeated
     in full rather than patched with a variable for the direction because a transform is one
     property: a rule that set only the axis would still be carrying the desktop's translateX
     underneath it. Order matters and it is deliberate — this block sits BEFORE the
     reduced-motion block below, so an honest phone in reduced motion still gets `transform:
     none` from there and not a vertical arrival from here. */
  .g-wsarena { --ws-step: calc(100% + 40px); }
  .g-wsenter .g-wschall { transform: translateY(var(--ws-step)); opacity: .25; }
  .g-wsboss.g-wsenter .g-wschall {
    transform: translateY(calc(var(--ws-step) + 24px)) scale(.94); opacity: .2; }
  /* the two crossfading slots are the same on this axis as on the other, because a crossfade
     has no axis — they are restated only so the rule above them cannot reach them. */
  .g-wsdefeat .g-wschamp { transform: none; opacity: 1; }
  .g-wsheld .g-wschall { transform: none; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  /* SILENCE IS THE RIGHT ANSWER HERE, and only here: this movement carries no state. Every
     fact it decorates — which card is the champion, that this is the Final Boss, which matchup
     of how many — is printed in words on the same card. */
  .g-wscard { transition: none; }
  .g-wsenter .g-wschall, .g-wsenter .g-wschamp,
  .g-wsboss.g-wsenter .g-wschall { transform: none; opacity: 1; }
  /* WO190 — AND THE DEFEAT IS A STATIC SWAP. The ghost is not drawn at all and the card that
     won is simply in the champion's place, which is the same screen everybody else arrives at
     a quarter of a second later. The order's own requirement, and the right one here for the
     reason the note above already gives: this movement carries no fact. */
  .g-wsgone { display: none; }
  .g-wsdefeat .g-wschamp, .g-wsdefeat .g-wschall { transition: none; transform: none;
    opacity: 1; }
  /* ==========================================================================================
     WO232 — AND THE THREE NEW MOVEMENTS ARE HONEST HERE TOO
     ==========================================================================================
     MATT's standing rule, and this order says it again: "honest under reduced-motion".
       THE HELD CHALLENGER is the same static swap the defeat is — the ghost is already
         `display: none` above, and the card that arrives is simply there.
       THE TAP'S OWN SMOKE does not play. The card that lost is not faded out from under a
         thumb; the redraw replaces it, and site/assets/games.js sets no hold at all in this
         mode, so the screen moves as soon as the server answers rather than sitting still for
         seven tenths of a second with nothing happening on it.
       THE RING IS A RING AND NOT A LOOP. This is the one of the three that keeps something,
         because it CARRIES A FACT for the reader who has just lost the reveal line: it marks
         the answer the player picked. So it is the house's own reduced-motion treatment —
         member.css holds `.m-attention` still as a static ring for exactly this reason — and
         it is held until the next matchup redraws the arena. A ring that flashes is decoration;
         a ring that is simply there is a label. */
  .g-wsheld .g-wschamp, .g-wsheld .g-wschall { transition: none; transform: none; opacity: 1; }
  .g-wsloser, .g-wsleaving .g-wsloser { transition: none; transform: none; opacity: 1; }
  .g-wspicked { animation: none;
    box-shadow: 0 0 0 4px rgba(181, 72, 0, .55), var(--shadow); }
}

/* ============================================================================
   WO232 — THE ROUND-END SCREEN, AND IT IS DELIBERATELY NOT A WINNER STAYS CLASS
   ============================================================================
   `.g-roundend` is the SHARED panel (site/assets/games.js's roundEndHTML, composed by
   lib/games.mjs's roundEndPanel): a head, whatever blocks the game handed it, a button onward
   and the talk window. WO234 draws a Lesser Evils trial into the same frame, which is why not
   one rule below mentions a ranking, a column or a matchup.
   THE TALK WINDOW READS AS A CONVERSATION AND NOT AS A FORM. The lines above the box are
   `.g-talklines`, the same element the per-trial boxes have used since WO188 — so a line from
   the other person wears their name in the same place, in the same type, on every game surface
   in the product. All this section adds is the room round it and the line over it.
   IT IS OPEN, WHICH IS THE ONE THING IT DOES DIFFERENTLY. Matt's words: "a 'Want to talk about
   it?' line over a small open chat window". No pill, no disclosure, nothing to press first. */
.g-roundend { margin: 0 0 18px; }
.g-roundend > h3 { margin: 0 0 12px; }
/* THE BUTTON ONWARD IS 48px, which is the house's touch target and not a preference: the
   primary button's own padding comes to 46, and two pixels is the difference between a control
   that passes the standing rule and one that only looks as though it does. */
.g-roundend [data-roundnext] { min-height: 48px; }
.g-retalk { border-top: 1px solid rgba(33, 29, 22, .10); margin: 18px 0 0; padding-top: 14px; }
.g-retalkhead { margin: 0 0 8px; font-size: 1rem; font-weight: 700; }
.g-retalk .g-talklines { margin: 0 0 10px; }
.g-retalk .g-roundsay { margin: 0; }
/* ----------------------------------------------------------------------------
   WO234 (MATT, AUGUST 15 2026) — "A SMALL OPEN TEXT WINDOW THAT EXPANDS A LITTLE AS THEY CHAT"
   ----------------------------------------------------------------------------
   His three words are SMALL, OPEN and EXPANDS A LITTLE, and the third one is the one that needs
   a rule: a trial's window sits between the reveal above it and the 'Next trial' pill below it,
   so a conversation that grew without limit would push the way onward off the bottom of a
   phone. The list of lines therefore GROWS TO ABOUT FOUR LINES AND THEN SCROLLS INSIDE ITSELF —
   the window gets taller as they talk and then stops, and nothing older is lost because the
   whole thread is one tap away in Messages.
   RECORDED DEFAULT, VETO-ABLE: 9.5rem is roughly four short lines at this type size on a 390px
   screen. Say the word and it is one number.
   IT IS SCOPED TO A WINDOW THAT HAS NO BLOCKS IN IT, which is what `.g-roundend-bare` names —
   Winner Stays' round-end screen is a whole screen of its own with nothing under it to protect,
   and its window is deliberately left to grow as it always has.
   NO NEW KEYFRAMES, for the sixth order running: nothing here animates. */
.g-roundend-bare { margin: 14px 0 0; }
.g-roundend-bare .g-retalk { margin-top: 0; }
.g-roundend-bare .g-talklines { max-height: 9.5rem; overflow-y: auto; }
/* THE BOX STAYS TWO ROWS TALL WHATEVER IS ABOVE IT. A textarea that grew with the conversation
   would be the "giant chat" Matt struck on this page in WO187A, arriving one trial at a time. */
.g-roundend-bare .g-roundsay textarea { min-height: 0; }

/* ============================================================
   WORK ORDER 170 — THE SPINE AND THE TAB. August 13, 2026.
   ------------------------------------------------------------
   THE FILE'S THREE STANDING RULES ARE UNBROKEN HERE, and the first is the one worth naming
   again: NO NEW KEYFRAMES. The invitation at the top of the tab wears member.css's own
   `.m-attention` — three beats at 1.2s and then still, with a STATIC RING under
   prefers-reduced-motion — and nothing below animates anything of its own.

   ONE RECORDED FINDING AND ITS FIX. Since WO153a this page has been writing `.n-attention` on
   an invitation row, and `.n-attention` is defined in network.css — which games.html has never
   loaded. The class matched no rule and the arrival flash the order asks for has never fired
   on this tab. It is fixed by wearing the class this page's own stylesheets define
   (`.m-attention`, member.css) rather than by copying network.css's rule here, which would
   have been the second implementation of the one attention treatment in the product.
   ============================================================ */

/* ---------- the invitation at the top, set off on its own ---------- */
.g-invitetop { margin: 0 0 30px; }
.g-invitehead { font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 1.05rem;
  margin: 0 0 10px; color: var(--ink-soft, #55503F); }
/* THE CARD IS SET OFF BY ITS OWN GROUND rather than by a flash, so it still reads as separate
   after the three beats are over and for a reader who never saw them. */
/* ============================================================
   WO253 (MATT, AUGUST 15 2026) — AND THIS CARD IS DARK ORANGE, PULSING UNTIL IT IS HANDLED
   ------------------------------------------------------------
   MATT'S ITEM 3: "the games-tab invitation card gains the same dark orange pulse-until-handled
   treatment so the grammars agree." The centre-then-dock signal this order puts on every member
   page and this card are the SAME PIECE OF NEWS in two registers — the arrival and the standing
   evidence — and until tonight they looked like two different products.

   WHAT DIED HERE, VERBATIM:

       .g-invitecard { background: var(--orange-soft, #FCEBD2); … }

   LIGHT ORANGE with ink on it, plus WO170's `m-attention` finite three-beat ring on the first
   draw. Matt has ruled the treatment for these two events dark orange, and pulse-until-handled:
   an unanswered invitation is still pending, and a signal about a pending thing that has stopped
   signalling is a signal that was missed.
   THE COLOUR IS `--orange-deep` (#B54800) CARRYING WHITE at 5.4:1 — comfortably AA, and the same
   ground the signal card wears, from the same two tokens. Every piece of text on the card is
   repainted below rather than left to inherit: `.m-fine` (#6E685A) and `.g-said` (#8A3A22) are
   both ink-family colours chosen for a cream card and would be unreadable on this one.
   THE PRECEDENCE OF THE PULSE IS DECLARED RATHER THAN LEFT TO SOURCE ORDER. `.m-hs-pulse` lives
   in member.css and this file is loaded after it, so the plain class would already win — but a
   rule that is correct because of the order two <link> tags happen to be in is a rule that
   breaks the day somebody reorders them. The scoped selector below says it on purpose.
   ============================================================ */
.g-invitecard { background: var(--orange-deep, #B54800); border-radius: 18px;
  padding: 18px 20px; border: 1px solid rgba(255, 253, 248, .35);
  color: #FFFDF8;
  box-shadow: 0 6px 18px rgba(33, 29, 22, .18); }
.g-invitecard + .g-invitecard { margin-top: 12px; }
.g-inviteline { font-family: "Fraunces", Georgia, serif; font-size: 1.12rem; margin: 0 0 12px; }
.g-invitecard p:last-child { margin-bottom: 0; }
.g-invitecard .m-fine, .g-invitecard .g-said { color: #FFFDF8; }
/* THE THREE PILLS ON A DARK GROUND. The primary keeps its weight by inverting rather than by
   shouting — cream ground, ink on it — and the two secondaries become outlines in the same
   cream. Nothing about which control is primary changes; only what it is sitting on. */
.g-invitecard .btn-primary { background: #FFFDF8; color: var(--ink, #211D16);
  box-shadow: 0 8px 24px rgba(33, 29, 22, .22); }
.g-invitecard .btn-primary:hover { background: #FFFFFF; box-shadow: 0 12px 30px rgba(33, 29, 22, .28); }
.g-invitecard .m-btn-small { background: transparent; color: #FFFDF8;
  border-color: rgba(255, 253, 248, .7); }
/* ---- WO246: THE HOVER DARKENS RATHER THAN LIGHTENS, and that is a contrast fix ----
   A cream wash over the card's dark orange composites to a LIGHTER orange, and cream text on it
   falls just under the 4.5:1 floor — a latent AA failure on all three of this card's secondary
   pills that nobody had met because nothing on it was hovered in a suite until WO246 added a
   fourth control and opened it in the browser half. Darkening the ground instead keeps the
   card's own colour, keeps the "this is hovered" signal, and puts the composite comfortably
   above the floor. The border still brightens, so the state is carried twice. */
.g-invitecard .m-btn-small:hover { background: rgba(20, 18, 15, .20);
  border-color: #FFFDF8; }
.g-invitecard .btn:focus-visible, .g-invitecard .m-btn-small:focus-visible {
  outline: 3px solid #FFFDF8; outline-offset: 3px; }
/* PULSE UNTIL HANDLED — member.css's keyframes, scoped here so the precedence is a decision.
   No iteration count: the card leaves because the invitation was ANSWERED, never because an
   animation ran out. The reduced-motion branch is the static high-contrast ring, never nothing. */
.g-invitecard.m-hs-pulse { animation: m-hs-beat 1.4s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .g-invitecard.m-hs-pulse { animation: none;
    box-shadow: 0 0 0 10px rgba(181, 72, 0, .48), 0 6px 18px rgba(33, 29, 22, .18); }
}

/* ---------- WO170: the count beside a name ----------
   Quiet, and deliberately not a badge: no pill, no ring, no colour of its own. It is a fact
   about the two of them ('4 games'), which is the whole of what Principle 4's amendment
   allows, and it must not read as a score. */
.g-played { color: var(--ink-soft, #55503F); font-size: .88rem; font-variant-numeric: tabular-nums; }
.g-personlink .g-played + .g-state::before { content: "· "; }

/* ---------- WO170: the two pull-downs ----------
   Stacked on a phone, side by side from 560px, each with its own label above it. Both are the
   full 48px control this file requires everywhere. */
.g-pickpool2 { margin: 0 0 12px; }
.g-pickpool2 select { width: 100%; min-height: 48px; border-radius: 12px; padding: 8px 12px;
  font: inherit; border: 1px solid rgba(33, 29, 22, .18); background: var(--white, #FFFDF8); }
.g-pickpool2 select:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }
.g-pickbox { margin-top: 14px; }
@media (min-width: 560px) {
  .g-pickbox { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
  .g-pickbox > .g-said, .g-pickbox > p { grid-column: 1 / -1; }
}

/* ---------- WO170: the Under construction card ----------
   A NATIVE <details>, so the fold is the browser's own disclosure widget: keyboard-operable,
   its expanded state announced, and shut by default because the server said so.
   IT IS DELIBERATELY QUIET. Greyed ground, no shadow, no accent, no counter and nothing that
   could be mistaken for a badge — a card that looked like news would be the one thing
   Principle 19 forbids it to be. */
.g-uc { margin: 0 0 34px; background: var(--cream-deep, #F3EADA); border-radius: 18px;
  border: 1px solid rgba(33, 29, 22, .08); padding: 4px 18px; }
.g-ucsum { cursor: pointer; padding: 14px 0; min-height: 48px; display: flex;
  align-items: center; color: var(--ink-soft, #55503F); }
.g-ucsum:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px;
  border-radius: 10px; }
.g-uctitle { font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 1.05rem; }
.g-uclede { margin: 0 0 14px; max-width: 44rem; }
.g-uclist { padding-bottom: 16px; }
/* GREYED AND UNPLAYABLE, and it is the ground and the ink that say so rather than a label
   shouting it. There is no Play control inside one of these cards at all — the markup does not
   draw one, so there is nothing here to disable. */
.g-ucitem { background: var(--cream, #FAF5EC); box-shadow: none;
  border: 1px dashed rgba(33, 29, 22, .18); color: var(--ink-soft, #55503F); }
.g-ucitem .g-menuname { color: var(--ink-soft, #55503F); }
.g-ucword { font-size: .82rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-soft, #55503F); margin: 8px 0 0; }

/* ============================================================
   WO171 (MATT, AUGUST 13–14 2026) — LESSER EVILS: ONE ROUND, AND THE REVEAL BY NAME
   ------------------------------------------------------------
   ONE ROUND FILLS THE CARD, so nothing here is a list. The two options are real <button>s the
   full width of the card, because the order's rule is that the tap IS the answer and a target
   you can miss is a target that costs somebody a round they cannot take back.
   NO NEW KEYFRAMES, still. The arrow does not animate; the chosen option does not pulse.
   ------------------------------------------------------------
   WO189 (MATT, AUGUST 14 2026) — AND THE REVEAL IS NO LONGER BY NAME OR SIDE BY SIDE. The
   heading above is WO171's and is kept as the record; the panel it describes is gone and its
   replacement is the block further down ("THE REVEAL, AS A COLUMN OF BOXES"). What is still
   true of this section is everything before that sentence: one round fills the card, the two
   options are full-width buttons because the tap is the answer, and nothing animates.
   ============================================================ */
.g-round { background: var(--white, #FFFDF8); border-radius: 18px; padding: 20px;
  box-shadow: 0 6px 18px rgba(33, 29, 22, .07); border: 1px solid rgba(33, 29, 22, .05); }
.g-round.g-revealed { background: var(--cream, #FAF5EC); }
/* HOW FAR IN. Quiet, small, and above everything — it is orientation, not news. */
.g-where { font-size: .82rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-soft, #55503F); margin: 0 0 14px; }
.g-choices { margin: 0 0 18px; }
.g-choices:last-of-type { margin-bottom: 6px; }
.g-choicelab { font-size: .95rem; font-weight: 700; color: var(--ink-soft, #55503F);
  margin: 0 0 10px; }
/* THE OPTION. 56px tall rather than the house floor of 48, because there are two of them and
   they carry a whole sentence each; a two-line clause at 48px is a cramped target. */
.g-choice { display: block; width: 100%; box-sizing: border-box; text-align: left;
  min-height: 56px; padding: 14px 16px; margin: 0 0 10px; font: inherit; line-height: 1.35;
  color: var(--ink, #211D16); background: var(--cream, #FAF5EC); cursor: pointer;
  border: 1px solid rgba(33, 29, 22, .14); border-radius: 14px; }
.g-choice:last-child { margin-bottom: 0; }
.g-choice:hover { border-color: rgba(33, 29, 22, .3); }
.g-choice:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 3px; }
/* THE ONE THEY TOOK. It stays visible and stays tappable — the first tap is changeable right
   up until the second one, which is the whole reason there is no submit button.
   ---- WITHDRAWN, WO189: THERE IS NO SUCH STATE ANY MORE ----
   WO188's phase gate replaces the answer screen with the guess screen the moment the answer is
   tapped, so a chosen option is never on the screen to be styled; the rule survives as the
   'Change my answer' control the gate offers instead. The declaration went with the
   `aria-pressed` attribute it partnered — see choiceBtn in site/assets/games.js, where that
   attribute is the whole of Matt's double-press bug. */

/* ============================================================
   WO189 (MATT, AUGUST 14 2026) — THE REVEAL, AS A COLUMN OF BOXES
   ------------------------------------------------------------
   WHAT WAS HERE: .g-facing — two people side by side with an arrow between them and green
   ticks laid over the arrow. His order takes all of it out ("the old arrows and overlapping
   check/X are gone") and replaces it with a straight read down the card: two boxes, a verdict
   with a large mark BESIDE it, the talk pill, then the same three again mirrored.
   WHY THE MARK IS A SIBLING AND NOT A BACKGROUND. "the check/X sits to the RIGHT of the text."
   So it is a flex row with the sentence first and the mark second, which also means it can
   never overlap the words at any width — the failure he was describing.
   COLOUR IS NEVER THE ONLY CARRIER, which is the standing rule and is what makes a green check
   and a red X safe here: the sentence says "You got it right!" or "You missed that one" in
   words, and the two marks are DIFFERENT SHAPES rather than one shape in two colours.
   NO NEW KEYFRAMES, still: nothing on this card animates.
   ============================================================ */
.g-revsec { margin: 4px 0 0; }
.g-revsec + .g-revsec, .g-revmirror { margin-top: 18px; }
/* THE MIRROR IS THE SAME PICTURE, QUIETER. It is about the other person's guess, and reading it
   as a second scoreboard of equal weight is how a reveal becomes a report card. */
.g-revmirror { padding-top: 16px; border-top: 1px solid rgba(33, 29, 22, .1); }
.g-revbox { background: var(--white, #FFFDF8); border: 1px solid rgba(33, 29, 22, .1);
  border-radius: 14px; padding: 12px 14px; margin: 0 0 10px; min-width: 0; }
.g-revhead { font-size: .82rem; font-weight: 700; letter-spacing: .03em;
  color: var(--ink-soft, #55503F); margin: 0 0 6px; }
.g-revans { margin: 0; font-family: "Fraunces", Georgia, serif; font-weight: 600;
  font-size: 1.06rem; line-height: 1.35; overflow-wrap: anywhere; }
/* THE VERDICT ROW. The sentence, then the mark, on one baseline. */
.g-verdictrow { display: flex; align-items: center; gap: 12px; margin: 12px 0 0; }
.g-verdicttext { font-size: 1.06rem; }
.g-mark { flex: none; width: 38px; height: 38px; display: block; }
.g-mark path { fill: none; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
/* THE ONE GREEN IN THIS PRODUCT, and the one red. */
.g-mark-check path { stroke: #1E7A46; }
.g-mark-x path { stroke: #A3282A; }
/* THE SENTENCE IS PLAIN INK IN BOTH STATES and the MARK carries the colour. The generic
   .g-verdict.g-right (deep orange, eight other games) would put orange words beside a green
   check, which is three colours saying one thing; this narrows it on this row only. */
.g-verdict.g-verdictrow.g-right, .g-verdict.g-wrongmark { color: var(--ink, #211D16); }
/* WAITING SAYS NOTHING ABOUT THE OTHER PERSON. Quiet, because it is a fact about the round. */
.g-verdict.g-waiting { font-weight: 600; color: var(--ink-soft, #55503F); }
.g-bothword { margin: 6px 0 0; font-weight: 600; color: var(--ink-soft, #55503F); }
/* THE COLLABORATIVE RUNNING TOTAL. It is about the two of them, so it is not coloured like a
   personal result and does not sit beside a mark — a plain sentence under the panel. */
.g-pairscore { margin: 18px 0 0; font-weight: 700; color: var(--ink-soft, #55503F); }

/* ---------- the per-round box, the button, the pill ---------- */
.g-roundsay { margin: 18px 0 0; }
.g-roundsay textarea { width: 100%; box-sizing: border-box; border-radius: 12px;
  padding: 10px 12px; font: inherit; min-height: 60px;
  border: 1px solid rgba(33, 29, 22, .18); background: var(--white, #FFFDF8); }
.g-roundsay textarea:focus-visible { outline: 3px solid var(--orange-deep, #B54800);
  outline-offset: 2px; }
.g-whyrow { margin: 14px 0 0; }
/* A REAL BUTTON, not the quiet text the other eight games use — the order's own word for it.
   ---- WO189: AND ON THIS CARD IT IS BURNT SIENNA ----
   MATT: "a burnt-sienna pill 'That's interesting. Tell me why you chose that'." --orange-deep
   (#B54800) IS that colour and is already the house's one deep orange — the Next pill wears it
   filled — so this is the existing token rather than a tenth hex code. It is drawn OUTLINED
   rather than filled so the two pills on the card are not the same weight: Next is the control
   that moves the game and stays the only solid one. */
.g-whybtn { min-height: 48px; background: var(--white, #FFFDF8);
  border: 2px solid var(--orange-deep, #B54800); color: var(--orange-deep, #B54800);
  font-weight: 700; border-radius: 999px; padding: 12px 22px; }
.g-whybtn:hover { background: var(--orange-soft, #FCEBD2); }
.g-nextrow { margin: 16px 0 0; }
/* THE ORANGE PILL. It is the only filled orange control on this card, because it is the only
   one that moves the game forward. */
.g-next { min-height: 48px; background: var(--orange-deep, #B54800);
  border: 1px solid var(--orange-deep, #B54800); color: var(--white, #FFFDF8);
  font-weight: 700; border-radius: 999px; padding: 12px 22px; }
.g-next:hover { filter: brightness(1.06); }
@media (max-width: 560px) {
  /* WO189 — the reveal is a single column at every width now, so there is nothing to stack: the
     rule that stacked .g-facing's three columns went with .g-facing. What is left is the two
     full-width controls, which is this file's standing habit for a row of pills on a phone. */
  .g-whybtn, .g-next { width: 100%; box-sizing: border-box; text-align: center; }
}

/* ---------- WO170: the four ending pills ----------
   They wrap on a phone and go full width there, which is this file's standing rule for a row
   of controls (.g-menufoot / .g-actions do the same).
   ---------- WO188 (MATT, AUGUST 14 2026): ALL FOUR ARE WHITE ----------
   HIS WORDS: "make all the pills white. Don't leave FF as the sole orange one." The Fast Friends
   door carried .btn-primary and was the one filled control on the row; it wears .g-pill now like
   its three neighbours. .g-ffdoor IS STILL ON IT — that class is the handle the handoff is
   identified by, on the page and in two suites, and it carries no colour of its own, so the
   restyle is a restyle rather than a rename.
   NOTHING ELSE ABOUT THE ROW MOVED: same order, same wrap, same 48px, same full width on a
   phone. */
.g-pills { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.g-pills .btn { min-height: 48px; }
.g-pill { background: var(--white, #FFFDF8); border: 1px solid rgba(33, 29, 22, .18);
  color: var(--ink, #211D16); }
.g-pill[disabled] { opacity: .55; cursor: default; }
@media (max-width: 560px) {
  .g-pills { flex-direction: column; align-items: stretch; }
  .g-pills .btn { width: 100%; box-sizing: border-box; text-align: center; }
}

/* ==========================================================================================
   WORK ORDER 188 (MATT, AUGUST 14 2026) — THE ENDING SCREEN, THE ASK, THE PHASE GATE, THE TALK
   ==========================================================================================
   THE FILE'S STANDING RULE IS UNBROKEN AND IS WORTH SAYING AGAIN HERE, because rule 5 asks for
   something that flashes: NO NEW KEYFRAMES. The talk line and the ask card wear member.css's own
   `.m-attention` — three beats at 1.2s and then STILL, with a static ring under
   prefers-reduced-motion — which is the one attention mechanism in the product and the same one
   the invitation at the top of the tab has worn since WO170. Nothing below animates anything. */

/* ---------- the score line and the joint high score ---------- */
.g-ending { margin: 0 0 18px; }
/* THE SCORE SENTENCE. It is the loudest thing on a finished game and it is still not a badge:
   the page's own display face, the size the game's own name is, and no colour but the ink. */
.g-endscore { font-family: "Fraunces", Georgia, serif; font-size: 1.15rem; margin: 0 0 6px; }
.g-endhigh { margin: 0; color: var(--ink-soft, #55503F); font-variant-numeric: tabular-nums; }
/* A NEW HIGH SCORE IS THE ONE PLACE THIS SCREEN RAISES ITS VOICE, and it raises it by one
   step: the product's own deep orange and a bold weight, on the same line in the same place.
   No ring, no animation, no icon — it is a sentence that is true today and ordinary tomorrow. */
.g-endnew { color: var(--orange-deep, #B54800); font-weight: 700; }
/* ----------------------------------------------------------------------------
   WO234 (MATT, AUGUST 15 2026) — THE AGREEMENT LINE AND THE SHARED-CHOICES LIST
   ----------------------------------------------------------------------------
   MATT: "how often you made the same choice … and, when there are same-choices, 'You both chose
   that you would rather…' followed by the list of the things you both chose."
   THE HIERARCHY IS THE ORDER HE WROTE THEM IN AND IT IS DELIBERATE. The score sentence above
   stays the loudest thing on the screen; the agreement line is the same weight as the high
   score beside it, because it is the second fact and not a second headline; and the LIST is the
   only thing on a finished game set on its own ground — because it is the only thing on this
   screen made of the pair's own words rather than of the product's.
   NO BULLET AND NO NUMBER. A numbered list would read as a ranking of things they agreed about,
   which is a scoreboard by another road (Principle 4), and a bullet in this product's type is
   noise. The indent is the list.
   NO NEW KEYFRAMES. Nothing here moves. */
.g-endagree { margin: 6px 0 0; color: var(--ink-soft, #55503F); font-variant-numeric: tabular-nums; }
.g-endsharedhead { font-family: "Fraunces", Georgia, serif; margin: 16px 0 8px; }
.g-endshared { list-style: none; margin: 0; padding: 14px 16px;
  background: var(--cream, #FBF6EC); border-radius: 14px;
  border: 1px solid rgba(33, 29, 22, .10); }
.g-endshared li { margin: 0 0 8px; }
.g-endshared li:last-child { margin-bottom: 0; }

/* ---------- WO188 rule 4 (c): the ending ask ---------- */
/* THE PARTNER'S CARD wears the invitation card's own ground, because it IS an invitation — the
   same kind of thing arriving from the same person by the same rule (they ask, you answer, a no
   is silent). Wearing a second treatment would have made two shapes for one idea. */
.g-askcard { margin: 14px 0 0; background: var(--orange-soft, #FCEBD2); border-radius: 18px;
  padding: 14px 16px; border: 1px solid rgba(181, 72, 0, .22); }
.g-askline { font-family: "Fraunces", Georgia, serif; font-size: 1.05rem; margin: 0 0 10px; }
.g-askrow { display: flex; flex-wrap: wrap; gap: 10px; margin: 0; }
.g-askrow .btn { min-height: 48px; }
/* THE ASKER'S RECEIPT IS THE QUIETEST THING ON THE SCREEN, and that is the design rather than
   the leftovers: it says what they did and nothing about what the other person has done. Soft
   ink, no ground, no border, no colour — the visual weight of a footnote, exactly as WO183's
   quiet ending has. */
.g-asksent { margin: 14px 0 0; color: var(--ink-soft, #55503F); font-size: .95rem; }
.g-asksent p { margin: 0 0 4px; }
@media (max-width: 560px) {
  .g-askrow { flex-direction: column; align-items: stretch; }
  .g-askrow .btn { width: 100%; box-sizing: border-box; text-align: center; }
}

/* ---------- WO188 rule 1: the way back out of a phase ---------- */
/* A QUIET CONTROL, DELIBERATELY. It is the same white button the "tell me why" row uses and not
   a primary: going back is a repair, and a repair that looks like the main move on the screen
   competes with the move the member is actually there to make. */
.g-backrow { margin: 14px 0 0; }
.g-back { min-height: 48px; background: var(--white, #FFFDF8);
  border: 1px solid rgba(33, 29, 22, .22); color: var(--ink, #211D16); }
@media (max-width: 560px) {
  .g-back { width: 100%; box-sizing: border-box; text-align: center; }
}

/* ---------- WO188 rule 5: what was said about this reveal ---------- */
/* THE SAME BUBBLES THE CHAT CARD DRAWS, at the round's grain — one conversation, so one shape.
   They sit above the box they were typed in, which is what "in the same place" means on both
   phones. */
/* THE VALUES ARE .g-line's OWN, not near-misses beside them: same radius, same border, same
   two grounds, and the member's own line pushed right by the same rule. Two bubbles that were
   nearly the same would read as two kinds of conversation, and there is only one. */
.g-talklines { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 8px; }
.g-talkline { padding: 10px 14px; border-radius: 14px; max-width: 34rem;
  background: var(--white, #FFFDF8); border: 1px solid rgba(33, 29, 22, .06); }
.g-talkline.g-me { margin-left: auto; background: var(--orange-soft, #FCEBD2); }

/* ==========================================================================================
   WO172 (MATT, AUGUST 13–14 2026) — SAME PAGE REBUILT: THE LINE, THE CURVE, THE TEACHING
   ==========================================================================================
   THE ANCHORS SIT ON THE LINE, AND THAT IS A GRID FACT RATHER THAN A MARGIN. `.g-specline` is
   three columns — anchor, body, anchor — so the two pole labels are physically beside the
   control at every width above the phone breakpoint, and directly above and below it at the
   phone breakpoint, where three columns would leave four characters a line. In neither case is
   there anything BETWEEN them: the DOM has three children and no fourth seat. */
/* ==========================================================================================
   WO252 (MATT, AUGUST 16–17 2026) — THE AXIS: BOTH LABELS BELOW THE LINE, ONE AT EACH END
   ==========================================================================================
   MATT, ON THE FIRST THING HE SAW: the example "pairs 'a snack' and 'a feast' — but places the
   labels at the TOP and BOTTOM while the line runs horizontally, which reads as nothing."

   HE WAS LOOKING AT THIS FILE'S PHONE BREAKPOINT. Above 560px the three columns put the two
   poles left and right of the line and the picture read correctly; at 390px the rule below the
   media query collapsed the grid to ONE column, so the DOM's three children stacked — 'a snack'
   above the line and 'a feast' below it. A vertical arrangement of the two ends of a horizontal
   dimension is not a smaller version of the same picture; it is a different and wrong one, and
   it was the version every phone met.
   THE ORDER IS EXACT AND IT IS THE SAME AT EVERY WIDTH: "labels sit BELOW the line, one at each
   END — left and right… Never above/below the middle." So there is no breakpoint here any more.
   TWO ROWS AND TWO COLUMNS. The line spans the full width on row one; the two anchors sit on
   row two, one hard left and one hard right, directly under the ends they name. At 390 that
   gives each pole half the screen to wrap in, which is what the old three-column layout could
   not do and is why WO172 collapsed it in the first place.
   THE DOM IS UNTOUCHED — still exactly three children, still anchor / body / anchor in source
   order, still nothing that could come between them. The placement is grid-area and the reading
   order is unchanged, so WO172's adjacency assertion and smoke-wo153b's own walk of these three
   children both still describe the shipped markup. */
.g-specline { display: grid; grid-template-columns: 1fr 1fr;
  column-gap: 10px; row-gap: 4px; align-items: start; margin: 10px 0 14px; }
.g-anchor { grid-row: 2; font-size: .86rem; line-height: 1.25; color: var(--ink-soft, #55503F);
  font-weight: 700; }
.g-anchorleft { grid-column: 1; text-align: left; }
.g-anchorright { grid-column: 2; text-align: right; }
.g-linebody { grid-column: 1 / -1; grid-row: 1; min-width: 0; display: block; }

/* THE CURVE. A hill centred on the mark, in three tiers — the widest and lowest first, then
   orange, then a narrow blue peak. The COLOURS are here and the WIDTHS are the server's: this
   file never says how wide a zone is, because that is the scoring and the scoring is canon.
   ==========================================================================================
   WO194 (MATT, AUGUST 14 2026) — THE THIRD ZONE IS CALLED PINK, AND IT IS THE SAME COLOUR
   ==========================================================================================
   Matt names it twice ("1 for pink", "0 points for being outside the pink area"), so the token
   is `pink` and the word a member reads and the class the page draws are the same word. THE
   FILL DID NOT CHANGE BY ONE HEX DIGIT: this is the colour he was looking at when he called it
   pink — twenty-two per cent of a warm red over cream reads pink, which is exactly why he did.
   RECORDED DEFAULT, VETO-ABLE, and it is this one line.
   AND THE DOT'S THREE ZONE TINTS ARE GONE. `.g-needledot.g-in-blue|orange|red` coloured the
   guess circle at the reveal and left it white while the member was dragging it — which is the
   difference "looks exactly like the guess-marker in the reveal" is asking not to see. One
   marker, one appearance, both screens. The zone is still said in words under it.
   THE DASHED LINE IS `.g-peak` AND IT WAS ALREADY DASHED — the order asks for it to be STATED,
   not restyled, and the sentence that states it is the server's. */
.g-curve { display: block; width: 100%; height: auto; }
.g-zone { stroke: none; }
.g-zone-pink { fill: rgba(200, 62, 40, .22); }
.g-zone-orange { fill: rgba(214, 122, 20, .30); }
.g-zone-blue { fill: rgba(38, 105, 168, .38); }
.g-peak { stroke: rgba(38, 105, 168, .55); stroke-width: 2; stroke-dasharray: 4 4; fill: none; }
.g-baseline { stroke: rgba(33, 29, 22, .35); stroke-width: 2; fill: none; }
.g-needle { stroke: var(--ink, #211D16); stroke-width: 2.5; fill: none; }
.g-needledot { fill: var(--white, #FFFDF8); stroke: var(--ink, #211D16); stroke-width: 2.5; }
/* WO194 — THE MARKER THE GUESSER DRAGS. It sits in the same grid cell as the slider, directly
   above it, so the circle and the thumb move together down one column of the line. It takes no
   pointer events of its own: the control under it is the control. */
.g-guessmark { display: block; pointer-events: none; margin-bottom: -6px; }

/* THE SLIDER, ON THE LINE. 44px of thumb and 48px of row, which is the standing floor for
   every control in this feature — and it is stated here rather than inherited, because this
   is the one control a member drags rather than taps. */
.g-specline .g-slider { width: 100%; min-height: 48px; accent-color: var(--orange-deep, #B54800); }
.g-specline .g-slider::-webkit-slider-thumb { width: 44px; height: 44px; }
.g-specline .g-slider:focus-visible { outline: 3px solid var(--orange-deep, #B54800);
  outline-offset: 3px; }

/* ==========================================================================================
   WO252 (MATT, AUGUST 16–17 2026) — THE GUESS IS ON THE LINE, NOT ON A PILL UNDER IT
   ==========================================================================================
   MATT: "the guess control is a detached slider pill floating below the line" — and what he
   wants instead is "a VERTICAL LINE that touches the horizontal distribution line and slides
   along it as the member drags the circle."

   THERE WERE TWO TRACKS ON THAT SCREEN. The SVG carried the baseline and the needle; the range
   input under it carried the house's cream pill and a 44px orange thumb with a drop shadow. Two
   horizontal things six pixels apart, and the wrong one was the loud one.
   ONE BOX NOW. `.g-guessline` is a positioning context holding the drawing and the input, and
   the input is laid over the drawing exactly. Its track and its thumb are made transparent —
   TAKEN AWAY VISUALLY AND KEPT IN EVERY OTHER SENSE — so what a member sees under their finger
   is the needle: a vertical line touching the baseline with a circle on top, the same string
   needleSVG hands the reveal.
   THE ARITHMETIC THAT MAKES THEM AGREE, and it is the only fiddly line in this block. The SVG's
   viewBox is 300 wide and the drawable band runs from x=10 (position 0) to x=290 (position 100)
   — 3.3333% to 96.6667% of the box. A range input puts the CENTRE of its thumb at half a thumb
   in from each edge, so the input is inset by 3.3333% and then pulled back out by half a thumb
   at both ends: left: calc(3.3333% - 22px); width: calc(93.3334% + 44px). The thumb's centre
   then travels exactly from x=10 to x=290 and the needle sits under the finger at every value.
   THE 44px TOUCH TARGET GOT BIGGER RATHER THAN SMALLER. The thumb is still 44px and the input
   covers the bottom seventy per cent of the figure — the circle, the vertical line and the
   distribution line under it — so the whole width of the line is draggable rather than a pill
   being. It is anchored to the BOTTOM rather than centred because that is where the control
   is: the top third of the box is the peak of a curve nobody drags.
   THE KEYBOARD PATH IS UNTOUCHED. It is still a native input[type=range]: arrow keys, Home and
   End, the value announced, the <output> beside it, the <label> on it and one submit path. The
   focus ring is stated here because taking a control's own chrome away must never take its
   focus ring with it — this one is tabbable, so WO298's tabindex="-1" rule cannot reach it. */
.g-guessline { position: relative; display: block; }
.g-guessline .g-guessmark { margin-bottom: 0; }
.g-specline .g-guessline .g-slider { position: absolute; bottom: 0;
  left: calc(3.3333% - 22px); width: calc(93.3334% + 44px);
  height: 70%; min-height: 48px; margin: 0; padding: 0; background: transparent;
  -webkit-appearance: none; appearance: none; }
.g-guessline .g-slider::-webkit-slider-runnable-track { height: 100%; border: 0;
  border-radius: 0; background: transparent; box-shadow: none; }
.g-guessline .g-slider::-moz-range-track { height: 100%; border: 0; border-radius: 0;
  background: transparent; box-shadow: none; }
.g-guessline .g-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none;
  width: 44px; height: 44px; margin-top: 0; border-radius: 50%; border: 0;
  background: transparent; box-shadow: none; cursor: grab; }
.g-guessline .g-slider::-moz-range-thumb { width: 44px; height: 44px; border-radius: 50%;
  border: 0; background: transparent; box-shadow: none; cursor: grab; }
.g-guessline .g-slider:focus-visible { outline: 3px solid var(--orange-deep, #B54800);
  outline-offset: 2px; border-radius: 16px; }
.g-slideout { display: block; text-align: center; font-size: .88rem;
  color: var(--ink-soft, #55503F); }

/* ---------- WO172: ONE TRIAL, TWO DIRECTIONS, ONE SCREEN ---------- */
.g-trial { background: var(--white, #FFFDF8); border-radius: 18px; padding: 18px 20px;
  border: 1px solid rgba(33, 29, 22, .06); }
.g-side { padding: 14px 0; }
.g-side + .g-side { border-top: 1px solid rgba(33, 29, 22, .10); margin-top: 4px; }
.g-sidehead { font-size: 1rem; margin-bottom: 8px; color: var(--ink, #211D16); }
.g-side-theirs { background: var(--cream, #FAF5EC); border-radius: 14px; padding: 14px 14px 4px; }
.g-rulefine { color: var(--ink-soft, #55503F); font-size: .88rem; margin: 4px 0 8px; }
/* ==========================================================================================
   WO194 (MATT, AUGUST 14 2026) — "IN LARGE LETTERS", WHICH IS A SIZE AND THEREFORE LIVES HERE
   ==========================================================================================
   MATT: 'Each of the two trials in the reveal is headed in LARGE LETTERS "You were the clue
   giver" / "You were the guesser".' The WORDS are the server's (lib/spectrum-items.mjs); the
   size is this file's, under the standing rule that a drawing — and a type size is a drawing —
   is not copy. `.g-side-revealed` is on the section only once that half has opened, so the
   phase header a member reads WHILE PLAYING keeps its ordinary size and only the two past-tense
   headings are loud. */
.g-side-revealed .g-sidehead { font-size: 1.35rem; line-height: 1.2; margin-bottom: 10px; }
/* THE CLUE, SAID BACK, under the guesser's header. It is the thing on that screen a member is
   actually reading, so it carries the weight the deleted stem used to. */
.g-cluegiven { font-weight: 700; margin: 0 0 12px; }
/* WO194 — THE LEGEND UNDER A REVEAL. Quiet: it explains a picture that is already there, and a
   sentence in the same weight as the points line would compete with it. */
.g-revlegend { color: var(--ink-soft, #55503F); font-size: .9rem; margin: 8px 0 2px; }
/* WO194 — "Below both reveals, in a LARGE FONT: Running total: ___". It rides .g-pairscore's
   colour and spacing (WO189's) and says the size Matt asked for. */
.g-runtotal { font-size: 1.3rem; color: var(--orange-deep, #B54800); margin: 20px 0 4px; }

/* ---------- WO172: THE TEACHING, AND THE DEMO BESIDE THE RULES ---------- */
.g-modalfoot { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.g-modalfoot .btn { min-height: 48px; }
.g-demobtn { background: var(--white, #FFFDF8); border: 1px solid rgba(33, 29, 22, .18);
  color: var(--ink, #211D16); }
/* WO194 — 'Skip example', on the first window only. It wears the demo button's quiet white so
   that the one filled control in the dialog is still the one that goes forwards: a member who
   has never played should meet Next, not a way out, as the obvious thing to press. */
.g-teachskip { background: var(--white, #FFFDF8); border: 1px solid rgba(33, 29, 22, .18);
  color: var(--ink, #211D16); margin-left: auto; }
.g-teachcard { max-width: 34rem; }
.g-teachstep { font-size: .8rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-soft, #55503F); margin-bottom: 4px; }
.g-teachlede { margin-bottom: 10px; }
.g-teachclue { font-size: 1.12rem; font-weight: 700; text-align: center; margin: 4px 0 10px;
  color: var(--orange-deep, #B54800); }
.g-teachnote { color: var(--ink-soft, #55503F); margin-bottom: 10px; }
.g-teachline { margin: 4px 0 10px; }
/* ==========================================================================================
   WO252 — THE EXAMPLE'S TWO BEATS, AND THE TWO SENTENCES THEY HANG ON
   ==========================================================================================
   `.g-teachask` is the question that stands under the clue while the payoff is still owed, and
   it is asked of the reader, so it carries the ink the clue does rather than the fine grey of a
   note. `.g-teachlegend` names the two marks on the picture once they are both on it — the same
   job, and the same low weight, as `.g-revlegend` on the live reveal, deliberately: a member
   should read the same kind of sentence about the same kind of picture in both places. */
.g-teachask { font-weight: 700; text-align: center; margin: 0 0 10px;
  color: var(--ink, #211D16); }
.g-teachlegend { color: var(--ink-soft, #55503F); font-size: .9rem; margin: 0 0 6px; }

/* ---------- WO172: THE SCORING SCREEN AND ITS THREE TIERS ---------- */
.g-end { margin: 20px 0 8px; background: var(--cream-deep, #F3EADA); border-radius: 18px;
  padding: 20px; border: 1px solid rgba(33, 29, 22, .06); }
.g-endhead { margin-bottom: 4px; }
.g-endtotal { font-weight: 700; color: var(--orange-deep, #B54800); margin-bottom: 16px; }
.g-tier + .g-tier { margin-top: 18px; border-top: 1px solid rgba(33, 29, 22, .10);
  padding-top: 14px; }
.g-tier h3 { font-size: 1rem; margin-bottom: 4px; }
.g-tierprivate { font-style: italic; }
.g-tierlist { list-style: none; margin: 8px 0 0; padding: 0; }
.g-tierrow { display: flex; gap: 12px; align-items: baseline; padding: 6px 0;
  border-bottom: 1px solid rgba(33, 29, 22, .06); }
.g-tierrow.g-tiernow { font-weight: 700; }
.g-tierscore { min-width: 2.5rem; font-variant-numeric: tabular-nums;
  color: var(--orange-deep, #B54800); font-weight: 700; }
.g-tierwith { color: var(--ink-soft, #55503F); }

@media (max-width: 560px) {
  /* ==========================================================================================
     WO252 — THE PHONE'S OWN AXIS RULE IS DELETED RATHER THAN ADJUSTED
     ==========================================================================================
     WO172's phone rule stacked the three children in one column, which put 'a snack' above the
     line and 'a feast' below it — the exact picture Matt says "reads as nothing". Its reasoning
     about the SLIDER was right and is kept by the new layout for free: the line spans both
     columns, so it still has the whole width of a 390px screen. Nothing replaces this rule,
     because the two-row grid above is already the phone layout and the desktop one.
     ONLY THE DIALOG'S BUTTON STACK REMAINS HERE, and it never had anything to do with the axis.
     ========================================================================================== */
  .g-modalfoot { flex-direction: column; align-items: stretch; }
  .g-modalfoot .btn { width: 100%; box-sizing: border-box; text-align: center; }
}

/* ============================================================================================
   WO187A (MATT, AUGUST 14 2026) — GAMES IN PROGRESS, AT THE TOP OF THE TAB
   ============================================================================================
   MATT: "In-progress games are listed at the TOP of the games page, not the bottom."

   IT SITS BETWEEN THE INVITATION CARD AND THE SIX, AND IT IS QUIETER THAN BOTH — deliberately.
   The invitation above it is news from another person and earns the warm ground and Principle
   19's finite flash; this is the member's OWN state, so it gets the same cream card the rest of
   the tab uses and nothing that could be mistaken for an arrival. NO BADGE, NO COUNTER, NO
   ATTENTION CLASS, and no rule below that could produce one.
   THE WHOLE ROW IS THE TARGET, like every other list on this page (`.g-person`), so the tap
   area is the card rather than a word inside it — and it clears the 48px minimum on a phone by
   padding rather than by a height, so a long game name wraps instead of being clipped.
   THE TURN WORD IS A WORD AND NOT A COLOUR. A game waiting on this member is marked by weight
   and by the accent on its own label; there is no red, no dot and no ring, because "your turn"
   is information and not an alarm — and a member who cannot distinguish the two colours reads
   the same sentence everybody else does. */
.g-inprog { margin: 0 0 30px; }
.g-inproghead { font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 1.05rem;
  margin: 0 0 10px; color: var(--ink-soft, #55503F); }
.g-inproglist { list-style: none; margin: 0; padding: 0; }
.g-inprogitem { background: var(--white, #FFFDF8); border-radius: 14px;
  border: 1px solid rgba(33, 29, 22, .08); }
.g-inprogitem + .g-inprogitem { margin-top: 8px; }
.g-inproglink { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline;
  padding: 14px 16px; min-height: 48px; box-sizing: border-box;
  text-decoration: none; color: inherit; border-radius: 14px; }
.g-inproglink:hover { background: var(--cream-deep, #F3EADA); }
.g-inproglink:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }
.g-inprogline { font-family: "Fraunces", Georgia, serif; font-size: 1.05rem; }
.g-inprogword { margin-left: auto; color: var(--ink-soft, #55503F); font-size: .88rem; }
/* THE ONE WAITING ON THIS MEMBER, said in weight and in the accent the rest of the product
   already uses for "this one is yours". Still a word; still no badge. */
.g-inprogmine .g-inprogword { color: var(--orange-deep, #B54800); font-weight: 700; }
@media (max-width: 560px) {
  .g-inprogword { margin-left: 0; width: 100%; }
}

/* ---------- WO216: the one real control on the card (Matt, August 14 2026) ----------
   HIS RULING: dismissing a game ends it — "and that should be what the button says, 'End game',
   so it's clear."
   IT IS DRAWN OUTSIDE THE ROW'S LINK, in its own strip under it, and the rule above is what
   makes that visible rather than merely true in the markup: the link keeps its own rounded
   ground and its own hover, and this strip sits on the card's plain white beneath it, so the
   destructive control is never inside the thing a thumb aims at to OPEN the game.
   IT IS THE QUIET BUTTON AND NOT THE PRIMARY ONE (`.m-btn-small`, the product's standing
   secondary), because the primary act on this card is still "open the game and play it".
   Ending is available, clearly labelled, and not the thing the eye lands on.
   THE FINE PRINT IS BESIDE IT AND NOT UNDER IT on a wide screen and wraps beneath on a phone,
   which is the same behaviour every other control-plus-consequence pair on this page has. */
.g-inprogact { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  margin: 0; padding: 0 16px 12px; }
.g-inprogend { flex: 0 0 auto; }
.g-inprogfine { flex: 1 1 220px; margin: 0; }
@media (max-width: 560px) {
  .g-inprogfine { flex-basis: 100%; }
}

/* ---------- WO215: the asks I am waiting on (Matt, August 14 2026) ----------
   "When A asks B to play from the main game menu, it goes back to the main games menu as if you
   haven't asked."
   IT IS THE IN-PROGRESS SECTION'S CARD, ONE SHADE QUIETER, and that is the design rather than
   laziness: the two sections sit on top of each other and say two halves of one sentence —
   what is running, and what I am waiting on — so they must read as one family. The difference
   is weight, because an ask is not a game and must not compete with one for the eye.
   NO ATTENTION TREATMENT ANYWHERE IN HERE, and there is no class in this block that could
   carry one: this is the member's own act, not news from another person, so Principle 19's
   flash is not its to wear (the invitation card above it is the one thing on this page that
   flashes). No badge, no count, no colour that means alarm.
   THE OPTIMISTIC CARD WEARS THE SAME CLASSES, so the moment of the tap and the moment the
   server answers look identical and nothing on the screen moves between them. */
.g-askedout { margin: 0 0 30px; }
.g-askedouthead { font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 1.05rem;
  margin: 0 0 10px; color: var(--ink-soft, #55503F); }
.g-askedoutlist { list-style: none; margin: 0; padding: 0; }
.g-askedoutitem { background: var(--white, #FFFDF8); border-radius: 14px;
  border: 1px dashed rgba(33, 29, 22, .16); }
.g-askedoutitem + .g-askedoutitem { margin-top: 8px; }
.g-askedoutlink { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline;
  padding: 14px 16px; min-height: 48px; box-sizing: border-box;
  text-decoration: none; color: inherit; border-radius: 14px; }
.g-askedoutlink:hover { background: var(--cream-deep, #F3EADA); }
.g-askedoutlink:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px; }
/* THE OPTIMISTIC CARD HAS NO LINK IN IT — there is nothing to link to until the server has a
   game — so the line carries the card's own padding for the one moment it stands alone. */
.g-askedoutitem > .g-askedoutline { display: block; padding: 14px 16px; }
/* ---------- WO231 (MATT, AUGUST 15 2026): AND THIS ONE LINE IS SANS ----------
   HIS RULING, VERBATIM: "'Asked … to play' is in a serif font while everything at its level is
   sans — switch it to the page's sans."
   HE IS RIGHT AND THE MISTAKE WAS A FAMILY RESEMBLANCE. This section was built as a quieter copy
   of the in-progress card (see the note above), and the in-progress card's LINE is a game's own
   name — 'Two Truths with Ada' — which is a title and wears the display face like every other
   title on this page. 'Asked Ada to play.' is not a title. It is a sentence about something that
   happened, at the same level as the porch line and every blurb around it, and all of those are
   the body face. The SAME SENTENCE also appears on the picker's own button two sections down,
   where `.btn` has always set the body face — so one string was being drawn in two faces on one
   screen, which is what he was looking at.
   THE HEADING ABOVE IT IS UNTOUCHED ('Waiting on them' is a heading, and its neighbours
   `.g-inproghead` and `.g-invitehead` are the same weight in the same face). ONE LINE CHANGES.
   VETO-ABLE, AND RECORDED AS AN OPEN QUESTION: `.g-inprogline` beside it is still the display
   face. It is a game's name rather than a sentence, so this order leaves it — say the word. */
.g-askedoutline { font-family: var(--font-body, "DM Sans", sans-serif); font-size: 1.05rem;
  color: var(--ink-soft, #55503F); }

/* ---------- WO187A: the fresh chat window's signpost ----------
   The one line at the top of a game chat that already has lines in it, saying where everything
   from before this game went. It is a NOTE, not a message: it wears the quiet-note treatment
   the empty state already wears (`.g-quietnote`), sits above the first line, and is separated
   from the conversation by a rule so it can never be read as something somebody said. */
.g-chatearlier { border-bottom: 1px solid rgba(33, 29, 22, .08); padding-bottom: 8px;
  margin-bottom: 4px; font-size: .9rem; }

/* ---------- WO187A: the menu entry whose ask has been sent ----------
   'Asked Ben to play.' is a RECEIPT and not a disabled state: the button stays live, because
   asking again is exactly what withdraws the first ask (createInvite), and a member must never
   have to undo something to change their mind. So there is no grey-out and no lock here — only
   a quieter, secondary weight, so the five games still on offer read as the offers and this one
   reads as the answer it already gave. */
.g-menuasked .btn-primary { background: transparent; color: var(--orange-deep, #B54800);
  border: 1px solid rgba(181, 72, 0, .45); box-shadow: none; }

/* ---------- WO191: THE GUESSING SCREEN'S HEADER (Matt, August 14 2026) ----------
   "Clue word: ____, Number of pictures: ___" — one sentence, composed by the server, sitting
   directly above the nine tiles it is about. It is drawn heavier and a shade larger than body
   copy because it is the ONLY thing on that screen a member has to hold in their head while
   they tap, and it is a <p> rather than a heading because it is a statement of two facts
   rather than the title of a section. No colour of its own: the clue is the game's own word,
   not an alert. */
.g-guesshead { font-weight: 700; font-size: 1.06rem; margin: 0 0 10px;
  color: var(--ink, #211D16); }

/* ---------- WO191: THE DOOR TO THE GAME'S OWN PAGE ----------
   Where the games list leads over a FINISHED game, this pill is what stands in for the game
   that used to be drawn open underneath it. It is a `.g-pill` — the same white pill as the four
   ending ones, deliberately, because it belongs to the same family of "somewhere to go next"
   and inventing a second treatment for it would have made it read as something else. It sits
   between the menu and the chat, on its own row, at the full 48px the rest of this page keeps. */
.g-gamedoor { margin: 18px 0 0; }
.g-gamedoor .btn { min-height: 48px; display: inline-flex; align-items: center; }
@media (max-width: 560px) {
  .g-gamedoor .btn { width: 100%; box-sizing: border-box; justify-content: center; }
}

/* ---------- WO191: ONE BOARD AT A TIME, INSIDE A ROUND ----------
   One Word's two boards now come through WO172's trial renderer, which draws each side in a
   `.g-side` section. The board's own answering form ALSO uses `.g-side` (as a bare fieldset,
   since WO153b), so a board inside a round nests one inside the other — and `.g-side + .g-side`
   above would then draw a rule between a board's grid and the text under it. This narrows that
   rule to the two SECTIONS it was written for and leaves the fieldset alone. Nothing about
   Same Page's screen moves: its sides are sections and always were. */
.g-side + fieldset.g-side { border-top: none; margin-top: 0; }
.g-side-mine > .g-board, .g-side-theirs > .g-board { margin-top: 4px; }

/* ==========================================================================================
   WO217 (MATT, AUGUST 15 2026) — THE END-GAME PILL IN THE ROOM, THE CONFIRM, AND '___ said:'
   ==========================================================================================
   THREE SMALL BLOCKS AND NO NEW KEYFRAME. This page's standing rule since WO170 is that no
   animation is minted here — the only motion in the feature is member.css's `.m-attention`,
   three beats and then still — and none of what follows moves.

   (1) THE ROOM'S PILL REUSES THE CARD'S STRIP. `.g-endstrip` is the shared class both doors
   draw (site/assets/games.js's endStripHTML) and `.g-inprogact` is WO216's card padding kept
   exactly as it was, so the tab is byte-identical to what shipped last night. `.g-roomend` is
   the room's own padding: it stands at the foot of the game, above the conversation, separated
   by a rule so it reads as the end of the game rather than as another thing in it.
   IT IS THE QUIET BUTTON, NOT THE PRIMARY ONE, for WO216's reason at a second door: the primary
   act in this room is playing the game.

   (2) THE CONFIRM IS THE STRIP, REPLACED IN PLACE. No overlay, no modal, no focus trap — the
   question and its two answers sit exactly where the button was, which is the choreography
   WO153b's owner-delete already uses at this door. The question is bold enough to be read and
   not so loud that a member who tapped by accident feels told off.

   (3) '___ said:' IS A LABEL ABOVE THE LINE, not the first three words of it. It is small,
   quiet and its own block, so a member's own sentence is still the thing you read — and a
   screen reader hears the name and then the line rather than one run-on. It is drawn on THEIR
   lines only (nobody meets their own name), so `.g-me` never has one and no rule here needs to
   hide it. */
.g-endstrip { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin: 0; }
.g-roomend { margin: 20px 0 0; padding: 14px 0 0;
  border-top: 1px solid rgba(33, 29, 22, .10); }
.g-endask { flex: 0 0 auto; font-weight: 700; color: var(--ink, #211D16); }
.g-endask:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 3px;
  border-radius: 6px; }
.g-said-by { display: block; font-size: .82rem; font-weight: 700; letter-spacing: .01em;
  color: var(--ink-soft, #55503F); margin: 0 0 3px; }
.g-talkbody { display: block; }
@media (max-width: 560px) {
  .g-endstrip .m-btn-small { flex: 0 0 auto; }
}

/* ============================================================
   WO231 (MATT, AUGUST 15 2026) — THE SHELL'S THREE NEW PIECES
   ============================================================
   (1) 'BACK TO GAMES', THE ONE CONTROL ABOVE AN OPEN GAME. His ruling: "the list of games must
   not sit above it… replace with a single 'Back to Games' button at the top of the game." It is
   drawn as a link and looks like a control, because it is now the only thing standing between a
   member and the whole tab — the row it lives in (`.g-back`) is unchanged, so nothing above the
   game moved except what was deleted from it. 48px, like every other target in this feature.

   (2) THE START PILL, IN THE PAGE. 'NOTHING EVER GOES ABOVE THE TABS' is a recorded design line
   as of this order (lib/games.mjs's NOTHING_ABOVE_THE_TABS), so the bar that used to be inserted
   above the nav strip is now a section inside the page, directly above Games in progress. It
   wears `.m-attention` from member.css — the house finite flash, three beats then still, a
   STATIC ring under prefers-reduced-motion — exactly as the invitation card above it does, and
   it mints no keyframe of its own. IT IS THE INVITATION CARD'S OWN GROUND for the reason the
   cross-page pill took it (see .m-startpill's note in member.css): ink on #FCEBD2 is 12.4:1,
   and the recipient's half and the inviter's half of one rule should not look like two ideas.

   (3) THE PAIR SPACE. A <details> in the same family as the under-construction card, quieter
   than the six-game wall it replaces inside a room: it is a way onward, not an offer competing
   with the game a member is in. Shut by default, its summary is a 48px target, and the six
   inside it are the ordinary menu items so nothing about them has to be restyled. */
.g-backbtn { display: inline-flex; align-items: center; min-height: 48px; padding: 0 4px;
  text-decoration: none; color: var(--ink-soft, #55503F); font-weight: 700; }
.g-backbtn:hover { color: var(--ink, #211D16); }
.g-backbtn:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px;
  border-radius: 8px; }

.g-startpill { display: block; margin: 0 0 22px; background: var(--orange-soft, #FCEBD2);
  border-radius: 18px; border: 1px solid rgba(181, 72, 0, .22);
  box-shadow: 0 6px 18px rgba(33, 29, 22, .07); }
.g-startpill-link { display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline;
  padding: 16px 20px; min-height: 48px; box-sizing: border-box;
  text-decoration: none; color: var(--ink, #211D16); border-radius: 18px; }
.g-startpill-link:hover { background: rgba(181, 72, 0, .08); }
.g-startpill-link:focus-visible { outline: 3px solid var(--orange-deep, #B54800);
  outline-offset: 2px; }
.g-startpill-line { font-family: "Fraunces", Georgia, serif; font-size: 1.12rem; }
.g-startpill-cta { font-size: .9rem; font-weight: 700; color: var(--orange-deep, #B54800); }

.g-pairspace { margin: 26px 0 0; background: var(--cream-deep, #F3EADA); border-radius: 18px;
  border: 1px solid rgba(33, 29, 22, .08); padding: 4px 18px; }
.g-pairsum { cursor: pointer; padding: 14px 0; min-height: 48px; display: flex;
  align-items: center; color: var(--ink-soft, #55503F); }
.g-pairsum:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 2px;
  border-radius: 10px; }
.g-pairtitle { font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 1.05rem; }
.g-pairfine { margin: 0 0 14px; max-width: 44rem; }
.g-pairlist { padding-bottom: 16px; }
.g-pairitem { background: var(--white, #FFFDF8); }

/* ============================================================================
   WO246 (MATT, AUGUST 16 2026) — THE GAMES SHELL RULES
   ============================================================================
   Five things, and every one of them is shared machinery the six per-game orders (WO247–252)
   wear without editing: the house treatment for a native control, the message door on a card,
   the enter-the-game pill, the hovering next-round notice, and the focus anchors' one rule.
   NO NEW KEYFRAMES, still — this file's standing law since WO153a. Where attention is wanted
   the markup wears member.css's `.m-attention` (Principle 19's finite three beats) or
   `.m-hs-pulse` (the chrome's pulse-until-handled), both of which already carry the
   prefers-reduced-motion answer. Nothing below animates anything of its own.
   ============================================================================ */

/* ---------- (a) NO BLUE. THE PICK-A-PERSON STEP, AND EVERY NATIVE CONTROL BESIDE IT ----------
   MATT: "There should not be any blue anywhere on the website as far as I'm concerned. This
   needs to be fixed for all the games."

   WHERE THE BLUE WAS, EXACTLY, AND IT IS NOT A COLOUR ANYBODY WROTE. There is no blue hex and
   no blue variable anywhere in this stylesheet — the pick-a-person control is a NATIVE <select>
   with `appearance: auto`, so the browser drew it with the SYSTEM tint: the disclosure chevron,
   the highlight on the row under the finger in the popup, and the focus wash are all the
   platform's accent, which on iOS and on Windows is blue. That is why it never showed up in a
   grep and why it is worst on a phone, where the popup is the whole screen.
   THE THREE THINGS THAT TAKE IT AWAY, and all three are needed because each covers a different
   browser's idea of a select:
     appearance: none   drops the platform widget, so the chevron is ours (drawn below as a
                        background image in the house's deep orange, in the ink's own geometry).
     accent-color       is what a modern browser tints the popup's selected row and every
                        checkbox and radio with. Set to --orange-deep it is the house palette
                        rather than the system's.
     color-scheme       light, declared, so a phone in dark mode does not hand these controls a
                        dark chrome with a blue accent underneath our own colours.
   IT IS SCOPED TO THE GAMES SURFACE (`#page`) AND NOT TO A CLASS, deliberately: every game's
   controls are drawn by a different renderer and the picker is only the one Matt happened to be
   looking at. His rule is about the product, not about one card, and inside this feature the
   honest reading of "all the games" is every native control on the page.
   THE SITE-WIDE SWEEP IS WO238'S AND IS NAMED IN ITS OWN ORDER ("the blue sweep… unstyled
   native widgets are the likely culprits"). This is the games-side half; the shared source is
   the platform's own accent on an unstyled control, and it is reported in the WO246 to-do doc
   for that lane rather than fixed from here.
   THE 48px FLOOR AND THE ORANGE FOCUS RING ARE UNCHANGED — the per-control rules above still
   set them and this adds nothing that could shrink one. */
#page { color-scheme: light; accent-color: var(--orange-deep, #B54800); }
#page select,
#page input[type="checkbox"],
#page input[type="radio"],
#page input[type="range"] { accent-color: var(--orange-deep, #B54800); color-scheme: light; }
#page select {
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  color: var(--ink, #211D16);
  background-color: var(--white, #FFFDF8);
  /* the chevron, in the house's own deep orange, drawn rather than borrowed */
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23B54800' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 18px 18px;
  padding-right: 40px;
}
/* THE OPTIONS THEMSELVES, where a browser lets a stylesheet reach them at all. Never a rule
   anything depends on — the three above are what actually removes the blue — but on the engines
   that do honour it the popup is the page's own ink on the page's own ground. */
#page select option { color: var(--ink, #211D16); background-color: var(--white, #FFFDF8); }
/* AND NO PLATFORM BLUE ON A HELD TAP. The house's own soft orange, at the same weight the tap
   highlight has everywhere else. */
#page { -webkit-tap-highlight-color: rgba(181, 72, 0, .12); }

/* ---------- (b) THE MESSAGE DOOR ON A CARD (both directions) ----------
   The pill is the card's THIRD control and is drawn low-key, because the card's real question is
   the two pills above it: a composer that looked like a primary action would make an invitation
   read as three equal choices. The window it opens is the room's own composer at card size —
   same label treatment, same 48px send, same status line. */
.g-cardmsgrow { margin: 10px 0 0; }
.g-cardmsgpill { min-height: 44px; }
.g-cardmsg { margin: 10px 0 0; }
.g-cardmsg[hidden] { display: none; }
.g-cardsay textarea { width: 100%; box-sizing: border-box; border-radius: 12px;
  padding: 10px 12px; font: inherit; min-height: 60px;
  border: 1px solid rgba(33, 29, 22, .18); background: var(--white, #FFFDF8); }
.g-cardsay textarea:focus-visible { outline: 3px solid var(--orange-deep, #B54800);
  outline-offset: 2px; }
.g-cardsayrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  margin: 10px 0 0; }
/* ON THE DARK CARD, THE COMPOSER IS THE CARD'S OWN CREAM — WO253 painted the invitation card
   dark orange and gave its three pills a cream treatment; a fourth control and a label that
   inherited the page's soft ink would sit on that ground below the contrast floor. The textarea
   keeps its white ground and its ink, because a box you type into is a box you type into. */
.g-invitecard .g-saylab, .g-invitecard .g-cardsay .g-said { color: #FFFDF8; }
.g-invitecard .g-cardsay .g-quiet { color: #FFFDF8; text-decoration-color: rgba(255, 253, 248, .7); }
.g-invitecard .g-cardsay textarea { color: var(--ink, #211D16);
  background: var(--white, #FFFDF8); border-color: rgba(255, 253, 248, .7); }
.g-invitecard .g-cardsay textarea:focus-visible { outline: 3px solid #FFFDF8; }
@media (max-width: 560px) {
  .g-cardsayrow { flex-direction: column; align-items: stretch; }
  .g-cardsayrow .m-btn-small { width: 100%; }
}

/* ---------- (c) THE ENTER-THE-GAME PILL ----------
   MATT: "the card names the person — '[Name] has entered the game' — and below it an orange
   'Enter the game' pill that flashes until it is hit (or until End game is). On any later
   return… 'Return to game' beside 'End game', never a bare red waiting label with no action."
   THE PILL IS THE ONE FILLED ORANGE CONTROL ON THIS CARD, which is how the card says which of
   its two buttons moves the member forward — 'End game' has been the low-key one since WO216 and
   stays that way. THE FLASH IS `.m-hs-pulse`, worn in the markup, and it is the chrome's own
   pulse-until-handled with member.css's static high-contrast ring under reduced motion. This
   file adds no animation and no timing of its own; what it adds is the row's geometry. */
.g-enterrow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  margin: 0; padding: 0 16px 12px; }
.g-enterline { font-family: "Fraunces", Georgia, serif; font-size: 1.02rem;
  flex: 1 1 200px; }
.g-enterpill { min-height: 48px; flex: 0 0 auto;
  background: var(--orange-deep, #B54800); border: 1px solid var(--orange-deep, #B54800);
  color: var(--white, #FFFDF8); font-weight: 700; border-radius: 999px; padding: 12px 22px;
  text-decoration: none; display: inline-flex; align-items: center; }
.g-enterpill:hover { background: #9C3E00; color: var(--white, #FFFDF8); text-decoration: none; }
.g-enterpill:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 3px; }
/* THE FIRST-TIME ROW IS THE THING THAT PULSES, not the pill alone, so the person's name and the
   way in are one signal rather than two. `.m-hs-pulse` is member.css's and is not redefined
   here; this only gives the animation something with a radius to travel around. */
.g-enterfirst { border-radius: 14px; padding: 12px 16px; margin: 0 12px 12px; }
@media (max-width: 560px) {
  .g-enterrow { flex-direction: column; align-items: stretch; }
  .g-enterpill { width: 100%; justify-content: center; }
}

/* ---------- (d) THE HOVERING NEXT-ROUND NOTICE ----------
   MATT: "a small centered floating notice hovers mid-screen — 'Next round' plus a second
   button, 'Close' — staying put while the page scrolls."
   IT IS MID-SCREEN AND IT CAN NEVER BE ABOVE THE TABS. `top: 50%` with a translate is not a
   position that can drift upward: whatever the viewport, the card's own middle is the
   viewport's middle, so NOTHING_ABOVE_THE_TABS (WO231) is kept by the geometry rather than by a
   promise. z-index sits above the page and BELOW the shell's scrim and panel (200/260), so the
   Account panel and any modal still cover it — a floating notice must never be the thing on top
   of a dialog.
   IT IS NOT FULL WIDTH AND IT DOES NOT BLOCK THE PAGE: `pointer-events: none` on the wrapper
   and `auto` on the card, so the two buttons work and everything around them is still readable
   and tappable. */
.g-nudge { position: fixed; left: 0; right: 0; top: 50%; transform: translateY(-50%);
  z-index: 80; display: flex; justify-content: center; padding: 0 16px;
  pointer-events: none; box-sizing: border-box; }
.g-nudgecard { pointer-events: auto; box-sizing: border-box;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 14px;
  background: var(--white, #FFFDF8); border: 1px solid rgba(33, 29, 22, .14);
  border-radius: 18px; padding: 14px 18px; max-width: 26rem; width: 100%;
  box-shadow: 0 18px 44px rgba(33, 29, 22, .22); }
.g-nudgego { min-height: 48px; background: var(--orange-deep, #B54800);
  border: 1px solid var(--orange-deep, #B54800); color: var(--white, #FFFDF8);
  font-weight: 700; border-radius: 999px; padding: 12px 24px; }
.g-nudgego:hover { background: #9C3E00; }
.g-nudgego:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 3px; }
.g-nudgeclose { min-height: 44px; }

/* ==========================================================================================
   WO294 (MATT, AUGUST 17 2026) — THE RANKINGS CHAT IS A PILL UNTIL SOMEBODY WANTS IT
   ==========================================================================================
   MATT: "add a pill: 'Want to say something about our rankings?'. Tapping it opens a small chat
   window right there… the pill is collapsed by default so the reveal stays clean until somebody
   wants to talk."

   IT IS <details>/<summary> AND THE STYLING IS ALL THIS FILE ADDS. The disclosure behaviour, the
   keyboard, the announcement and the browser's own in-page find are the element's; a pill built
   out of a button and a hidden div would have been four things to keep right by hand.
   THE MARKER GOES because a triangle beside a pill reads as a second control. The pill's own
   shape is what says it opens, and the state is announced by the element regardless.
   IT WEARS THE SECONDARY PILL AND NOT THE BURNT-SIENNA ONE, deliberately: the primary pill on a
   reveal is the one that moves the game forward ('Next round'), and a conversation is an offer
   beside it rather than a competitor for the same tap.
   TOUCH TARGET FIRST: 44px minimum, like every other control on this page.
   ========================================================================================== */
.g-retalk-fold { margin-top: 14px; }
.g-retalk-fold > summary { list-style: none; }
.g-retalk-fold > summary::-webkit-details-marker { display: none; }
.g-retalkpill {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; box-sizing: border-box; padding: 10px 18px;
  border-radius: 999px; cursor: pointer;
  font: inherit; font-weight: 700; font-size: .94rem;
  background: transparent; color: var(--orange-deep, #B54800);
  border: 1.5px solid var(--orange-deep, #B54800);
}
.g-retalkpill:hover { background: rgba(181, 72, 0, .08); }
.g-retalkpill:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 3px; }
.g-retalk-fold[open] > .g-retalkpill { margin-bottom: 10px; }

/* WO294 — AND THE DESIGNER'S INVITATION TO BE IDIOSYNCRATIC SITS WITH THE OTHER TWO SENTENCES
   UNDER THE TOPIC FIELD. It is `.m-fine` like both of them and takes one thing of its own: a
   little air above it, so three sentences in a row read as three rather than as a paragraph. */
.g-wsodd { display: block; margin-top: 6px; }

/* ---------- (e) THE FOCUS ANCHORS ----------
   An anchor is a `data-focus` attribute and NOT a style: the whole point is that the page owns
   the names and the payload owns the choosing. The one rule it needs is that a surface which
   has just been given tabindex="-1" and focused must not draw a focus ring — a member who was
   moved somewhere did not tab there, and a box round half the screen reads as an error. Every
   real control on these surfaces keeps its own :focus-visible ring, which is untouched. */
[data-focus]:focus { outline: none; }
[data-focus]:focus-visible { outline: 3px solid var(--orange-deep, #B54800); outline-offset: 4px;
  border-radius: 12px; }

/* ==========================================================================================
   WO298 (MATT, AUGUST 17 2026) — THE BOX ROUND "GAMES", AND IT IS THE ANCHOR ABOVE, HALF-DONE
   ==========================================================================================
   MATT: "a giant blue box around the games subtab on mobile, not on desktop."

   WHAT IT IS, MEASURED AT 390 IN A REAL BROWSER RATHER THAN GUESSED, and it is the third time
   this product has met the same shape (WO246's select, WO265's tap highlight): NOBODY WROTE A
   COLOUR. The games tab's heading is the `top` focus anchor — assets/games.js's FOCUS_SEL maps
   `top` to the bare selector 'h1' — and WO246's focus engine gives whatever it moves to
   `tabindex="-1"` and focuses it. A focused element the author has said nothing about draws the
   USER AGENT's ring, `outline: auto`, which WebKit and Blink paint in the PLATFORM ACCENT. On a
   phone that accent is blue.

   WHY IT READS AS GIANT ON A PHONE AND AS NOTHING ON A DESKTOP, and the answer is arithmetic
   rather than a second bug: an h1 is a block, so the ring is drawn round the whole content
   column. Measured: 358px of a 390px screen — ninety-two per cent of the width, a box across
   the top of everything — against 576px of 1280, which is a ring round a word in the middle of
   a wide page. Same ring, same code path, two completely different objects to look at. (It also
   survives an arrival more often on the phone: three plain loads in six at 390 against one in
   six at 1280, because the heading is further down a taller nav and the draw settles later.)

   WHY THE RULE DIRECTLY ABOVE DID NOT CATCH IT. WO246 (e) says the thing this order needed said
   — "a surface which has just been given tabindex='-1' and focused must not draw a focus ring…
   a box round half the screen reads as an error" — and then scoped it to `[data-focus]`. `top`
   is the one anchor in the table selected BY TAG rather than by attribute (it is the honest
   fallback, and the page's heading is not a surface a renderer marks up), so the one anchor the
   rule could not reach is the one every game falls back to.

   SO THE RULE IS RESTATED ON WHAT IT WAS ALWAYS ABOUT: tabindex="-1". An element with
   tabindex="-1" CANNOT BE REACHED BY TAB — that is the whole meaning of the value — so a focus
   ring on one can only ever be the product having moved somebody, which is exactly the case
   WO246 wrote its sentence for. Nothing a member can tab to is touched: every real control on
   these surfaces keeps its own :focus-visible ring, because every real control is tabbable and
   therefore not matched here.
   IT IS SCOPED TO `.g-pagewrap`, the games page's own main element, so this file says nothing
   about any other page's headings.
   ========================================================================================== */
.g-pagewrap [tabindex="-1"]:focus,
.g-pagewrap [tabindex="-1"]:focus-visible { outline: none; }
