/* ═══════════════════════════════════════════════════════════════
   MAFIA — leather, brass and lamplight.
   Built to the reference Sasha chose: seat cards with portraits on the
   left, transcript centre, role card top right, action bar below.
   The round table was tried and rejected — it read stiff, and a list
   of faces is what a player actually scans.
   Warm sepia ground, NOT cold slate. That is the whole difference.
   ═══════════════════════════════════════════════════════════════ */

:root{
  /* leather and lamplight */
  --wood:#1A1310;            /* the room */
  --wood-2:#221913;          /* panels */
  --wood-3:#2C211A;          /* raised cards */
  --wood-4:#3A2C22;          /* hover */
  --felt:#17211C;            /* the desk surface */
  --edge:#3E2F24;            /* card edges */
  --edge-2:#2A1F18;

  --bone:#EFE7D8;            /* everything you read */
  --bone-2:#B3A692;
  /* ⚠️ #7C6E5E measured 3.49:1 against the room and 4.25:1 against the panel —
     both below WCAG AA's 4.5:1 for body text, and it is the colour used by
     EVERY label, hint, badge and footer link on the page. Thirty-two failures
     came from this one line. #A2957F clears 4.5:1 on both grounds and is still
     unmistakably the quiet tier. Measured by a11y-test.mjs, not eyeballed. */
  --bone-3:#A2957F;
  --bone-4:#7C6E5E;          /* the old value, for things that are not text */

  --brass:#C9A227;           /* frames, the current turn */
  --brass-2:#8A6F1B;
  --brass-dim:#332912;

  --blood:#B4262C;           /* accusation, death, mafia — DOTS, BORDERS, GLOWS */
  /* ⚠️ #B4262C as TEXT measures 2.43–2.84:1 on the four grounds it is used on —
     WCAG AA wants 4.5:1 — and it is what "MAFIA" and "NAMED" were written in,
     on the board, for the whole game. Found only when the game board itself was
     added to a11y-test.mjs; every earlier pass audited the start screen and the
     legal page. #E0787C clears 4.5:1 on all four (worst 5.34:1) and still reads
     as the same red. Use --blood for shapes, --blood-lit for anything read. */
  --blood-lit:#E0787C;

  /* ⚠️ PRIVATE KNOWLEDGE — your partner, a seat you checked. It was a violet
     for one afternoon and violet was wrong: the only cool colour in a warm
     room, and it read as borrowed from another game. Identity does not need a
     colour of its own — it needs a channel STATE does not use. So it is the
     reading colour on a brass hairline, as an outlined chip rather than a
     filled pill, and it never competes with the red that means danger. */
  --known:#EFE7D8;              /* the reading colour — 13:1 on every seat ground */
  --known-2:#8A6F1B;            /* the hairline, same brass as the rest of the room */
  --blood-2:#7E1A1F;
  --blood-dim:#2E1213;
  --alive:#5E9A62;           /* the little green dot */

  --card:5px;
  --lift:0 1px 2px rgba(0,0,0,.5), 0 10px 24px -14px rgba(0,0,0,.95);
  --rule:linear-gradient(90deg,transparent,var(--brass-2) 12%,var(--brass) 50%,var(--brass-2) 88%,transparent);
}

*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0; color:var(--bone);
  font-family:Barlow,-apple-system,BlinkMacSystemFont,sans-serif;
  font-size:16px; line-height:1.5; -webkit-font-smoothing:antialiased;
  /* one lamp, warm, above a dark leather room */
  background:
    radial-gradient(ellipse 70% 55% at 50% 0%, rgba(201,162,39,.055), transparent 60%),
    radial-gradient(ellipse 120% 100% at 50% 45%, #241A14, var(--wood) 70%);
}
h1,h2,h3,.deco{font-family:Cinzel,Georgia,serif; margin:0; font-weight:600; letter-spacing:.02em}
button{font:inherit; cursor:pointer; border:none; background:none; color:inherit}
:focus-visible{outline:2px solid var(--brass); outline-offset:2px}
.hidden{display:none !important}
/* ⚠️ `overflow:hidden` used to live on bare `body`, so legal.html — which
   shares this stylesheet — inherited a page that could not scroll and a
   viewport-height box that cut the text off. The app is a fixed shell and
   never scrolls as a page; a document page is a document. */
/* ⚠️ THE FOOTER WAS UNREACHABLE, and had been since it was written.
   The shell is `height:100%; overflow:hidden` and `.screen` was `height:100%`,
   so the footer — a SIBLING of the screens — began exactly one pixel past the
   bottom of the window. The body could not scroll (overflow:hidden) and
   scrolling the screen did not move it, because it was never inside it.
   Terms, Privacy and Refunds were on the page and could not be clicked.

   The shell is a COLUMN now: the active screen takes the space that is left,
   the footer is a real row at the bottom, and `min-height:0` is what lets the
   screen shrink instead of pushing the footer back off the end. */
body.app{overflow:hidden; display:flex; flex-direction:column}
body.app > .screen{flex:1 1 auto; min-height:0}
body.app > .site-foot{flex:0 0 auto}
body.doc{height:auto; min-height:100%; overflow:visible}

.label{font-family:Cinzel,serif; font-size:.75rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase; color:var(--bone-3)}

/* ── screens ────────────────────────────────────────────── */
/* height:100% belonged to the old sibling layout. In the column shell the
   screen is a flex child and takes the room the footer does not. */
.screen{height:100%; overflow-y:auto; overflow-x:hidden}
body.app > .screen{height:auto}
/* Centre only while it fits. `align-items:center` on a container that is
   shorter than its content clips BOTH ends — that is how the title went off
   the top the moment the profile panel opened. */
#start,#over{display:flex; align-items:flex-start; justify-content:center; padding:40px 22px}
/* ⚠️ This was `margin:auto 0`. An auto margin on a flex item taller than its
   container centres the overflow — half above the scroll origin, where no
   amount of scrolling reaches it. That is how the title disappeared. The panel
   now starts at the top and simply scrolls, at every window height. */
.start-inner,.over-inner{width:100%; max-width:448px}

/* Two figures flanking the start panel — a menu composition, not a background.
   A picture BEHIND text is the mistake; beside it, it is atmosphere.
   They vanish below 1180px rather than crowding the controls. */
/* Two figures flanking the panel — a menu composition, not a background.
   A picture BEHIND text is the mistake; beside it, it is atmosphere.

   The panel gets its own solid ground so nothing bleeds under the controls,
   and the figures are pushed out far enough that the two never touch. They
   disappear entirely when the window is too narrow to hold both. */
/* Both figures were drawn facing the same way, so one of them looked out of
   the page instead of into it. The woman is mirrored to turn her inward; the
   flip lives in a custom property because the entrance keyframes rewrite
   `transform` and would otherwise drop it on the first frame. */
.hero{
  --flip:1;
  position:fixed; top:50%; width:clamp(240px, 26vw, 400px); height:auto;
  transform:translateY(-50%) scaleX(var(--flip));
  pointer-events:none; user-select:none;
  opacity:.85; z-index:0;
}
/* Close enough to the panel to be in the same room as it. They pass BEHIND it
   (z-index 0 against the panel's 1), so the overlap reads as depth, and the
   panel's outer glow does the blending. */
.hero-l{left:max(8px, calc(50% - 560px))}
.hero-r{right:max(8px, calc(50% - 560px)); --flip:-1}

/* The panel sits on its own ground — the figures may pass behind it, never
   through the text. A soft outer glow melts the edge into the room. */
.start-inner{
  position:relative; z-index:1;
  padding:30px 32px 34px; border-radius:6px;
  background:radial-gradient(ellipse 120% 100% at 50% 30%, #241A14, var(--wood) 72%);
  box-shadow:
    0 0 0 1px rgba(62,47,36,.55),
    0 0 70px 40px var(--wood),
    0 30px 80px -30px rgba(0,0,0,.95);
}

/* ⚠️ The outer edge was visibly cut. `.hero-r` is the same artwork mirrored with
   scaleX(-1), so whichever side the source image feathers, the mirror puts the
   HARD edge outward — and at 1180–1300px the figure sits only 8px from the
   window edge, where that hard line is impossible to miss.
   Fading the outer 18% of each figure to transparent fixes it at every width,
   without touching the artwork. The mask is applied in the element's own
   (already mirrored) space, so "left" here means "outward" for both. */
.hero{
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 18%, #000 100%);
          mask-image: linear-gradient(to right, transparent 0%, #000 18%, #000 100%);
}

/* Below 1180px there is no longer room for a figure, the panel and a margin. */
@media (max-width:1180px){ .hero{display:none} }
@media (prefers-reduced-motion:no-preference){
  .hero{animation:heroIn .9s ease-out both}
  .hero-r{animation-delay:.12s}
}
@keyframes heroIn{
  from{opacity:0;   transform:translateY(-50%) scaleX(var(--flip)) scale(1.03)}
  to  {opacity:.92; transform:translateY(-50%) scaleX(var(--flip)) scale(1)}
}

/* the title on a brass plate, as in the reference */
.title-block{text-align:center; margin-bottom:30px}
.plate{
  display:inline-block; padding:14px 40px; position:relative;
  background:linear-gradient(180deg,#3A2C1E,#241A11);
  border:1px solid var(--brass-2); border-radius:3px;
  box-shadow:inset 0 1px 0 rgba(201,162,39,.28), var(--lift);
}
.plate::before,.plate::after{
  content:''; position:absolute; top:50%; width:7px; height:7px; margin-top:-3.5px;
  border-radius:50%; background:radial-gradient(circle at 34% 30%, #E3C566, #7A6115);
}
.plate::before{left:12px} .plate::after{right:12px}
#start h1{font-size:clamp(2.4rem,8vw,3.4rem); line-height:1; letter-spacing:.2em; font-weight:700; text-indent:.2em; color:var(--bone)}
.tagline{font-size:.92rem; color:var(--bone-2); margin:16px 0 0}
.tagline b{color:var(--blood); font-weight:600}

.field{margin-bottom:19px}
.field > .label{display:block; margin-bottom:9px}
.field.row{display:flex; gap:22px; flex-wrap:wrap}
input[type=text],input[type=email],textarea,select{
  width:100%; background:var(--wood-2); border:1px solid var(--edge); border-radius:3px;
  color:var(--bone); padding:11px 13px; font:inherit; font-size:.94rem;
}
input::placeholder,textarea::placeholder{color:var(--bone-3)}
input:focus,textarea:focus,select:focus{border-color:var(--brass)}
/* The native dropdown arrived as a blue system popup in a sepia room. The
   closed control is fully ours; the open list is styled as far as the browser
   allows (Chrome, Edge and Firefox honour it — Safari draws its own popup and
   there is no web API that changes that). */
.pick{position:relative}
.pick::after{
  content:''; position:absolute; right:15px; top:50%; width:7px; height:7px;
  margin-top:-5px; pointer-events:none;
  border-right:1.5px solid var(--brass); border-bottom:1.5px solid var(--brass);
  transform:rotate(45deg);
}
select{
  appearance:none; -webkit-appearance:none; cursor:pointer; padding-right:38px;
  background:linear-gradient(180deg,#241A13,var(--wood-2));
}
select:hover{border-color:var(--brass-2)}
select option{background:#1B140F; color:var(--bone)}
select option:checked,select option:hover{background:#3A2C1E; color:var(--brass)}
textarea{resize:vertical; font-size:.89rem}
.sub-hint{font-size:.86rem; color:var(--bone-3); margin:7px 0 0; line-height:1.45}
/* ⚠️ Every link inside the panel was rendering in the browser's default blue,
   underlined in blue — the one colour on the page that belongs to 1994. It is
   the same defect as the white checkbox and the blue dropdown: a control left
   to the user agent. Brass, with a brass underline that only appears on hover. */
.start-inner a, .over-inner a, .fold-body a{
  color:var(--brass); text-decoration:none;
  border-bottom:1px solid rgba(201,162,39,.32);
  transition:border-color .14s, color .14s;
}
.start-inner a:hover, .over-inner a:hover, .fold-body a:hover{
  color:#E3C566; border-bottom-color:var(--brass);
}
/* The consent line is a sentence, not a row of links: they stay in the running
   text colour so the eye reads the sentence and not four blue words. */
.check.consent a{color:inherit; border-bottom:none; text-decoration:underline; text-underline-offset:2px}
.check.consent a:hover{color:var(--brass)}

/* ⚠️ Hard-coded at repeat(4,1fr). Coaching has THREE buttons, so it drew a
   fourth, empty, clickable-looking cell — the "missing button" on screen.
   Auto columns fit whatever is actually in the control. */
.seg{display:grid; grid-auto-flow:column; grid-auto-columns:1fr; gap:1px; background:var(--edge); border:1px solid var(--edge); border-radius:3px; overflow:hidden}
.seg button{padding:11px 4px; background:var(--wood-2); color:var(--bone-2); font-family:Cinzel,serif; font-size:.8rem; letter-spacing:.06em; text-transform:uppercase; transition:.14s}
.seg button:hover{background:var(--wood-3); color:var(--bone)}
.seg button.on{background:linear-gradient(180deg,var(--blood),var(--blood-2)); color:#fff}

.check{display:flex; align-items:center; gap:9px; cursor:pointer; font-size:.95rem; color:var(--bone-2)}
/* A native checkbox is a bright white OS control dropped into a dark room —
   the one element on the page that belongs to somebody else's design. Drawn
   here instead: an unlit brass plate that lights when it is ticked. */
/* ⚠️ WEBKIT WILL NOT LET YOU STYLE THIS ELEMENT, and two attempts proved it:
   `border:1px solid var(--bone-4)` computed to rgb(15,13,11) in Safari and
   rgb(124,110,94) in Chrome, and replacing the token with the literal changed
   nothing — WebKit keeps its own near-black border on a checkbox whatever the
   page says. On Safari the one box a player MUST tick to play was invisible.
   So the input is not styled at all any more. It stays for semantics, keyboard
   and the form; the box a person sees is drawn by the LABEL, which is an
   ordinary element that both engines render the way they are told. */
.check{ position:relative; }
.check input[type=checkbox]{
  position:absolute; left:0; top:50%; transform:translateY(-50%);
  width:17px; height:17px; margin:0; opacity:0; cursor:pointer;
}
.check::before{
  content:''; flex:0 0 auto; width:17px; height:17px; border-radius:3px;
  border:1px solid #7C6E5E;
  background:linear-gradient(180deg,#241A13,#1B140F);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.045);
  transition:border-color .14s, background .14s, box-shadow .14s;
}
.check::after{
  content:''; position:absolute; left:5px; top:50%;
  width:5px; height:9px; border:solid var(--brass); border-width:0 2px 2px 0;
  transform:translateY(-62%) rotate(45deg) scale(.6); transform-origin:center;
  opacity:0; transition:opacity .14s, transform .14s; pointer-events:none;
}
.check:hover::before{ border-color:var(--brass-2); }
.check:has(input:checked)::before{ border-color:var(--brass); background:linear-gradient(180deg,#3A2C1E,#241A11); }
.check:has(input:checked)::after{ opacity:1; transform:translateY(-62%) rotate(45deg) scale(1); }
.check:has(input:focus-visible)::before{ outline:2px solid var(--brass); outline-offset:2px; }
.check:has(input:disabled){ opacity:.5; }
/* And when the game is waiting for exactly this tick, it says so in the only
   language a form has: the control itself. */
.check.wanted::before{ border-color:var(--brass); box-shadow:0 0 0 3px rgba(201,162,39,.22); }
/* ── jumping to an anchor ────────────────────────────────────────────────────
   Both document pages have a sticky bar and a list of anchors, and a hard jump
   drops the reader somewhere with no sense of having travelled — on the
   characters page it is indistinguishable from the page having reloaded.
   `scroll-margin-top` is the other half and matters more than the animation:
   without it the heading lands UNDER the sticky bar, which is the actual defect
   an anchor link usually has. */
html{ scroll-behavior:smooth; }
:target{ scroll-margin-top:76px; }
.ch, h2[id], h3[id]{ scroll-margin-top:76px; }
/* ⚠️ A person who has asked their operating system to stop moving things has
   asked for exactly this too. */
@media (prefers-reduced-motion:reduce){ html{ scroll-behavior:auto; } }

@media (prefers-reduced-motion:reduce){ .check::after{ transition:none } }
@media (prefers-reduced-motion:reduce){ .check input[type=checkbox]::after{transition:none} }

.primary{
  width:100%; padding:15px; border-radius:3px; color:#fff;
  background:linear-gradient(180deg,#C22C33,var(--blood-2));
  border:1px solid var(--blood-2); box-shadow:inset 0 1px 0 rgba(255,255,255,.14), var(--lift);
  font-family:Cinzel,serif; font-weight:600; font-size:.93rem; letter-spacing:.15em; text-transform:uppercase;
  transition:filter .14s;
}
.primary:hover{filter:brightness(1.13)}
.primary:disabled{opacity:.45; cursor:default}
.ghost{padding:12px 20px; border:1px solid var(--edge); border-radius:3px; background:var(--wood-2); color:var(--bone-2); font-family:Cinzel,serif; font-size:.8rem; letter-spacing:.08em; text-transform:uppercase; transition:.14s}
.ghost:hover{border-color:var(--brass); color:var(--bone)}
.ghost.small{padding:9px 15px; font-size:.76rem}
.ghost.on{border-color:var(--brass); color:var(--brass); background:var(--brass-dim)}
.stats{font-size:.86rem; color:var(--bone-3); margin:16px 0 0; text-align:center; font-variant-numeric:tabular-nums}

.fold{border:1px solid var(--edge); border-radius:3px; background:var(--wood-2); margin-bottom:17px}
.fold summary{padding:13px 14px; cursor:pointer; list-style:none; display:flex; align-items:center; gap:10px; color:var(--bone-2); font-size:.92rem}
.fold summary::-webkit-details-marker{display:none}
.fold summary::after{content:'+'; margin-left:auto; color:var(--bone-3); font-family:"JetBrains Mono",monospace}
.fold[open] summary::after{content:'−'}
.fold summary:hover{color:var(--bone)}
.fold-body{padding:0 14px 14px; border-top:1px solid var(--edge-2)}
.badge{font-family:"JetBrains Mono",monospace; font-size:.72rem; color:var(--bone-3); margin-left:auto}

.engine{display:grid; gap:1px; background:var(--edge); border:1px solid var(--edge); border-radius:3px; overflow:hidden; margin-bottom:12px}
.engine button{display:grid; grid-template-columns:1fr auto; gap:10px; padding:11px 13px; background:var(--wood-2); text-align:left; transition:.14s}
.engine button:hover{background:var(--wood-3)}
.engine button.on{background:var(--brass-dim)}
.engine .en{font-size:.89rem; color:var(--bone)}
.engine .ed{display:block; font-size:.83rem; color:var(--bone-2); margin-top:2px}
.engine button.on .en{color:var(--brass)}
.engine .tick{font-family:"JetBrains Mono",monospace; font-size:.7rem; color:var(--bone-3); align-self:center}
.engine button.on .tick{color:var(--brass)}
.dl{height:3px; background:var(--edge); border-radius:2px; overflow:hidden; margin-top:10px}
.dl i{display:block; height:100%; background:var(--brass); width:0; transition:width .3s}

/* ── game shell ─────────────────────────────────────────── */
#game{display:flex; flex-direction:column}
.bar{
  display:grid; grid-template-columns:1fr auto 1fr; align-items:center; gap:14px;
  padding:0 18px; height:56px; flex:0 0 auto; position:relative; z-index:5;
  background:linear-gradient(180deg,#261C15,#1C1410); border-bottom:1px solid var(--edge);
}
.bar::after{content:''; position:absolute; left:0; right:0; bottom:-1px; height:1px; background:var(--rule); opacity:.35}
.bar-l{display:flex; align-items:center; gap:11px}
.bar-r{display:flex; align-items:center; gap:11px; justify-self:end}
.day{font-family:Cinzel,serif; font-size:.98rem; letter-spacing:.14em; text-transform:uppercase}
.dot{width:3px; height:3px; border-radius:50%; background:var(--bone-3)}
#aliveCount{font-size:.83rem; color:var(--bone-2); font-variant-numeric:tabular-nums}
/* the brass plate from the reference, carrying the phase */
.phase-plate{
  font-family:Cinzel,serif; font-size:.8rem; letter-spacing:.16em; text-transform:uppercase;
  padding:6px 22px; color:var(--brass); white-space:nowrap;
  background:linear-gradient(180deg,#3A2C1E,#241A11);
  border:1px solid var(--brass-2); border-radius:3px;
  box-shadow:inset 0 1px 0 rgba(201,162,39,.25);
}
.role-chip{font-family:Cinzel,serif; font-size:.78rem; letter-spacing:.13em; text-transform:uppercase; padding:5px 11px; border:1px solid var(--edge); border-radius:2px; color:var(--bone-2)}
.role-chip.civ,.role-chip.sheriff{border-color:var(--brass-2); color:var(--brass); background:var(--brass-dim)}
.role-chip.mafia{border-color:var(--blood-2); color:var(--blood-lit); background:var(--blood-dim)}
.icon{font-size:.92rem; padding:6px 9px; border-radius:3px; color:var(--bone-3)}
.icon:hover{background:var(--wood-3); color:var(--bone)}

/* ⚠️ 250px was not enough for a status row carrying two labels — SPEAKING and
   PARTNER ran into each other, and so did NAMED ×2. Widened rather than made
   smaller: the labels are words on purpose, and shrinking type to fit is how a
   card becomes unreadable instead of crowded. */
.board{flex:1; display:grid; grid-template-columns:296px 1fr; min-height:0}
@media (max-width:900px){ .board{grid-template-columns:1fr} }

/* ── seat cards ─────────────────────────────────────────── */
.seats{
  background:linear-gradient(180deg,#20170F,#1A1310);
  border-right:1px solid var(--edge); overflow-y:auto;
  padding:12px 10px 20px; display:flex; flex-direction:column; gap:7px;
}
.seats-head{padding:2px 4px 8px}
.seat{
  display:grid; grid-template-columns:22px 46px 1fr; align-items:center; gap:11px;
  padding:8px 10px; width:100%; text-align:left; position:relative;
  background:linear-gradient(180deg,var(--wood-3),#241A14);
  border:1px solid var(--edge); border-radius:var(--card);
  box-shadow:var(--lift); transition:.15s;
}
.seat .num{font-family:"JetBrains Mono",monospace; font-size:.78rem; color:var(--bone-3); text-align:center}
/* portrait slot — a monogram now, a painted face when the art arrives */
/* The portraits already carry their own gold ring, so the slot must add
   nothing — a square border around a framed circle reads as a double frame.
   The monogram fallback keeps the frame, because there it IS the frame. */
.portrait{
  width:46px; height:46px; display:grid; place-items:center; position:relative;
  font-family:Cinzel,serif; font-size:1.02rem; font-weight:700; color:var(--bone-3);
}
.portrait:not(:has(img)){
  border-radius:50%; border:1px solid var(--edge);
  background:linear-gradient(165deg,#3C2D22,#241A13);
}
.portrait img{width:100%; height:100%; object-fit:contain; display:block}
.seat.speaking .portrait img{filter:drop-shadow(0 0 7px rgba(201,162,39,.55))}
.seat.accused .portrait img{filter:drop-shadow(0 0 7px rgba(180,38,44,.6))}
.seat-main{min-width:0}
.seat .nm{display:block; font-size:.97rem; color:var(--bone); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.pill{
  display:inline-flex; align-items:center; gap:5px; margin-top:3px;
  font-family:"JetBrains Mono",monospace; font-size:.75rem; letter-spacing:.07em; text-transform:uppercase;
  color:var(--bone-3);
}
.pill i{width:5px; height:5px; border-radius:50%; background:var(--bone-3); display:block}
.pill.alive i{background:var(--alive); box-shadow:0 0 6px rgba(94,154,98,.7)}
.pill.accused{color:var(--blood-lit)} .pill.accused i{background:var(--blood); box-shadow:0 0 6px rgba(180,38,44,.8)}
.pill.speaking{color:var(--brass)} .pill.speaking i{background:var(--brass); box-shadow:0 0 7px rgba(201,162,39,.85)}
.pill.known{color:var(--known)} .pill.known i{background:var(--known-2); box-shadow:0 0 6px rgba(201,162,39,.5)}

.seat.you{border-color:var(--brass-2)}
.seat.you .portrait{border-color:var(--brass-2); color:var(--brass)}
.seat.you .nm{font-weight:600}
.seat.speaking{
  border-color:var(--brass);
  background:linear-gradient(180deg,#3A2E17,#241C10);
  box-shadow:0 0 0 1px rgba(201,162,39,.22), 0 0 24px -6px rgba(201,162,39,.4), var(--lift);
}
.seat.accused{border-color:var(--blood-2); background:linear-gradient(180deg,#33191A,#241213)}
/* Identity, so it must survive being named: `accused` still paints the red
   border and the red ground, and this adds a mark the red cannot remove. */
.seat.known.accused{border-color:var(--blood-2)}
/* A labelled chip, in the same place every time, in words. It sits UNDER the
   state pill rather than in a corner, because a corner is where the eye goes
   last and this is a fact the player is not allowed to miss. */
/* ⚠️ First version was appended to the SEAT, which is a flex row, so the chip
   wrapped onto a line of its own and hung outside the card. It belongs in the
   text column, directly under the state pill — same column, same rhythm. */
/* One status row: what is happening to this seat on the left, what only you
   know on the right. */
.pill-row{ display:flex; align-items:center; gap:8px; min-width:0; }
.pill-row .pill{ min-width:0; }
.seat-known{
  margin-left:auto; padding:1px 6px; flex:0 0 auto;
  font-family:"JetBrains Mono",monospace; font-size:.6rem; letter-spacing:.11em;
  text-transform:uppercase; line-height:1.7; white-space:nowrap;
  color:var(--bone-3); border:0; border-radius:2px;
  background:rgba(201,162,39,.10);
  pointer-events:none;
}
/* And a stripe down the edge, so the card is identifiable at a glance without
   reading anything at all. */
.seat.known{ box-shadow:inset 3px 0 0 var(--known-2); }
.seat{position:relative}
.seat.dead{opacity:.34}
.seat.dead .nm{text-decoration:line-through; text-decoration-thickness:1px}
.seat.dead .portrait{filter:grayscale(1) brightness(.7)}
.seat.pickable{cursor:pointer}
.seat.pickable:hover{border-color:var(--blood); background:linear-gradient(180deg,#3B2020,#2A1616); transform:translateX(2px)}
/* ⚠️ Absolutely positioned at the right edge, so it sat ON TOP of the identity
   tag — "NAMED ×2" printed straight through "PARTNER". Nothing on this card is
   positioned over anything any more: the row lays itself out. */
.seat .tally{
  order:3; flex:0 0 auto; margin-left:6px;
  font-family:"JetBrains Mono",monospace; font-size:.66rem; color:var(--blood-lit);
}

/* ── transcript ─────────────────────────────────────────── */
.talk{display:flex; flex-direction:column; min-width:0; min-height:0; position:relative;
  background:radial-gradient(ellipse 90% 70% at 50% 0%, rgba(201,162,39,.03), transparent 60%)}
.transcript{flex:1; overflow-y:auto; padding:26px 34px 14px}
.line{margin-bottom:18px; max-width:66ch; animation:rise .2s ease-out}
@keyframes rise{from{opacity:0; transform:translateY(3px)} to{opacity:1; transform:none}}
.line .who{font-family:Cinzel,serif; font-size:.76rem; letter-spacing:.14em; text-transform:uppercase; color:var(--brass-2); display:block; margin-bottom:5px}
.line .txt{font-size:1.06rem; line-height:1.66; color:var(--bone)}
.line.you .who{color:var(--brass)}
.line.sys{max-width:none; border-left:2px solid var(--edge); padding-left:14px; color:var(--bone-2); font-size:.95rem}
.line.sys b{color:var(--bone); font-weight:600}
.line.sys.day{
  border-left:none; text-align:center; margin:26px 0 22px; padding:0;
  font-family:Cinzel,serif; font-size:.74rem; letter-spacing:.26em; text-transform:uppercase; color:var(--brass);
  position:relative;
}
.line.sys.day::before,.line.sys.day::after{
  content:''; position:absolute; top:50%; width:24%; height:1px; background:var(--rule); opacity:.5;
}
.line.sys.day::before{left:4%} .line.sys.day::after{right:4%}
.line.sys.death{border-left-color:var(--blood)} .line.sys.death b{color:var(--blood)}
.line.sys.check{border-left-color:var(--brass)} .line.sys.check b{color:var(--brass)}
.caret{display:inline-block; width:8px; height:1.05em; background:var(--brass); vertical-align:-2px; animation:blink .9s steps(2) infinite}
@keyframes blink{50%{opacity:0}}

/* ── action bar ─────────────────────────────────────────── */
.act{
  grid-column:1 / -1; flex:0 0 auto; padding:14px 24px 16px; position:relative;
  background:linear-gradient(180deg,#241A13,#1B1410); border-top:1px solid var(--edge);
}
.act::before{content:''; position:absolute; left:0; right:0; top:-1px; height:1px; background:var(--rule); opacity:.35}
.act-head{display:flex; align-items:baseline; gap:12px; margin-bottom:12px; min-height:17px}
.act-head .label{color:var(--brass)}
.act-head .sub{font-size:.86rem; color:var(--bone-3)}
.act-row{display:flex; gap:10px; align-items:center; flex-wrap:wrap; min-height:44px}
.btn{
  padding:11px 20px; border-radius:3px; color:var(--bone-2);
  background:linear-gradient(180deg,var(--wood-3),#231A14); border:1px solid var(--edge);
  font-family:Cinzel,serif; font-size:.84rem; letter-spacing:.07em; text-transform:uppercase;
  box-shadow:var(--lift); transition:.14s;
}
.btn:hover{border-color:var(--brass-2); color:var(--bone)}
.btn.on{
  background:linear-gradient(180deg,#C22C33,var(--blood-2)); border-color:var(--blood-2); color:#fff;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.14), var(--lift);
}
.spacer{flex:1}
.mic{
  display:flex; align-items:center; gap:9px; padding:10px 16px; border-radius:3px;
  background:linear-gradient(180deg,var(--wood-3),#231A14); border:1px solid var(--edge);
  font-family:Cinzel,serif; font-size:.8rem; letter-spacing:.1em; text-transform:uppercase; color:var(--bone-2);
}
.mic:hover{border-color:var(--brass-2)}
.mic.live{border-color:var(--blood); background:var(--blood-dim); color:var(--blood)}
.mic kbd{font-family:"JetBrains Mono",monospace; font-size:.61rem; padding:2px 6px; border:1px solid var(--edge); border-radius:2px; color:var(--bone-3); letter-spacing:0}
.heard{min-height:21px; margin-top:9px; font-size:.9rem; color:var(--bone-2); font-style:italic; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.heard.err{color:var(--blood-2); font-style:normal}

/* ── result ─────────────────────────────────────────────── */
#over h2{font-size:clamp(1.8rem,6vw,2.5rem); letter-spacing:.14em; text-transform:uppercase}
#over h2.won{color:var(--brass)} #over h2.lost{color:var(--blood)}
.reveal{display:flex; flex-direction:column; gap:5px; margin-bottom:24px}
.rv{display:grid; grid-template-columns:36px 1fr auto; gap:12px; align-items:center; padding:10px 13px;
  background:linear-gradient(180deg,var(--wood-3),#241A14); border:1px solid var(--edge); border-radius:3px; font-size:.9rem}
.rv .tk{width:34px; height:34px; border-radius:3px; display:grid; place-items:center; font-family:Cinzel,serif; font-weight:700; font-size:.85rem; background:linear-gradient(165deg,#3C2D22,#241A13); border:1px solid var(--edge); color:var(--bone-3); overflow:hidden}
.rv .tk img{width:100%; height:100%; object-fit:contain}
.rv .tk:has(img){border:none; background:none}
.rv .r{font-family:Cinzel,serif; font-size:.72rem; letter-spacing:.12em; text-transform:uppercase; color:var(--bone-3)}
.rv.black{border-color:var(--blood-2); background:linear-gradient(180deg,#33191A,#241213)}
.rv.black .r{color:var(--blood)}
.rv.me{border-color:var(--brass-2)}
.over-actions{display:flex; gap:10px; margin-bottom:22px}
.over-actions .primary{flex:1}

.cast{display:flex; flex-direction:column; gap:6px}
.cast-row{display:grid; grid-template-columns:70px 1fr 32px; gap:9px; align-items:center}
.cast-row .who{font-size:.82rem; color:var(--bone-2)}
.cast-row select{font-size:.78rem; padding:6px 8px}
.cast-row .play{padding:6px 0; border:1px solid var(--edge); border-radius:2px; font-size:.73rem; color:var(--bone-3)}
.cast-row .play:hover{border-color:var(--brass); color:var(--brass)}

/* ── mobile ─────────────────────────────────────────────── */
@media (max-width:820px){
  .bar{grid-template-columns:1fr auto; height:50px}
  .phase-plate{display:none}
  .board{grid-template-columns:1fr; grid-template-rows:auto 1fr}
  .seats{border-right:none; border-bottom:1px solid var(--edge); flex-direction:row; overflow-x:auto; overflow-y:hidden; padding:10px 12px; gap:8px}
  .seats-head{display:none}
  .seat{grid-template-columns:auto; grid-auto-flow:row; justify-items:center; gap:5px; min-width:84px; padding:8px 10px; text-align:center}
  .seat .num{display:none}
  .seat .nm{font-size:.8rem; max-width:72px}
  .transcript{padding:18px 18px 8px}
  .act{padding:12px 16px 14px}
  .btn{padding:10px 14px; font-size:.7rem}
}
@media (prefers-reduced-motion:reduce){*{animation:none !important; transition:none !important}}

/* ── your own face ──────────────────────────────────────── */
/* Sex tabs — the grid used to be one scrolling column of 36 with the women
   below the fold, so a player saw only men and reasonably concluded that was
   all there was. */
.face-tabs{display:flex; gap:1px; background:var(--edge); border:1px solid var(--edge); border-radius:3px; overflow:hidden; margin-bottom:10px}
.face-tabs button{flex:1; padding:8px 4px; background:var(--wood-2); color:var(--bone-2); font-family:Cinzel,serif; font-size:.7rem; letter-spacing:.1em; text-transform:uppercase; transition:.14s}
.face-tabs button:hover{background:var(--wood-3); color:var(--bone)}
.face-tabs button.on{background:var(--brass-dim); color:var(--brass)}

/* 24 faces, men and women mixed, six across — four rows, no scrolling. */
.face-grid{display:grid; grid-template-columns:repeat(6,1fr); gap:9px; padding:3px}
.face-grid button{
  aspect-ratio:1; border-radius:50%; padding:0; overflow:hidden; position:relative;
  border:2px solid transparent; transition:.14s; background:none;
}
.face-grid button img{width:100%; height:100%; display:block; object-fit:contain}
.face-grid button:hover{transform:scale(1.09)}
.face-grid button.on{border-color:var(--brass); box-shadow:0 0 0 3px rgba(201,162,39,.28)}
/* ⚠️ The tick lived here and was CLIPPED: the button is round with
   `overflow:hidden`, so a mark at right:-1px bottom:-1px was cut in half
   against the portrait and read as a smudge on the picture rather than a
   confirmation. The replacement is further down — it sits outside the clip,
   on its own ground, with a ring that separates it from the face. */

/* ── the one upsell, and only when payments are actually switched on ── */
.upsell{
  display:flex; align-items:center; gap:14px; margin-bottom:17px; padding:13px 15px;
  border:1px solid var(--brass-2); border-radius:3px; background:var(--brass-dim);
}
.upsell-l{flex:1; min-width:0}
.upsell-t{display:block; font-family:Cinzel,serif; font-size:.86rem; letter-spacing:.08em; text-transform:uppercase; color:var(--brass)}
.upsell-d{display:block; font-size:.84rem; color:var(--bone-2); margin-top:3px}
.upsell .ghost{border-color:var(--brass-2); color:var(--brass); white-space:nowrap}
.upsell .ghost:hover{background:var(--brass); color:var(--wood)}

/* ═══ the coach report — the paid feature ══════════════════════════════
   It has to look like the reason to pay, so it gets the brass rule and the
   raised card the rest of the room only hints at. Everything here is text and
   two-colour bars: no images, no fonts, nothing that costs a request. */
.coach{
  margin:26px 0 4px; padding:20px 22px 22px;
  background:var(--wood-2); border:1px solid var(--edge); border-radius:var(--card);
  box-shadow:var(--lift); text-align:left;
}
.coach::before{ content:''; display:block; height:2px; margin:-20px -22px 18px; background:var(--rule) }
.coach-head{ display:flex; gap:14px; align-items:flex-start; margin-bottom:18px }
.coach-line{ margin:0; color:var(--bone); font-size:1rem; line-height:1.5 }
.coach-h{
  margin:22px 0 12px; font-size:.78rem; font-weight:700;
  letter-spacing:.10em; text-transform:uppercase; color:var(--bone-3);
}

/* the grade, on a brass token */
.grade{
  flex:none; width:44px; height:44px; border-radius:50%;
  display:grid; place-items:center; font-size:1.35rem; font-weight:700;
  color:var(--wood); background:var(--brass); border:2px solid var(--brass-2);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35);
}
.g-D,.g-F{ background:var(--blood); color:var(--bone); border-color:var(--blood-2) }

/* you, against a perfect reader of the same evidence */
.bars{ display:grid; gap:9px }
.bar-row{ display:grid; grid-template-columns:104px 1fr 44px; gap:10px; align-items:center }
.bar-lab{ font-size:.82rem; color:var(--bone-2) }
.bar-track{ height:9px; border-radius:5px; background:var(--edge-2); overflow:hidden }
.bar-fill{ display:block; height:100%; border-radius:5px }
.bar-fill.you{ background:var(--brass) }
.bar-fill.engine{ background:var(--alive) }
.bar-fill.chance{ background:var(--bone-3) }
.bar-val{ font-size:.82rem; color:var(--bone); text-align:right; font-variant-numeric:tabular-nums }

/* the lock. It names what is behind it — a locked panel that says nothing
   sells nothing — without naming a single player. */
.coach-lock{
  margin-top:20px; padding:18px; text-align:center;
  border:1px dashed var(--brass-2); border-radius:var(--card);
  background:linear-gradient(180deg, rgba(201,162,39,.06), transparent);
}
.lock-h{ margin:0 0 6px; color:var(--bone); font-size:.95rem; line-height:1.5 }
.coach-lock .sub-hint{ margin:0 0 14px }

/* the teaching moments */
.misses{ display:grid; gap:12px }
.miss{ display:grid; grid-template-columns:52px 1fr; gap:12px; align-items:start }
.miss-day{
  font-size:.72rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--brass); padding-top:2px;
}
.miss-note{ margin:0 0 3px; color:var(--bone); font-size:.92rem; line-height:1.5 }
.miss-t .sub-hint{ margin:0 }

/* the ledger */
.rounds{ display:grid; gap:1px; background:var(--edge-2); border-radius:var(--card); overflow:hidden }
.rnd{
  display:grid; grid-template-columns:34px 1fr 1fr 52px; gap:10px; align-items:center;
  padding:9px 12px; background:var(--wood-3); font-size:.86rem;
}
.rnd-d{ color:var(--bone-3); font-weight:700; font-size:.76rem }
.rnd-you{ color:var(--bone) }
.rnd-eng{ color:var(--bone-2) }
.rnd-v{
  text-align:right; font-size:.7rem; font-weight:700;
  letter-spacing:.08em; text-transform:uppercase; color:var(--bone-3);
}
.rnd.hit .rnd-v{ color:var(--alive) }

@media (max-width:560px){
  .rnd{ grid-template-columns:30px 1fr 44px }
  .rnd-eng{ display:none }
  .bar-row{ grid-template-columns:88px 1fr 40px }
}

/* ═══ what the subscription actually is ═══════════════════════════════
   A price with no list beside it is a button people do not press. */
.tiers{display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-top:12px}
.tier{
  background:var(--wood-3); border:1px solid var(--edge); border-radius:var(--card);
  padding:15px 16px;
}
.tier.paid{border-color:var(--brass-2); background:linear-gradient(180deg, rgba(201,162,39,.07), var(--wood-3))}
.tier-n{
  display:block; font-size:.72rem; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--bone-3); margin-bottom:10px;
}
.tier.paid .tier-n{color:var(--brass)}
.tier-n b{font-weight:700; color:var(--bone); letter-spacing:0; text-transform:none}
.tier ul{margin:0; padding-left:17px; display:grid; gap:6px}
.tier li{font-size:.86rem; color:var(--bone-2); line-height:1.45}
.tier.paid li{color:var(--bone)}
.tier li strong{color:var(--brass)}

/* ═══ the footer nobody reads until they are about to pay ═════════════ */
.site-foot{
  width:100%; max-width:900px; margin:0 auto; padding:9px 18px 11px;
  border-top:1px solid var(--edge-2);
  display:flex; gap:14px; flex-wrap:wrap; align-items:center; justify-content:center;
  font-size:.7rem; color:var(--bone-3);
}
.site-foot a{color:var(--bone-3); text-decoration:none; border-bottom:1px solid var(--edge)}
.site-foot a:hover{color:var(--brass); border-bottom-color:var(--brass-2)}
.site-foot a:focus-visible{outline:2px solid var(--brass); outline-offset:3px}
/* No footer at the table. A game screen is a full-height instrument — every
   row of legal chrome under it steals a row from the transcript, which is what
   pushed the board up the moment the footer appeared. Every game in this genre
   does the same: chrome on the lobby, nothing on the board. */
body.playing .site-foot{display:none}

/* ⚠️ THE ACTION BAR SLID DOWN WHEN THE TRANSCRIPT FILLED UP. `#game` is a
   `.screen`, and `.screen` carries `overflow-y:auto` — so once the talk column
   was taller than the window the WHOLE game screen scrolled, taking the buttons
   with it. Only one thing on this screen is allowed to scroll, and it is the
   transcript. The board takes the room that is left; the bar is pinned to the
   bottom of the window and stays there whatever the table says. */
body.playing #game{ overflow:hidden; min-height:0; }
body.playing #game > .board{ min-height:0; overflow:hidden; }
body.playing #game > .act{ flex:0 0 auto; }

@media (max-width:560px){ .tiers{grid-template-columns:1fr} }

/* A renewal inside seven days changes the panel's colour. Not alarming — just
   impossible to miss, because the alternative is a surprise charge. */
.upsell.warn{
  border-color:var(--brass-2);
  background:linear-gradient(180deg, rgba(201,162,39,.10), var(--wood-3));
}
.upsell.warn .upsell-t{color:var(--brass)}


/* ── registration + plan picker (added with the coach positioning) ───────── */
/* The promise under the title. It is the sentence that says what this is, so
   it gets the width of the panel and none of the tagline's weight. */
.promise { max-width: 34ch; margin: 8px auto 0; line-height: 1.5; }
.check.consent { align-items: flex-start; line-height: 1.45; }
.check.consent a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
/* Two prices side by side. On a narrow screen they stack rather than shrink —
   a 90px-wide price button is a mis-tap waiting to happen. */
.upsell-buttons { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
#upgradeYear { white-space: nowrap; }
@media (max-width: 420px) { .upsell-buttons { width: 100%; } .upsell-buttons button { flex: 1 1 auto; } }


/* ── progress panel ──────────────────────────────────────────────────────── */
/* Two bars per week, engine behind and you in front. No axis and no grid: the
   question is "is the gap closing", which is a shape, not a reading. */
.prog-head { display:flex; align-items:baseline; gap:10px; margin:14px 0 6px; flex-wrap:wrap; }
.prog-big  { font-size:28px; font-weight:600; font-family:'JetBrains Mono',monospace; }
.prog-big.up   { color:#7FB069; }
.prog-big.down { color:var(--blood-2,#c0392b); }
.down { color:var(--blood-2,#c0392b); }
.prog-weeks { display:flex; align-items:flex-end; gap:6px; height:64px; margin:14px 0 6px; }
.prog-week  { position:relative; flex:1 1 0; min-width:10px; height:60px; display:flex; align-items:flex-end; }
.prog-week .bar-e, .prog-week .bar-y { position:absolute; bottom:0; border-radius:2px 2px 0 0; }
.prog-week .bar-e { left:0; right:0;   background:rgba(255,255,255,.16); }
.prog-week .bar-y { left:22%; right:22%; background:#7FB069; }
.key-y, .key-e { display:inline-block; width:9px; height:9px; border-radius:2px; vertical-align:middle; }
.key-y { background:#7FB069; } .key-e { background:rgba(255,255,255,.16); }
.prog-spots { margin:8px 0 0; padding-left:18px; line-height:1.6; font-size:13px; }
.prog-spots li { margin-bottom:4px; }


/* Languages: two columns on anything but the narrowest phone. Ten single-file
   rows would push the consent box below the fold, which is where consent goes
   to be ignored. */
.lang-grid { display:grid; grid-template-columns:1fr 1fr; gap:6px 14px; margin-top:8px; }
.lang-grid .check { align-items:center; }
.lang-grid input:disabled + span { opacity:.65; }
@media (max-width:380px) { .lang-grid { grid-template-columns:1fr; } }


/* ── the start screen after registration was surfaced ────────────────────── */
/* Email and consent sit above the button now, so they need to read as one
   small block rather than as two more rows in a long form. */
.signup { margin-bottom: 16px; }
.signup .check.consent { margin-top: 10px; }
.signup #accountMsg:empty { display: none; }
.signup #accountMsg { margin: 8px 0 0; color: var(--brass); }
/* A fold inside a fold needs to look subordinate, or it reads as a sibling. */
.fold.inner { margin-top: 12px; border-left: 2px solid rgba(255,255,255,.07); }
.fold.inner > summary { font-size: .92em; opacity: .9; }


/* ── the in-game hint ────────────────────────────────────────────────────── */
/* Above the transcript, not inside it: a coaching line must never be mistaken
   for something a character said. Different ground, different colour, an icon. */
.hint-bar{
  display:flex; gap:9px; align-items:flex-start; margin:0 0 10px;
  padding:10px 13px; border-radius:3px; line-height:1.5; font-size:.93rem;
  background:rgba(201,162,39,.10); border:1px solid rgba(201,162,39,.30);
  color:#E4D9C4;
}
.hint-i{flex:0 0 auto; opacity:.85}
@media (max-width:560px){ .hint-bar{font-size:.88rem; padding:9px 11px} }


/* ── below the fold ──────────────────────────────────────────────────────── */
/* Everything a player does not need in order to press the button once. */
.more{margin-top:26px; padding-top:22px; border-top:1px solid var(--edge)}

/* ── the toast ───────────────────────────────────────────────────────────── */
/* There is no Save button any more. A change is written the moment it is made,
   and this is how the game says so — brass for done, blood for refused. */
.toast{
  position:fixed; left:50%; bottom:26px; z-index:60;
  transform:translate(-50%,14px); opacity:0; pointer-events:none;
  max-width:min(430px, calc(100vw - 32px));
  padding:12px 18px; border-radius:3px; font-size:.9rem; line-height:1.45;
  background:linear-gradient(180deg,#2A1F16,#1B140F);
  border:1px solid var(--brass-2); color:var(--bone);
  box-shadow:0 18px 40px -18px rgba(0,0,0,.95), inset 0 1px 0 rgba(201,162,39,.18);
  transition:opacity .22s ease, transform .22s ease;
}
.toast.on{opacity:1; transform:translate(-50%,0)}
.toast.bad{border-color:var(--blood); background:linear-gradient(180deg,#33161A,#1B0F10)}
.toast .t-i{color:var(--brass); margin-right:9px}
.toast.bad .t-i{color:#E0656C}
@media (prefers-reduced-motion:reduce){ .toast{transition:none} }

/* A label and its live read-out on one line, above the control they describe. */
.label-row{display:flex; align-items:baseline; gap:10px; margin:15px 0 8px}
.label-row .badge{margin-left:auto}


/* ═══ FIXES 2026-08-31 ═══════════════════════════════════════════════════ */

/* ── 3 · the page must not twitch on load ────────────────────────────────
   The HTML ships with NORMAL and OFF lit, and app.js then moves the highlight
   to whatever was saved and rewrites the sentence under it. The player sees the
   red block jump one segment and the whole panel shift by a line. That is the
   "дрыкается".

   The page is held for one frame while the saved settings are applied, then
   faded in. ⚠️ The keyframe is the SAFETY NET: if app.js never runs — a syntax
   error, a blocked module, a browser with modules off — the page still appears
   on its own after 1.2s. A reveal that depends on script is a blank page. */
body.app{ opacity:0; animation:appReveal 0s linear 1.2s forwards; }
body.app.ready{ opacity:1; animation:none; transition:opacity .14s ease; }
@keyframes appReveal{ to{ opacity:1 } }
@media (prefers-reduced-motion:reduce){ body.app.ready{transition:none} }

/* ── 3 · 27 · and it must not shift when a segment is pressed ────────────
   The sentence under Difficulty and Coaching is one line for some choices and
   two for others, so switching OFF → NUDGE moved everything below it, the
   button included. Two lines are reserved, always. */
/* ⚠️ 2.6em was a guess and it was 4px short: the hint is .86rem at line-height
   1.45, so one line is 19.95px and two are 39.9 — and 2.6em of 13.76px is 35.8.
   The button still moved by 4px between OFF and NUDGE. Measured, in px. */
.sub-hint.fixed-2{ min-height:40px; }
@media (max-width:560px){ .sub-hint.fixed-2{ min-height:60px; } }
@media (max-width:400px){ .sub-hint.fixed-2{ min-height:80px; } }

/* ── 5 · the tick on a chosen face was inside the ring ───────────────────
   `overflow:hidden` on a round button clipped it against the portrait, where it
   read as a smudge on the picture. It sits on the edge now, on its own ground,
   outside the clip. */
.face-grid button{ overflow:visible; }
.face-grid button img{ border-radius:50%; }
.face-grid button.on::after{
  content:'✓'; position:absolute; right:-3px; bottom:-3px;
  width:19px; height:19px; border-radius:50%;
  display:grid; place-items:center;
  font-size:11px; font-weight:700; line-height:1;
  color:#1B140F; background:linear-gradient(180deg,#E3C566,var(--brass));
  border:2px solid var(--wood); box-shadow:0 1px 4px rgba(0,0,0,.6);
}

/* ── 7 · the country list, without the operating system's blue ───────────
   `option:checked` alone is drawn by the OS on macOS. A background-image
   gradient is honoured where a flat background-color is not — it is the one
   lever a page has over a native popup in Chrome, Edge and Firefox.
   Safari draws its own popup and no web API changes that. */
select option{ background:#1B140F; color:var(--bone); }
select option:checked,
select option:hover,
select option:focus{
  background:linear-gradient(#3A2C1E,#3A2C1E) !important;
  background-color:#3A2C1E !important;
  color:var(--brass) !important;
}

/* ── 10 · which coaching level is running, at the table ──────────────────*/
.coach-chip{
  font-family:'JetBrains Mono',monospace; font-size:.66rem; letter-spacing:.08em;
  text-transform:uppercase; padding:4px 9px; border-radius:3px;
  border:1px solid var(--brass-2); color:var(--brass); background:var(--brass-dim);
}

/* ── 13 · the microphone explains itself ────────────────────────────────*/
.mic-tip{ margin:6px 0 0; }
.heard{ transition:color .14s; }

/* ── 14 · the paywall, in the game's own voice ──────────────────────────
   `alert('Payments are not switched on yet.')` is the browser's dialog, in the
   browser's font, on a grey sheet, with an OK button — the single most
   out-of-place thing that can appear on a page like this. */
.sheet{
  position:fixed; inset:0; z-index:80; display:grid; place-items:center;
  padding:22px; background:rgba(12,8,6,.78); backdrop-filter:blur(3px);
}
.sheet[hidden]{ display:none !important; }
.sheet-card{
  width:100%; max-width:430px; padding:28px 30px 24px; border-radius:5px;
  background:linear-gradient(180deg,#2A1F16,#1B140F);
  border:1px solid var(--brass-2);
  box-shadow:0 40px 90px -30px rgba(0,0,0,.95), inset 0 1px 0 rgba(201,162,39,.16);
  text-align:center;
}
.sheet-card h3{ font-size:1.25rem; color:var(--brass); margin-bottom:10px; }
.sheet-card p{ color:var(--bone-2); font-size:.93rem; line-height:1.6; margin:0 0 8px; }
.sheet-card .sheet-actions{ display:flex; gap:10px; justify-content:center; margin-top:20px; flex-wrap:wrap; }
@media (prefers-reduced-motion:no-preference){
  .sheet-card{ animation:sheetIn .18s ease-out both }
  @keyframes sheetIn{ from{opacity:0; transform:translateY(8px) scale(.98)} to{opacity:1} }
}

/* ── 15 · the copyright line sits apart from the links ──────────────────*/
.site-foot .foot-c{ opacity:.72; }

/* ── 16 · one red button per screen, and it is the one you came for ─────
   Red is the call to action and nothing else: Take a seat, Deal again, See the
   full report. Everything else is a ghost button on the room's own ground.
   Two reds on one screen is two primary actions, which is none. */
.act-row .btn.on{ background:linear-gradient(180deg,var(--blood),var(--blood-2)); color:#fff; border-color:var(--blood-2); }

/* ── 21 · the action row on a phone ─────────────────────────────────────
   The buttons wrapped into a ragged two-and-a-half rows and the microphone
   ended up alone under them. Below 560px they are a proper grid with a
   44px minimum target — the size a thumb actually hits. */
@media (max-width:560px){
  .act-row{ display:grid; grid-template-columns:1fr 1fr; gap:8px; min-height:0; }
  .act-row .btn{ min-height:46px; padding:10px 8px; font-size:.78rem; }
  .act-row .spacer{ display:none; }
  .act-row .mic{ grid-column:1 / -1; min-height:48px; }
  .act{ padding-bottom:calc(12px + env(safe-area-inset-bottom)); }
  .site-foot{ gap:10px 12px; font-size:.68rem; padding:8px 14px 10px; }
  .sheet-card{ padding:22px 20px 20px; }
}
/* ⚠️ This was max-width:400px, which caught a 390px iPhone and stacked three
   buttons into three rows. A 390px screen fits two columns comfortably; one
   column is for the genuinely tiny, and there is almost nothing below 340. */
@media (max-width:340px){
  .act-row{ grid-template-columns:1fr; }
}

/* ── 22 · accessibility ─────────────────────────────────────────────────
   Every interactive thing gets a visible focus ring on the keyboard, and a
   44px target where a finger is expected. The seat list is a listbox, so its
   focus ring must not be clipped by the scrolling column. */
.seats{ scroll-padding:8px; }
.seat:focus-visible,.face-grid button:focus-visible,.seg button:focus-visible,
.engine button:focus-visible,.fold summary:focus-visible{
  outline:2px solid var(--brass); outline-offset:2px; border-radius:3px;
}
/* A skip link, for someone arriving on the keyboard. */
.skip{
  position:absolute; left:-9999px; top:0; z-index:100;
  padding:10px 16px; background:var(--wood-2); color:var(--brass);
  border:1px solid var(--brass); border-radius:0 0 3px 0;
}
.skip:focus{ left:0; }


/* ── 4 · the download bar says what it is doing ─────────────────────────*/
.dl-row{ display:flex; align-items:center; gap:10px; margin-top:12px; }
.dl-row .dl-label{ font-size:.78rem; color:var(--bone-3); white-space:nowrap; }
.dl-row .dl{ flex:1 1 auto; margin-top:0; }
.dl-row .dl-pct{
  font-family:'JetBrains Mono',monospace; font-size:.74rem; color:var(--brass);
  min-width:3.4em; text-align:right; font-variant-numeric:tabular-nums;
}

/* ── 11 · the two figures ───────────────────────────────────────────────
   A menu flanked by portraits is a poster composition, and a poster puts the
   eye-line in the upper third — level with the title, not with the middle of a
   form. They sat at top:50% of the WINDOW while the panel starts at the top and
   is taller than it, so on a tall screen their heads landed beside the email
   field. Raised, widened a little, and pushed further out so nothing crowds the
   controls. Still symmetric, still facing inward, still gone below 1180px. */
.hero{ top:44%; width:clamp(250px, 27vw, 430px); }
.hero-l{ left:max(8px, calc(50% - 585px)) }
.hero-r{ right:max(8px, calc(50% - 585px)) }
@media (max-height:760px){ .hero{ top:47%; width:clamp(220px, 22vw, 340px); } }


/* ── 22 · contrast, and the targets a finger can hit ────────────────────── */

/* The tagline's red was #B4262C at 14.7px bold — 3.25:1, and bold only earns
   the relaxed 3.0 threshold from 18.66px. Red stays the accent; the TEXT red is
   lighter. The buttons keep the deep red, because white on it is 5.9:1. */
.tagline b{ color:#E0656C; }

/* A 23px checkbox row and a 20px footer link are below WCAG 2.2's 24px minimum
   target (2.5.8). On a phone they get the comfortable 44px instead. */
.check{ min-height:24px; }
.site-foot a{ display:inline-block; padding:2px 0; }
@media (max-width:560px){
  .check{ min-height:44px; }
  .site-foot{ gap:6px 14px; }
  .site-foot a{ padding:12px 4px; }
  .legal-nav-in a{ padding:12px 2px; display:inline-block; }
}

/* The legal page's own footer, so the document has a contentinfo landmark like
   every other page — a screen reader user should not lose the way out. */
/* The document page uses the SAME footer as the game — `.site-foot`. It only
   needs the width of the reading column and a little air under a long page. */
body.doc .site-foot{ max-width:680px; margin-top:38px; padding-bottom:40px; }

/* Inline links in the terms are exempt from the 24px target rule, but a comfortable
   line is still worth having on a phone — the text is read once, carefully, by
   someone deciding whether to trust us with a card. */
@media (max-width:560px){ .legal p, .legal li{ line-height:1.85; } }

/* A paragraph whose whole content is one link is a button in a link's clothes:
   it needs a real target, on every screen, not only on a phone. */
.legal p > a:only-child{ display:inline-block; padding:4px 2px; min-height:24px; }


/* ═══ FIXES round 4 ══════════════════════════════════════════════════════ */

/* ── 18 · the two chips at the table were different sizes ────────────────
   CIVILIAN is .role-chip and TEACH ME was .coach-chip, written separately and
   drifting apart. One size, one shape, one baseline. */
.role-chip,.coach-chip{
  font-family:'JetBrains Mono',monospace; font-size:.7rem; letter-spacing:.09em;
  text-transform:uppercase; padding:6px 11px; border-radius:3px;
  line-height:1; display:inline-flex; align-items:center; min-height:28px;
}

/* ── 19 · a button pressed against the paragraph above it ────────────────
   "SEE WHAT IT COSTS прямо под текстом" — no air, so it read as part of the
   sentence rather than as the thing to press. */
.fold-body .act-row{ margin-top:16px; }

/* ── 29 · the table is read at a glance, so it has to be legible ─────────
   Names at .97rem, statuses at .62rem and the day header at .68 were sized for
   a dense dashboard, not for a game you look up at between lines. Everything
   on the board goes up one step. The design does not change — only the size,
   the weight and the room between them. */
.seat .nm{ font-size:1.05rem; font-weight:500; }
.seat .pill{ font-size:.72rem; letter-spacing:.09em; }
.seats-head .label{ font-size:.78rem; }
.bar .day{ font-size:1.15rem; }
.bar-l{ font-size:.92rem; }
.transcript .line .who{ font-size:.8rem; letter-spacing:.12em; }
.transcript .line .txt,.transcript .line p{ font-size:1.02rem; line-height:1.62; }
.act-head .label{ font-size:.82rem; }
.act-head .sub{ font-size:.86rem; }
.act-row .btn{ font-size:.84rem; }
.heard{ font-size:.95rem; }
.hint-bar{ font-size:.98rem; }
@media (max-width:560px){
  .seat .nm{ font-size:1rem; }
  .transcript .line .txt,.transcript .line p{ font-size:1rem; }
  .hint-bar{ font-size:.94rem; }
}


/* ═══ FIXES round 6 ══════════════════════════════════════════════════════ */

/* ── 19 · the save note sits at the far end of the row it belongs to ─────*/
.saved-note{ margin:0 0 0 auto; text-align:right; }

/* ── 17 · the scrollbars ─────────────────────────────────────────────────
   Two bright grey system bars down the middle of a sepia room — the same
   mistake as the white checkbox and the blue dropdown, and the most visible
   one because they sit against the darkest part of the page. Drawn in brass,
   thin, and only while there is something to scroll. Firefox gets the two
   properties it understands; WebKit and Chromium get the full treatment. */
.seats, .transcript, .fold-body, .legal, .screen{
  scrollbar-width: thin;
  scrollbar-color: var(--edge) transparent;
}
.seats::-webkit-scrollbar,
.transcript::-webkit-scrollbar,
.screen::-webkit-scrollbar,
.fold-body::-webkit-scrollbar{ width:8px; height:8px; }
.seats::-webkit-scrollbar-track,
.transcript::-webkit-scrollbar-track,
.screen::-webkit-scrollbar-track,
.fold-body::-webkit-scrollbar-track{ background:transparent; }
.seats::-webkit-scrollbar-thumb,
.transcript::-webkit-scrollbar-thumb,
.screen::-webkit-scrollbar-thumb,
.fold-body::-webkit-scrollbar-thumb{
  background:var(--edge); border-radius:4px;
  border:2px solid transparent; background-clip:content-box;
}
.seats::-webkit-scrollbar-thumb:hover,
.transcript::-webkit-scrollbar-thumb:hover,
.screen::-webkit-scrollbar-thumb:hover{ background:var(--brass-2); background-clip:content-box; }
.seats::-webkit-scrollbar-corner,
.transcript::-webkit-scrollbar-corner{ background:transparent; }


/* ═══ FIXES round 7 ══════════════════════════════════════════════════════ */

/* ── 2 · the move, beside the name that made it ──────────────────────────*/
.line .names{
  margin-left:10px; color:var(--blood); font-family:'JetBrains Mono',monospace;
  font-size:.68rem; letter-spacing:.06em; text-transform:none;
}
.line.you .names{ color:#E0656C }

/* ── 1 · the reading column is CENTRED, not left-aligned in a wide pane ──
   `.line{max-width:66ch}` is the right measure — 66 characters is what an eye
   reads without losing the line. But left-aligned inside a 1600px pane it
   looks like text breaking in the middle of the screen for no reason, which
   is exactly how it was reported. Centring the column makes the whitespace
   symmetrical, and a symmetrical margin reads as a decision. */
.transcript{ padding-inline: max(34px, calc((100% - 74ch) / 2)); }
@media (max-width:900px){ .transcript{ padding-inline:20px } }

/* Who is signed in, and the way out. Quiet by design — it is a safety valve, not
   a call to action — but it must be findable, because on a shared machine the
   second person cannot start without it. */
/* Below the button and visibly separate from it: a quiet account line, not a
   second call to action. */
.whoami{
  margin:16px 0 0; padding-top:14px; border-top:1px solid var(--edge-2);
  font-size:.84rem; color:var(--bone-3);
  display:flex; gap:12px; align-items:baseline; flex-wrap:wrap; justify-content:center;
}
/* ⚠️ 196x21 — under WCAG 2.5.8's 24x24 minimum, caught by a11y-test the first
   time it ran after this button existed. The inline-link exception does not
   apply: it stands on its own line, it is not a link inside a sentence. */
.linkish{
  background:none; border:0; padding:4px 2px; min-height:24px; font:inherit;
  color:var(--brass); text-decoration:underline; text-underline-offset:3px; cursor:pointer;
}
.linkish:hover{ color:var(--bone); }

/* ── the country list, drawn by the page instead of by the operating system ──
   The native <select> stays as the value; this is what a person sees. */
.combo{ position:relative; }
.combo-native{ position:absolute; width:1px; height:1px; opacity:0; pointer-events:none; }
.combo-btn{
  width:100%; text-align:left; cursor:pointer;
  font:inherit; color:var(--bone); background:linear-gradient(180deg,#241A13,#1B140F);
  border:1px solid var(--edge); border-radius:4px; padding:11px 34px 11px 12px;
  min-height:44px;
}
.combo-btn:hover{ border-color:var(--brass-2); }
.combo.open .combo-btn{ border-color:var(--brass); }
.combo-btn::after{
  content:''; position:absolute; right:14px; top:50%; width:7px; height:7px;
  border-right:1.5px solid var(--bone-3); border-bottom:1.5px solid var(--bone-3);
  transform:translateY(-70%) rotate(45deg); pointer-events:none;
}
.combo-list{
  position:absolute; z-index:40; left:0; right:0; top:calc(100% + 5px);
  margin:0; padding:5px; list-style:none; max-height:280px; overflow-y:auto;
  background:#1B140F; border:1px solid var(--brass-2); border-radius:4px;
  box-shadow:0 14px 40px rgba(0,0,0,.6);
}
.combo-opt{
  padding:9px 11px; border-radius:3px; cursor:pointer; color:var(--bone-2);
  min-height:24px; display:flex; align-items:center;
}
.combo-opt.active{ background:#3A2C1E; color:var(--bone); }
.combo-opt.on{ color:var(--brass); }
.combo-opt.on::after{ content:'✓'; margin-left:auto; }

/* One week is not a trend, so it is not drawn as one: three numbers, read left
   to right, instead of a chart with a single bar floating in an empty box. */
.prog-now{
  display:flex; gap:26px; flex-wrap:wrap; align-items:flex-end;
  margin:16px 0 4px; padding:14px 0 0; border-top:1px solid var(--edge-2);
}
.prog-now > div{ display:flex; flex-direction:column; gap:3px; }
.prog-n{ font-family:Cinzel,serif; font-size:1.6rem; line-height:1; color:var(--bone); }
.prog-n.dim{ color:var(--bone-3); }
.prog-now .label{ font-size:.66rem; letter-spacing:.12em; }

/* ── the turning point ──────────────────────────────────────────────────────
   The first thing in the report and the only thing a player has to read. It is
   deliberately typographic rather than a chart: this is a sentence about one
   move, and a chart would make it look like more data. */
.turning{
  margin:2px 0 18px; padding:14px 16px; border-radius:var(--card);
  background:linear-gradient(180deg,#241A13,#1B140F);
  border:1px solid var(--brass-2);
}
.turning .label{ color:var(--brass); margin:0 0 8px; }
.turn-ev{ margin:0 0 6px; font-size:1.02rem; color:var(--bone); line-height:1.5; }
.turn-you,.turn-cost{ margin:0 0 4px; font-size:.9rem; color:var(--bone-2); line-height:1.5; }
.turn-lesson{
  margin-top:12px; padding-top:11px; border-top:1px solid var(--edge-2);
  display:flex; gap:11px; align-items:baseline; flex-wrap:wrap;
}
.turn-l-lab{
  flex:0 0 auto; font-family:"JetBrains Mono",monospace; font-size:.62rem;
  letter-spacing:.14em; text-transform:uppercase; color:var(--brass);
}
.turn-l-txt{ margin:0; flex:1 1 260px; min-width:0; font-size:.93rem; color:var(--bone); line-height:1.55; }
.turning.locked{ border-style:dashed; }
.turn-cost.blur{ color:var(--bone-3); font-style:italic; }

/* ── who they were, and what that kind of player normally does ───────────── */
.turn-who{
  margin:10px 0; padding:10px 12px; border-left:2px solid var(--brass-2);
  background:rgba(201,162,39,.06); border-radius:0 3px 3px 0;
}
.who-h{ margin:0 0 5px; }
.who-name{ font-family:Cinzel,serif; font-size:.98rem; color:var(--brass); letter-spacing:.02em; }
.who-short{ color:var(--bone-3); font-size:.9rem; }
.who-tell{ margin:0 0 5px; font-size:.9rem; color:var(--bone-2); line-height:1.5; }
.who-stat{ margin:0 0 3px; font-size:.88rem; color:var(--bone); line-height:1.5; }

.cast-list{ display:flex; flex-direction:column; gap:8px; margin:10px 0 6px; }
.cast-p{ padding:9px 12px; border:1px solid var(--edge); border-radius:var(--card); background:var(--wood-2); }
.cast-p.was-black{ border-color:var(--blood-2); }
.cast-top{ margin:0 0 3px; display:flex; gap:10px; align-items:baseline; flex-wrap:wrap; }
.cast-nm{ color:var(--bone); font-size:.98rem; }
.cast-ch{ font-family:Cinzel,serif; color:var(--brass); font-size:.86rem; }
.cast-role{
  margin-left:auto; font-family:"JetBrains Mono",monospace; font-size:.6rem;
  letter-spacing:.12em; text-transform:uppercase; color:var(--bone-3);
}
.cast-p.was-black .cast-role{ color:var(--blood-lit); }
.cast-tell{ margin:0; font-size:.85rem; color:var(--bone-3); line-height:1.5; }

/* The daily allowance, said in words at the moment it applies. */
.quota{
  margin:0 0 12px; padding:8px 12px; border-radius:4px;
  font-size:.86rem; line-height:1.5; color:var(--bone-2);
  background:rgba(201,162,39,.08); border-left:2px solid var(--brass-2);
}
.quota.spent{ color:var(--bone); background:rgba(201,162,39,.13); border-left-color:var(--brass); }

/* The half of the progress panel a free player can see the shape of. */
.spots-locked{
  margin-top:8px; padding:12px 14px; border:1px dashed var(--brass-2);
  border-radius:var(--card); background:rgba(201,162,39,.05);
}
.spots-locked p{ margin:0 0 6px; font-size:.92rem; line-height:1.5; color:var(--bone-2); }
.spots-locked p b{ color:var(--bone); }



/* ── the eight kinds of player ───────────────────────────────────────────────
   A gallery, not a document. The portraits are the reason a stranger reads it,
   so they are the largest thing on the page and the type is arranged around
   them — one column of reading beside one face, at a size where the face is a
   person rather than a thumbnail. */
body.chars{ background:var(--wood); }
.ch-wrap{ max-width:1120px; margin:0 auto; padding:0 22px 80px; }
/* The sticky bar: the way out on the left, the way around on the right. */
.ch-nav{
  position:sticky; top:0; z-index:5;
  background:rgba(26,19,16,.92); backdrop-filter:blur(8px);
  border-bottom:1px solid var(--edge);
}
@supports not (backdrop-filter: blur(1px)){ .ch-nav{ background:var(--wood); } }
.ch-nav-in{
  max-width:1120px; margin:0 auto; padding:10px 22px;
  display:flex; gap:18px; align-items:center; justify-content:space-between; flex-wrap:wrap;
}
.ch-out{
  flex:0 0 auto; color:var(--bone-2); text-decoration:none; font-size:.86rem;
  padding:6px 0; min-height:24px; display:inline-flex; align-items:center;
}
.ch-out:hover{ color:var(--brass); }
.ch-jump{ display:flex; gap:2px; flex-wrap:wrap; justify-content:flex-end; min-width:0; }
.ch-jump a{
  color:var(--bone-3); text-decoration:none; font-size:.76rem; letter-spacing:.02em;
  padding:6px 8px; border-radius:3px; min-height:24px; display:inline-flex; align-items:center;
}
.ch-jump a:hover{ color:var(--brass); background:rgba(201,162,39,.08); }
@media (max-width:700px){ .ch-jump{ display:none; } }

.ch-hero{ padding:40px 0 28px; max-width:64ch; }
.ch-eyebrow{
  margin:0 0 12px; font-family:"JetBrains Mono",monospace; font-size:.66rem;
  letter-spacing:.2em; text-transform:uppercase; color:var(--brass);
}
.ch-hero h1{
  margin:0 0 18px; font-family:Cinzel,serif; font-weight:600;
  font-size:clamp(2rem,5.5vw,3.2rem); line-height:1.05; color:var(--bone);
  letter-spacing:.01em;
}
.ch-dek{ margin:0 0 14px; font-size:1.1rem; line-height:1.6; color:var(--bone-2); }
.ch-dek strong{ color:var(--bone); }
.ch-note{ margin:0; font-size:.92rem; line-height:1.6; color:var(--bone-3); }
.ch-note b{ color:var(--bone-2); }

/* The three verdicts, shown once at the top so the tags on the cards mean
   something before the first card is read. */
.ch-key{ display:flex; gap:10px; flex-wrap:wrap; padding:0 0 26px; border-bottom:1px solid var(--edge-2); }
.ch-verdict{
  display:inline-block; padding:3px 10px; border-radius:20px;
  font-family:"JetBrains Mono",monospace; font-size:.62rem; letter-spacing:.11em;
  text-transform:uppercase; white-space:nowrap; border:1px solid transparent;
}
.ch-verdict.read{ color:var(--brass); background:rgba(201,162,39,.13); border-color:var(--brass-2); }
/* Four bands, four weights — the tag is the first thing read and it has to
   rank at a glance without colour alone carrying the meaning. */
.ch-verdict.loud{ color:var(--bone); background:rgba(201,162,39,.09); border-color:var(--edge); }
.ch-verdict.soft{ color:var(--bone-2); background:rgba(178,166,146,.07); border-color:var(--edge-2); }
.ch-verdict.flat{ color:var(--blood-lit); background:rgba(180,38,44,.11); border-color:var(--blood-2); }

.ch-grid{ display:flex; flex-direction:column; gap:0; margin:0 0 44px; }
.ch{
  display:grid; grid-template-columns:1fr; gap:0;
  padding:30px 0; border-bottom:1px solid var(--edge-2); scroll-margin-top:64px;
}
@media (min-width:720px){
  .ch{ grid-template-columns:220px 1fr; gap:30px; align-items:start; }
}
@media (min-width:1000px){
  .ch{ grid-template-columns:260px 1fr; gap:38px; }
}
.ch-face{ margin:0 0 16px; }
@media (min-width:720px){ .ch-face{ margin:0; position:sticky; top:22px; } }
.ch-face img{
  display:block; width:100%; max-width:260px; height:auto; border-radius:50%;
  box-shadow:0 14px 42px -18px #000;
}
.ch-body{ min-width:0; max-width:60ch; }
.ch-body .ch-verdict{ margin-bottom:10px; }
.ch h3{
  margin:0 0 3px; font-family:Cinzel,serif; font-size:1.5rem; line-height:1.15;
  color:var(--bone); letter-spacing:.01em;
}
.ch-short{ margin:0 0 12px; font-size:.9rem; color:var(--bone-3); font-style:italic; }
.ch .tell{ margin:0 0 10px; font-size:1rem; color:var(--bone-2); line-height:1.6; }
.ch .watch{ margin:0 0 14px; font-size:.96rem; color:var(--bone-2); line-height:1.6; }
.ch .watch b{
  color:var(--brass); font-family:"JetBrains Mono",monospace; font-size:.64rem;
  letter-spacing:.13em; text-transform:uppercase; margin-right:6px;
}
.ch .stat{
  margin:0 0 7px; padding:10px 13px; font-size:.94rem; line-height:1.55;
  color:var(--bone); background:linear-gradient(180deg,#241A13,#1D160F);
  border:1px solid var(--edge); border-left:2px solid var(--brass-2);
  border-radius:0 4px 4px 0;
}
.ch .stat.terse{ color:var(--bone-3); font-size:.88rem; border-left-color:var(--edge); }

.ch-how{ max-width:64ch; padding-top:8px; }
.ch-how h2{ margin:0 0 14px; font-family:Cinzel,serif; font-size:1.5rem; color:var(--bone); }
.ch-how p{ margin:0 0 14px; font-size:1rem; line-height:1.65; color:var(--bone-2); }
.ch-how p strong{ color:var(--bone); }
.ch-cta{ margin-top:26px; display:flex; gap:14px; align-items:baseline; flex-wrap:wrap; }
.ch-cta a{
  display:inline-block; padding:6px 0; min-height:24px;
  font-family:Cinzel,serif; font-size:1.02rem; letter-spacing:.03em;
  color:var(--brass); text-decoration:none; border-bottom:1px solid var(--brass-2);
}
.ch-cta a:hover{ color:var(--bone); border-color:var(--bone-3); }
.ch-cta-note{ font-size:.86rem; color:var(--bone-3); }
a.cta{
  display:inline-block; padding:13px 26px; border-radius:3px; text-decoration:none;
  font-family:Cinzel,serif; letter-spacing:.09em; text-transform:uppercase; font-size:.88rem;
  color:#fff; background:linear-gradient(180deg,var(--blood),var(--blood-2)); border:1px solid var(--blood-2);
}
a.cta:hover{ filter:brightness(1.12); }

/* The one contextual link out of the lobby — placed where the question it
   answers is already in the player's head, not buried in the footer. */
.learn-link{ margin-top:8px; }
/* ⚠️ 263x19 — under WCAG 2.5.8's 24x24 minimum. It stands on its own line, so
   the inline-link exception does not apply to it. */
.learn-link a{
  display:inline-block; padding:4px 0; min-height:24px;
  color:var(--brass); text-decoration:none; font-size:.88rem;
  border-bottom:1px solid var(--brass-2);
}
.learn-link a:hover{ color:var(--bone); border-color:var(--bone-3); }
