/* The Dare Room — the "game night box" look (Virtec picked it on 2026-10-19
   from the look-and-feel review): cream paper, ink outlines and sticker
   shadows, every game its own coloured box, the red die as a mascot.

   Rules that keep it consistent:
   - Font sizes come from the type scale (--t*), stepping up at a breakpoint
     rather than sliding with clamp(). Gaps come from the space scale (--s*);
     the few exceptions are a game's own geometry (the die, the boards).
     Need another size? Add a step here rather than a one-off value.
   - One card style (.panel and friends: white, ink edge, sticker shadow) and one
     accent card (.result-card, the dare card). A card never sits in a card:
     end screens and hand-offs are plain paper, so the dare card or role card is
     the only card there. Small things inside a card are "inset": paper, a thin
     ink edge, no shadow.
   - One "not yet" look: a disabled control goes flat (no shadow), its edge
     dashed and its colours drained to --ink-soft; an icon-only control just
     drains to --ink-soft.
   - Red is the action colour and the error colour; errors use --red-text so
     they never look like a headline.
   - Mobile first. No fixed or sticky bars except the room chat on phones
     (iOS Safari's moving toolbar is a trap TheDareRoom paid for).
   - One web font, Montserrat (self-hosted, web/assets/vendor/montserrat), for
     headings, buttons and the logo. Body text stays the system sans. */

@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../vendor/montserrat/montserrat-latin-wght.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: light;

  /* paper and ink */
  --paper: #fff6e9;
  --paper-deep: #f6e6cc;
  --card: #ffffff;
  --ink: #231b3a;
  --ink-soft: #5e5677; /* secondary text: 6.4:1 on paper, 6.8:1 on white */
  --rule: rgba(35, 27, 58, 0.16); /* hairlines inside a card */

  /* the box colours: every game has one (text colour after the slash) */
  --red: #d7263d; /* / white 5.0:1 */
  --red-text: #b3172c; /* red words on paper or white: 6.4:1 */
  --red-wash: #ffe3e6;
  --gold: #ffc233; /* / ink */
  --purple: #6a3df0; /* / white 5.9:1; links on paper 5.5:1 */
  --teal: #12b5a6; /* / ink */
  --sky: #3fa9f5; /* / ink */
  --pink: #ff7aa8; /* / ink */
  --orange: #ff8a3d; /* / ink */
  --navy: #1f3b70; /* / white */
  --lime: #9be15d; /* / ink: Would You Rather */
  --lilac: #c4a3ff; /* / ink: Never Have I Ever */
  --green: #0b7a52; /* "in", "+1", wins: 5.0:1 on paper */
  --mint: #d6f5e7;

  /* edges and the sticker shadow */
  --edge: 3px solid var(--ink);
  --edge-thin: 2px solid var(--ink);
  --lift: 4px 4px 0 var(--ink);
  --lift-big: 6px 6px 0 var(--ink);
  --lift-small: 2px 2px 0 var(--ink);
  --r-xs: 6px; /* marks on the game boards */
  --r-s: 10px;
  --r: 16px;
  --r-l: 24px;

  /* type: the only sizes on the site (--t72 is for giant numbers only) */
  --t12: 0.75rem;
  --t14: 0.875rem;
  --t16: 1rem;
  --t18: 1.125rem;
  --t20: 1.25rem;
  --t24: 1.5rem;
  --t32: 2rem;
  --t48: 3rem;
  --t72: 4.5rem;
  --display: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* space */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --gutter: 16px;
  --max: 1080px;

  /* the page's own game colour (set per page below) */
  --game: var(--gold);
  --game-ink: var(--ink);
}

.page-wheel { --game: var(--sky); }
.page-dice { --game: var(--red); --game-ink: #fff; }
.page-tod { --game: var(--purple); --game-ink: #fff; }
.page-imposter { --game: var(--teal); }
.page-pairs { --game: var(--gold); }
.page-tower { --game: var(--orange); }
.page-bs { --game: var(--navy); --game-ink: #fff; }
.page-room { --game: var(--pink); }
.page-wyr { --game: var(--lime); }
.page-nhie { --game: var(--lilac); }

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

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

body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--paper);
  /* a faint dot grid, like the inside of a game box */
  background-image: radial-gradient(rgba(35, 27, 58, 0.07) 1px, transparent 1.4px);
  background-size: 22px 22px;
  color: var(--ink);
  font: var(--t16)/1.55 var(--body);
  overflow-x: hidden;
}

a { color: var(--purple); text-underline-offset: 3px; text-decoration-thickness: 2px; }
a:hover { color: var(--ink); }
h1, h2, h3 { font-family: var(--display); font-weight: 800; line-height: 1.15; margin: 0 0 0.5em; letter-spacing: -0.01em; }
h1 { font-size: var(--t32); }
h2 { font-size: var(--t20); }
h3 { font-size: var(--t18); }
p { margin: 0 0 1em; }
strong { font-weight: 700; }
.muted { color: var(--ink-soft); }
.fine { font-size: var(--t14); }
[hidden] { display: none !important; }

:focus-visible { outline: 3px solid var(--purple); outline-offset: 3px; border-radius: 6px; }

.skip { position: absolute; left: -9999px; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.skip:focus { left: var(--gutter); top: var(--s2); z-index: 10; background: var(--gold); color: var(--ink); padding: var(--s2) var(--s3); border: var(--edge-thin); border-radius: var(--r-s); }

.display { font-family: var(--display); font-weight: 800; letter-spacing: -0.01em; }

.ui-icon { width: 1.15em; height: 1.15em; flex: none; display: inline-block; vertical-align: -0.2em; }

/* --- frame -------------------------------------------------------------------- */

.topbar {
  max-width: var(--max);
  margin: 0 auto;
  padding: var(--s3) var(--gutter) var(--s2);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2) var(--s4);
}
.brand {
  font: 900 var(--t20)/1 var(--display);
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
}
.brand:hover { color: var(--ink); }
.brand .mascot { width: 38px; height: 38px; flex: none; transition: transform 0.15s ease; }
@media (hover: hover) {
  .brand:hover .mascot { transform: rotate(-10deg) scale(1.06); }
}
.mascot { display: block; }

/* "Darecade", with Dare in red: one word, so no gap between the two halves. */
.wordmark { display: inline-flex; align-items: baseline; white-space: nowrap; letter-spacing: -0.02em; }
.wm-dare { color: var(--red); }

.topnav { display: flex; gap: var(--s1); flex-wrap: wrap; }
.topnav a {
  color: var(--ink);
  text-decoration: none;
  font: 700 var(--t16)/1 var(--display);
  padding: var(--s2) var(--s2);
  min-height: 40px; /* a comfortable tap on a phone */
  display: inline-flex;
  align-items: center;
  border-radius: 0;
}
.topnav a:hover { box-shadow: inset 0 -3px 0 var(--rule); color: var(--ink); }
.topnav a[aria-current="page"] { box-shadow: inset 0 -3px 0 var(--red); }
.nav-short { display: none; }
.topbar-cta {
  flex: none; color: var(--ink); text-decoration: none; font: 800 var(--t16)/1 var(--display);
  padding: var(--s2) var(--s4); min-height: 40px; display: inline-flex; align-items: center;
  border-radius: 999px; border: var(--edge-thin); background: var(--card); box-shadow: var(--lift-small);
}
.topbar-cta:hover { color: var(--ink); background: var(--gold); }
.topbar-cta[aria-current="page"] { background: var(--gold); }
/* Below 960px the full labels don't fit on one row, so the short ones show; one
   row of those needs 801px (measured in Montserrat). Narrower than that (phones,
   phones on their side, small tablets): brand and Play online share the first
   row, the games get the second — never a third row, never Play online alone
   (true from 310px up; measured every 2px from 300 to 830). */
@media (max-width: 959px) {
  .nav-long { display: none; }
  .nav-short { display: inline; }
}
@media (max-width: 819px) {
  .topbar-cta { order: 1; min-height: 36px; padding: var(--s1) var(--s3); font-size: var(--t14); }
  .topnav { order: 2; width: 100%; justify-content: center; }
}
@media (max-width: 520px) {
  .topnav { justify-content: space-between; gap: 0; }
  .topnav a { padding: var(--s1) 5px; font-size: var(--t14); }
}

main { max-width: var(--max); margin: 0 auto; padding: var(--s2) var(--gutter) var(--s6); }

.footer {
  max-width: var(--max);
  margin: 0 auto;
  padding: var(--s5) var(--gutter) var(--s6);
  border-top: 2px dashed var(--rule);
  color: var(--ink-soft);
  font-size: var(--t14);
}
.footer nav { display: flex; gap: var(--s1) var(--s4); flex-wrap: wrap; }
.footer a { color: var(--ink-soft); display: inline-block; padding: var(--s1) 0; } /* 24px+ tap targets */
.footer a:hover { color: var(--ink); }

/* --- buttons, chips ------------------------------------------------------------ */

/* Every button is a sticker: an ink edge and a hard shadow that it presses into. */
.btn {
  appearance: none;
  border: var(--edge);
  border-radius: var(--r);
  padding: 10px 20px;
  font: 800 var(--t16)/1.1 var(--display);
  color: #fff;
  background: var(--red);
  box-shadow: var(--lift);
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: 48px;
  text-align: center;
  transition: transform 0.08s ease, box-shadow 0.08s ease, background-color 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}
.btn:hover { color: #fff; }
@media (hover: hover) {
  .btn:hover:not(:disabled) { transform: translate(-1px, -1px); box-shadow: var(--lift-big); }
}
.btn:active:not(:disabled) { transform: translate(3px, 3px); box-shadow: 1px 1px 0 var(--ink); }
/* One "not yet" look for every button: flat paper, a dashed edge, readable text. */
.btn:disabled,
.btn[aria-disabled="true"] {
  background: var(--paper-deep);
  color: var(--ink-soft);
  border-style: dashed;
  border-color: var(--ink-soft);
  box-shadow: none;
  transform: none;
  cursor: not-allowed;
}
.btn-ghost { background: var(--card); color: var(--ink); }
.btn-ghost:hover { color: var(--ink); }
.btn-gold { background: var(--gold); color: var(--ink); }
.btn-gold:hover { color: var(--ink); }
.btn-small { min-height: 40px; padding: 6px var(--s3); font-size: var(--t14); border-width: 2px; border-radius: var(--r-s); box-shadow: var(--lift-small); }
.btn-big {
  font-weight: 900;
  /* A step smaller on phones, so labels like "Battle the computer" stay on one line. */
  font-size: var(--t20);
  padding: 14px var(--s5);
  min-height: 62px;
  min-width: 200px;
  border-radius: var(--r);
  box-shadow: var(--lift);
  text-wrap: balance;
}
@media (min-width: 480px) { .btn-big { font-size: var(--t24); padding: 14px var(--s6); } }
.btn-truth { background: var(--purple); }
.btn-dare { background: var(--red); }

.link-btn {
  background: none;
  border: 0;
  color: var(--purple);
  font: 700 var(--t16)/1.3 var(--display);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  cursor: pointer;
  padding: 6px 4px;
}
.link-btn:hover { color: var(--ink); }
.link-btn[data-armed] { color: var(--red-text); }

.chip {
  appearance: none;
  border: var(--edge-thin);
  background: var(--card);
  color: var(--ink);
  border-radius: 999px;
  padding: 6px var(--s3);
  font: 700 var(--t14)/1.2 var(--display);
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 40px;
  box-shadow: var(--lift-small);
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.chip:hover { color: var(--ink); background: #fffaf2; }
.chip[aria-pressed="true"] { background: var(--ink); color: #fff; box-shadow: none; transform: translate(2px, 2px); }
.chip:disabled { background: var(--paper-deep); color: var(--ink-soft); border-style: dashed; border-color: var(--ink-soft); box-shadow: none; transform: none; cursor: not-allowed; }
.chip[aria-pressed="true"]:disabled { background: var(--ink-soft); color: #fff; } /* still shows which is picked: 6.8:1 */
.chip-small { min-height: 36px; padding: 4px 12px; }
.chip-tag {
  font: 800 var(--t12)/1.3 var(--display);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: var(--red);
  color: #fff;
  border-radius: 999px;
  padding: 1px 7px;
}
.chip-row, .picker { display: flex; flex-wrap: wrap; gap: var(--s2); }
.picker { margin: var(--s3) 0; }
.picker-break { flex-basis: 100%; margin: var(--s2) 0 0; }

.tag {
  display: inline-block;
  font: 800 var(--t12)/1.3 var(--display);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 2px 8px;
  border-radius: 999px;
  border: var(--edge-thin);
  background: var(--card);
  color: var(--ink);
  margin-right: 6px;
}
.tag-bold { background: var(--red); color: #fff; }
.tag-mild { background: var(--sky); }
/* --- My dares panel (lib/my-dares.js) --- */
.my-dares > summary { cursor: pointer; list-style: none; display: flex; align-items: baseline; gap: var(--s2); min-height: 32px; }
.my-dares > summary::-webkit-details-marker { display: none; }
/* A drawn chevron: down when closed, up when open. */
.my-dares > summary::after, .chat-caret::before { content: ""; flex: none; width: 9px; height: 9px; margin: 0 4px 0 auto; border-right: 3px solid var(--ink); border-bottom: 3px solid var(--ink); transform: translateY(-3px) rotate(45deg); align-self: center; }
.my-dares[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.my-dares[open] > summary { margin-bottom: var(--s2); }
.my-dares-list { margin-top: var(--s2); max-height: 40vh; overflow-y: auto; overscroll-behavior: contain; }

/* Dares you typed (kept on this phone). Drawn by CSS so the dare's own text stays clean. */
.numbered li.is-own .dare-text::before {
  content: "Yours";
  display: inline-block;
  margin-right: 6px;
  padding: 0 7px;
  border-radius: 999px;
  font: 800 var(--t12)/1.3 var(--display);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  vertical-align: 0.1em;
  background: var(--gold);
  color: var(--ink);
}

.label { font: 800 var(--t12)/1.3 var(--display); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-soft); }
.my-dares > summary .label, .invite-code .label { white-space: nowrap; }

/* The one card. */
.panel {
  background: var(--card);
  border: var(--edge);
  border-radius: var(--r);
  padding: var(--s4);
  margin: var(--s4) 0;
  box-shadow: var(--lift);
}

/* --- home ------------------------------------------------------------------------ */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s2) var(--s3);
  padding: var(--s4) 0 var(--s1);
}
.hero-title { font-size: var(--t32); font-weight: 900; line-height: 1.05; margin: 0 0 var(--s2); letter-spacing: -0.02em; text-wrap: balance; }
.hero .lede { margin: 0; text-align: left; font-size: var(--t16); }
@media (min-width: 680px) { .hero .lede { font-size: var(--t18); } }
.hero-mascot { width: clamp(84px, 24vw, 140px); height: auto; transform: rotate(8deg); }
@media (prefers-reduced-motion: no-preference) {
  .hero-mascot { animation: mascot-hop 2.6s ease-in-out 0.4s 2; }
}
@keyframes mascot-hop {
  0%, 60%, 100% { transform: rotate(8deg) translateY(0); }
  70% { transform: rotate(-4deg) translateY(-10px); }
  80% { transform: rotate(10deg) translateY(0); }
}
.hero-actions { grid-column: 1 / -1; display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); margin: var(--s3) 0 0; }
.hero-actions .btn-big { min-width: 0; min-height: 56px; font-size: var(--t18); padding-left: var(--s3); padding-right: var(--s3); }
@media (min-width: 680px) {
  .hero-title { font-size: var(--t48); }
  .hero-actions { grid-template-columns: auto auto; justify-content: start; }
  .hero-actions .btn-big { min-width: 220px; font-size: var(--t20); }
}
.lede { font-size: var(--t18); color: var(--ink); max-width: 34em; margin-left: auto; margin-right: auto; text-wrap: balance; }
.eyebrow { color: var(--ink-soft); font: 800 var(--t14)/1.3 var(--display); letter-spacing: 0.06em; text-transform: uppercase; margin-bottom: 6px; }
.grid-label { margin: var(--s5) 0 var(--s2); }

/* Every game is a coloured box. */
.game-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); margin: 0 0 var(--s6); }
@media (min-width: 760px) { .game-grid { grid-template-columns: repeat(4, 1fr); gap: var(--s4); } }
.game-box {
  --box: var(--card);
  --box-ink: var(--ink);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: var(--s3);
  min-height: 120px;
  background: var(--box);
  color: var(--box-ink);
  border: var(--edge);
  border-radius: var(--r);
  box-shadow: var(--lift);
  text-decoration: none;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.game-box:hover { color: var(--box-ink); }
@media (hover: hover) {
  .game-box:hover { transform: translate(-2px, -2px) rotate(-1deg); box-shadow: var(--lift-big); }
}
.game-box:active { transform: translate(3px, 3px); box-shadow: 1px 1px 0 var(--ink); }
.game-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--card);
  border: var(--edge-thin);
  margin-bottom: 6px;
}
.game-icon svg { width: 32px; height: 32px; display: block; }
.game-box-title { font: 900 var(--t18)/1.15 var(--display); }
.game-box-text { font-size: var(--t14); line-height: 1.35; text-wrap: balance; }
.box-wheel { --box: var(--sky); }
.box-dice { --box: var(--red); --box-ink: #fff; }
.box-tod { --box: var(--purple); --box-ink: #fff; }
.box-imp { --box: var(--teal); }
.box-pairs { --box: var(--gold); }
.box-tower { --box: var(--orange); }
.box-ships { --box: var(--navy); --box-ink: #fff; }
.box-rooms { --box: var(--pink); }
.box-wyr { --box: var(--lime); }
.box-nhie { --box: var(--lilac); }

.how { margin: 0 0 var(--s6); }
.how-steps { list-style: none; counter-reset: step; padding: 0; margin: 0; display: grid; gap: var(--s3); }
@media (min-width: 760px) { .how-steps { grid-template-columns: repeat(3, 1fr); } }
.how-steps li { counter-increment: step; position: relative; padding: var(--s1) 0 0 52px; min-height: 40px; }
.how-steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  font: 900 var(--t20)/1 var(--display);
  background: var(--gold);
  border: var(--edge-thin);
  border-radius: 50%;
  box-shadow: var(--lift-small);
}
.library-teaser { margin-bottom: var(--s5); }

/* --- game pages --------------------------------------------------------------------- */

/* The page title is a sticker in the game's own colour. */
.game-head { text-align: center; padding: var(--s3) 0 var(--s1); }
.game-head h1 {
  display: inline-block;
  font-size: var(--t32);
  font-weight: 900;
  margin: 0 0 var(--s3);
  padding: 2px var(--s4) 4px;
  background: var(--game);
  color: var(--game-ink);
  border: var(--edge);
  border-radius: var(--r);
  box-shadow: var(--lift);
  transform: rotate(-1.5deg);
}
.game-head .lede { font-size: var(--t16); color: var(--ink-soft); }

.players { padding: var(--s3) var(--s4); }
/* Built by script: hold its place so the page doesn't jump when it arrives. */
/* (Measured. Dice, Pair Rush and Tower have a longer hint that takes two lines
   on a phone. The fleet's height leaves out the Start row below it, which the
   script moves in beside Shuffle.) */
.panel.players:empty { min-height: 103px; }
@media (max-width: 520px) { :is(.page-dice, .page-pairs, .page-tower) .panel.players:empty { min-height: 124px; } }
[data-placer]:empty { min-height: 409px; }
@media (max-width: 520px) { [data-placer]:empty { min-height: 406px; } }
@media (max-width: 360px) { [data-placer]:empty { min-height: 373px; } }
@media (min-width: 960px) { [data-placer]:empty { min-height: 466px; } }
.players-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); margin-bottom: var(--s2); }
.players-head .hint { color: var(--ink-soft); font-size: var(--t14); }
.player-chips { list-style: none; margin: 0 0 var(--s2); padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.chip.player { cursor: default; padding-right: var(--s1); }
.chip.player.is-turn { background: var(--gold); }
.chip-x {
  border: 0;
  background: transparent;
  color: var(--ink);
  font: 800 var(--t18)/1 var(--body);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  cursor: pointer;
  display: inline-grid;
  place-items: center;
  padding: 0;
}
.chip-x .ui-icon { width: 16px; height: 16px; vertical-align: 0; }
.chip-x:hover { background: var(--red-wash); color: var(--red-text); }

.player-add, .add-form { display: flex; gap: var(--s2); }
.player-add input, .add-form input {
  flex: 1;
  min-width: 0;
  background: var(--card);
  border: var(--edge-thin);
  color: var(--ink);
  border-radius: var(--r-s);
  padding: 10px 12px;
  font: 16px var(--body); /* 16px stops iOS zooming on focus */
}
/* Focus: the site's purple ring (5.5:1 on paper), the border turns purple too. */
.player-add input:focus-visible, .add-form input:focus-visible { border-color: var(--purple); outline: 3px solid var(--purple); outline-offset: 2px; }
.player-add input:disabled, .add-form input:disabled, .text-input:disabled, .select:disabled { background: var(--paper-deep); color: var(--ink-soft); border-style: dashed; border-color: var(--ink-soft); cursor: not-allowed; }
::placeholder { color: var(--ink-soft); opacity: 1; } /* 6.8:1 on white */
/* Form messages are almost always "that didn't work": red words, never a headline. */
.form-msg { color: var(--red-text); font-weight: 700; font-size: var(--t14); margin: 6px 0 0; min-height: 1em; }
.form-msg.is-ok { color: var(--green); }
.form-msg.is-note { color: var(--ink); font-weight: 400; overflow-wrap: anywhere; }
.invite-error { text-align: center; font-size: var(--t16); margin: 0 auto var(--s3); max-width: 30em; text-wrap: balance; } /* under the centred title it explains */
.form-msg:empty { display: none; }

/* Whose turn it is: one style for every game. */
.turn-banner,
.room-tod .tod-turn,
.challenge-title {
  text-align: center;
  font: 900 var(--t24)/1.2 var(--display);
  color: var(--ink);
  margin: var(--s3) 0 var(--s1);
  letter-spacing: -0.01em;
  text-wrap: balance;
}
@media (min-width: 720px) {
  .turn-banner, .room-tod .tod-turn, .challenge-title { font-size: var(--t32); }
}

.spin-row { display: flex; justify-content: center; gap: var(--s3); flex-wrap: wrap; margin: var(--s4) 0; }

.tools { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); justify-content: center; align-items: center; margin: var(--s2) 0 var(--s1); }
.tool-group { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; justify-content: center; }
.switch { display: inline-flex; align-items: center; gap: var(--s2); font-weight: 700; cursor: pointer; }
.switch input { width: 20px; height: 20px; accent-color: var(--red); }

.numbered { list-style: none; margin: 0 0 var(--s3); padding: 0; }
.numbered li {
  display: grid;
  grid-template-columns: 30px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: var(--s2) 0;
  border-bottom: 2px dashed var(--rule);
}
.numbered li:last-child { border-bottom: 0; }
.numbered .num {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font: 800 var(--t14)/1 var(--display);
  background: var(--card);
  border: var(--edge-thin);
}
.numbered li.is-played .dare-text, .numbered li.is-done .dare-text { text-decoration: line-through; color: var(--ink-soft); }
.numbered li.is-played .num, .numbered li.is-done .num { opacity: 0.45; }
.numbered li.is-rolled { background: #fff3d1; border-radius: var(--r-s); padding-left: 6px; padding-right: 6px; }
.numbered li.is-rolled .num { background: var(--gold); }
.icon-btn {
  border: 0;
  background: transparent;
  color: var(--ink);
  font: 800 var(--t18)/1 var(--body);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  cursor: pointer;
  display: inline-grid;
  place-items: center;
  padding: 0;
}
.icon-btn .ui-icon { width: 18px; height: 18px; vertical-align: 0; }
.icon-btn:hover { background: var(--red-wash); color: var(--red-text); }
.icon-btn:disabled, .chip-x:disabled { color: var(--ink-soft); background: transparent; opacity: 0.6; cursor: not-allowed; }

/* --- the dare card (shared) ------------------------------------------------------------ */

/* The accent card: a playing card dealt onto the table. */
.result-card {
  background: var(--card);
  border: var(--edge);
  border-radius: var(--r-l);
  padding: var(--s5) var(--s4) var(--s4);
  text-align: center;
  box-shadow: var(--lift-big);
  transform: rotate(-1deg);
  animation: deal-in 0.32s cubic-bezier(0.2, 1.4, 0.4, 1);
}
.result-who { color: var(--red-text); font: 800 var(--t18)/1.25 var(--display); margin: 0 0 var(--s1); overflow-wrap: anywhere; } /* whose dare it is, readable across a table */
.result-num { font: 800 var(--t14)/1 var(--display); color: var(--ink-soft); margin: 0; }
/* The dare itself: big enough to read from across a table. */
.result-text { font: 700 var(--t24)/1.3 var(--display); margin: var(--s2) 0 var(--s4); overflow-wrap: anywhere; }
@media (min-width: 720px) { .result-text { font-size: var(--t32); } }
.result-actions { display: flex; gap: var(--s3); justify-content: center; flex-wrap: wrap; }
.result-actions .btn { min-width: 120px; }

@keyframes deal-in {
  from { transform: translateY(18px) rotate(-6deg) scale(0.9); opacity: 0; }
  to { transform: rotate(-1deg); opacity: 1; }
}
@keyframes pop-in {
  from { transform: scale(0.85); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}
/* Truth or Dare turns the card over: the back first, then the face. */
.card-back {
  display: grid;
  place-items: center;
  min-height: 254px; /* a dealt card's usual height (198–282px measured on a phone) */
  border: var(--edge);
  border-radius: var(--r-l);
  box-shadow: var(--lift-big);
  background:
    radial-gradient(circle, rgba(255, 255, 255, 0.22) 2px, transparent 2.6px) 0 0 / 16px 16px,
    var(--card-back, var(--purple));
  transform: rotate(-1deg);
}
.card-back .mascot { width: 72px; height: 72px; }
.card-back.is-dare { --card-back: var(--red); }
@media (prefers-reduced-motion: no-preference) {
  .card-back { animation: deal-in 0.24s cubic-bezier(0.2, 1.4, 0.4, 1); }
  .card-back.is-turning { animation: turn-away 0.2s ease-in forwards; }
  .result-card.is-turned { animation: turn-up 0.26s cubic-bezier(0.2, 1.3, 0.4, 1); }
}
@keyframes turn-away { to { transform: rotate(-1deg) rotateY(90deg); } }
@keyframes turn-up {
  from { transform: rotate(-1deg) rotateY(-90deg); }
  to { transform: rotate(-1deg) rotateY(0); }
}

/* --- wheel ------------------------------------------------------------------------------ */

.wheel-stage { position: relative; width: min(100%, 440px); margin: var(--s2) auto 0; }
.wheel { display: block; width: 100%; height: auto; overflow: visible; filter: drop-shadow(5px 5px 0 var(--ink)); }
.wheel-rim { fill: var(--ink); }
.slice path { stroke: var(--ink); stroke-width: 1.5; }
.slice text { font: 800 15px var(--display); pointer-events: none; }
.slice.is-played path { fill: #e7dccb; }
.slice.is-played text { fill: #6f6787; }
/* The winning slice: the wheel holds on it for a beat before the card covers it. */
.slice.is-winner path { stroke: #fff; stroke-width: 5; stroke-linejoin: round; }
/* The rest stay as they are: dimming them over the ink rim turned the wheel muddy. */
@media (prefers-reduced-motion: no-preference) {
  .slice.is-winner { animation: winner-pulse 0.7s ease-in-out; transform-box: fill-box; transform-origin: center; }
}
@keyframes winner-pulse {
  0%, 100% { transform: scale(1); }
  40% { transform: scale(1.06); }
}
.peg { fill: #fff; }
.wheel-hub { fill: var(--card); stroke: var(--ink); stroke-width: 3; }
.wheel-hub-mark { fill: var(--red); }
.wheel-pointer { fill: var(--red); stroke: var(--ink); stroke-width: 3; stroke-linejoin: round; }

.wheel-stage .result {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 6%;
  background: radial-gradient(circle, rgba(255, 246, 233, 0.55), rgba(255, 246, 233, 0) 72%);
  border-radius: 50%;
}
.wheel-stage .result-card { width: 100%; max-width: 360px; }
.wheel-stage .result-text { font-size: var(--t20); }
@media (max-width: 400px) {
  /* Done and Skip share a row, so the card doesn't spill over Spin. */
  .result-actions .btn { min-width: 0; flex: 1 1 0; }
  .wheel-stage .result-card { padding: var(--s4) var(--s3) var(--s3); }
  .wheel-stage .result-text { font-size: var(--t18); margin-bottom: var(--s3); }
}

.dare-list h2 { font-size: var(--t18); }

/* --- dice ------------------------------------------------------------------------------ */

.pick-grid { display: grid; gap: var(--s3); grid-template-columns: 1fr; margin: var(--s3) 0; }
.pick-heading { margin: var(--s4) 0 0; }
.bs-best:empty { display: none; }
.setup-msg, .bs-best { text-align: center; margin: var(--s1) 0 var(--s2); }
.setup-msg { min-height: 1.55em; } /* filled by script on load: its line is kept free */
.bs-start-row:empty { display: none; } /* the button moves under the sea, beside Shuffle (battleships.js) */
.bs-place-row { gap: 10px 14px; align-items: center; flex-wrap: wrap; }
/* Playing (the setup is put away): the page heading shrinks and its intro goes,
   so the game sits higher. Imposter has no single play view, hence [data-setup]. */
.game:has(> [data-setup][hidden]) .game-head .lede { display: none; }
.game:has(> [data-setup][hidden]) .game-head h1 { font-size: var(--t24); box-shadow: var(--lift-small); border-width: 2px; margin-bottom: var(--s1); }
/* In a room the room bar says where you are; the "Play online" heading would only push the game down. */
[data-room].in-room > .game-head { display: none; }
@media (min-width: 680px) { .pick-grid { grid-template-columns: 1fr 1fr; } }
.pick-card {
  appearance: none;
  text-align: left;
  border: var(--edge);
  background: var(--card);
  color: var(--ink);
  border-radius: var(--r);
  padding: var(--s3) var(--s4);
  cursor: pointer;
  font: inherit;
  display: grid;
  gap: var(--s1);
  box-shadow: var(--lift);
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.pick-card[aria-pressed="true"] { background: var(--gold); transform: translate(2px, 2px); box-shadow: var(--lift-small); }
.pick-card-title { font: 900 var(--t18)/1.2 var(--display); }
.pick-card-text { color: var(--ink); font-size: var(--t14); }
.pick-card-rounds { color: var(--ink-soft); font-size: var(--t14); font-weight: 700; }
.pick-card[aria-pressed="true"] .pick-card-rounds { color: var(--ink); }

.round-head { margin: var(--s2) 0 0; }
.round-label { text-align: center; font: 800 var(--t16)/1.3 var(--display); margin-bottom: var(--s2); }
.bar { height: 14px; background: var(--card); border: var(--edge-thin); border-radius: 99px; overflow: hidden; }
.bar span { display: block; height: 100%; width: 0; background: var(--game, var(--red)); border-right: var(--edge-thin); transition: width 0.4s ease; }

.dice-stage { display: grid; place-items: center; gap: var(--s4); margin: var(--s3) 0; }
.dice-stage .result { width: 100%; max-width: 460px; }
.die {
  width: 120px;
  height: 120px;
  border-radius: var(--r-l);
  background: var(--card);
  border: 4px solid var(--ink);
  box-shadow: var(--lift-big);
  display: grid;
  grid-template: repeat(3, 1fr) / repeat(3, 1fr);
  padding: 13px;
  gap: 4px;
}
.die i { width: 20px; height: 20px; border-radius: 50%; background: var(--ink); place-self: center; opacity: 0; }
.die[data-face="1"] i:nth-child(5),
.die[data-face="2"] i:is(:nth-child(1), :nth-child(9)),
.die[data-face="3"] i:is(:nth-child(1), :nth-child(5), :nth-child(9)),
.die[data-face="4"] i:is(:nth-child(1), :nth-child(3), :nth-child(7), :nth-child(9)),
.die[data-face="5"] i:is(:nth-child(1), :nth-child(3), :nth-child(5), :nth-child(7), :nth-child(9)),
.die[data-face="6"] i:is(:nth-child(1), :nth-child(3), :nth-child(4), :nth-child(6), :nth-child(7), :nth-child(9)) { opacity: 1; }
.die[data-face="1"] i:nth-child(5) { background: var(--red); width: 26px; height: 26px; }
.die.is-rolling { animation: shake 0.12s linear infinite; }
.die.is-landed { animation: land 0.35s cubic-bezier(0.2, 1.6, 0.4, 1); }

@keyframes shake {
  0% { transform: rotate(-8deg) translateY(-2px); }
  50% { transform: rotate(8deg) translateY(2px); }
  100% { transform: rotate(-8deg) translateY(-2px); }
}
@keyframes land {
  from { transform: scale(1.18) rotate(6deg); }
  to { transform: scale(1) rotate(0); }
}

/* End screens: one layout for every game, on the paper itself (the dare card is the card). */
.end-panel { text-align: center; }
.panel.end-panel, .panel.handoff { background: transparent; border: 0; box-shadow: none; padding-left: 0; padding-right: 0; }
.end-panel h2 { font: 900 var(--t32)/1.15 var(--display); color: var(--ink); text-wrap: balance; }
.end-mascot { width: 72px; height: 72px; margin: 0 auto var(--s2); }
.scoreboard { width: 100%; max-width: 420px; margin: var(--s3) auto var(--s4); border-collapse: collapse; }
.scoreboard th, .scoreboard td { padding: var(--s2) 10px; border-bottom: 2px dashed var(--rule); text-align: left; }
.scoreboard th { color: var(--ink-soft); font: 800 var(--t12)/1.3 var(--display); text-transform: uppercase; letter-spacing: 0.06em; }
.scoreboard td + td, .scoreboard th + th { text-align: center; }
/* The leader gets a trophy (the crown means the room's host). */
.scoreboard tr.lead td { font-weight: 800; }
.scoreboard tr.lead td:first-child::before {
  content: "";
  display: inline-block;
  width: 1.1em;
  height: 1.1em;
  margin-right: 6px;
  vertical-align: -0.18em;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23231b3a' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 4h10v5a5 5 0 0 1-10 0Z' fill='%23ffc233'/%3E%3Cpath d='M7 6H4v1a3.5 3.5 0 0 0 3.5 3.5M17 6h3v1a3.5 3.5 0 0 1-3.5 3.5M12 14v3.5M8 20.5h8'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* --- truth or dare -------------------------------------------------------------------- */

/* Tall enough for nearly every card, so Sound / End game below don't jump as one turns over. */
.tod-stage { display: grid; place-items: center; gap: var(--s3); margin: var(--s3) 0 var(--s4); min-height: 300px; }
.tod-choose { display: flex; flex-wrap: wrap; gap: var(--s3); justify-content: center; align-items: center; }
.tod-choose .btn-big { min-width: 150px; }
.tod-choose .link-btn { flex-basis: 100%; }
.tod-stage .result { width: 100%; max-width: 460px; perspective: 900px; }
.tod-kind {
  display: inline-block;
  font: 900 var(--t14)/1.2 var(--display);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #fff;
  background: var(--red);
  border: var(--edge-thin);
  border-radius: 999px;
  padding: 3px 14px;
  margin: 0 0 var(--s2);
}
.tod-card.is-truth .tod-kind { background: var(--purple); }

/* --- library + prose ----------------------------------------------------------------- */

.page-head { padding: var(--s4) 0 var(--s1); }
.page-head h1 { font-size: var(--t32); font-weight: 900; }
.page-head .lede { margin-left: 0; }
.page-404-mascot { width: 88px; height: 88px; margin: var(--s4) 0 var(--s3); transform: rotate(-8deg); }
.meta { color: var(--ink-soft); }
.cta-row { display: flex; flex-wrap: wrap; gap: var(--s3); margin: var(--s3) 0 var(--s2); }
.crumbs { color: var(--ink-soft); font-size: var(--t14); padding-top: var(--s3); }

.lib-grid { display: grid; gap: var(--s3); grid-template-columns: 1fr; margin-bottom: var(--s5); }
@media (min-width: 640px) { .lib-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px) { .lib-grid { grid-template-columns: 1fr 1fr 1fr; } }
.lib-card {
  display: grid;
  align-content: start; /* titles line up across a row whatever the description's length */
  gap: var(--s1);
  padding: var(--s3) var(--s4);
  background: var(--card);
  border: var(--edge);
  border-radius: var(--r);
  box-shadow: var(--lift);
  color: var(--ink);
  text-decoration: none;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.lib-card:hover { color: var(--ink); }
@media (hover: hover) {
  .lib-card:hover { transform: translate(-2px, -2px); box-shadow: var(--lift-big); }
}
.lib-card-title { font: 900 var(--t18)/1.2 var(--display); }
.lib-card-text { color: var(--ink-soft); font-size: var(--t14); }
.lib-card-count { color: var(--ink); font-size: var(--t14); font-weight: 700; }

.library-list { margin: 0; padding-left: 1.8em; }
.library-list li { padding: 6px 0; border-bottom: 2px dashed var(--rule); }
.library-list li:last-child { border-bottom: 0; }
.library-list li::marker { color: var(--red-text); font-weight: 800; font-family: var(--display); }

/* The truth or dare questions page: one long, readable page with jump links. */
.page-questions main { max-width: 860px; }
.toc ul { margin: 0; }
.toc li { margin-bottom: 6px; }
.section-title { font: 900 var(--t32)/1.15 var(--display); margin: var(--s6) 0 var(--s2); scroll-margin-top: var(--s4); }
.pack-section { scroll-margin-top: var(--s4); }
.pack-title { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); font-size: var(--t24); margin-bottom: var(--s1); }
.round-title { font-size: var(--t18); margin: var(--s4) 0 var(--s2); }
.pack-section .cta-row { margin-bottom: 0; }

/* Guides: one readable column, the art drawn from the site's own pieces. */
.guide-grid { display: grid; grid-template-columns: 1fr; gap: var(--s4); margin: var(--s3) 0 var(--s6); }
@media (min-width: 640px) { .guide-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 960px) { .guide-grid { grid-template-columns: 1fr 1fr 1fr; } }
.guide-card {
  display: grid; align-content: start; gap: var(--s2); padding: var(--s3); color: var(--ink); text-decoration: none;
  background: var(--card); border: var(--edge); border-radius: var(--r); box-shadow: var(--lift);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.guide-card:hover { color: var(--ink); }
@media (hover: hover) { .guide-card:hover { transform: translate(-2px, -2px); box-shadow: var(--lift-big); } }
.guide-card-title { font: 900 var(--t18)/1.2 var(--display); }
.guide-card-text { color: var(--ink-soft); font-size: var(--t14); }
/* The art box takes the guide's first game's colour from its .box-<kind> class. */
.guide-art {
  position: relative; height: 160px; margin: var(--s2) 0 var(--s4); overflow: hidden;
  background: radial-gradient(rgba(255, 255, 255, 0.25) 2px, transparent 2.6px) 0 0 / 18px 18px, var(--box, var(--gold));
  border: var(--edge); border-radius: var(--r-l); box-shadow: var(--lift);
}
.guide-art-small { height: 96px; margin: 0; border-radius: var(--r); box-shadow: none; border-width: 2px; }
.guide-art-mascot { position: absolute; left: 50%; top: 50%; width: 92px; height: 92px; transform: translate(-50%, -50%) rotate(-8deg); }
.guide-art-small .guide-art-mascot { width: 56px; height: 56px; }
.guide-art-icon { position: absolute; display: grid; place-items: center; width: 60px; height: 60px; border-radius: 50%; background: var(--card); border: var(--edge-thin); box-shadow: var(--lift-small); }
.guide-art-icon svg { width: 40px; height: 40px; }
.guide-art-icon-1 { left: 9%; top: 18%; transform: rotate(-10deg); }
.guide-art-icon-2 { right: 9%; top: 10%; transform: rotate(9deg); }
/* Anchored to the mascot, not the edge: at phone width 22% from the right sat on top of it. */
.guide-art-icon-3 { left: calc(50% + 58px); bottom: 6%; transform: rotate(-6deg); }
.guide-art-small .guide-art-icon { width: 38px; height: 38px; }
.guide-art-small .guide-art-icon svg { width: 26px; height: 26px; }
.guide-art-small .guide-art-icon-3 { display: none; }
/* Small phones: at 9% from the edges the side icons met the mascot. Here, after the
   base rules, so it wins; the card-sized art keeps its own sizes (more specific). */
@media (max-width: 374px) {
  .guide-art-mascot { width: 72px; height: 72px; }
  .guide-art-icon { width: 50px; height: 50px; }
  .guide-art-icon svg { width: 34px; height: 34px; }
  .guide-art-icon-1 { left: 6%; }
  .guide-art-icon-2 { right: 6%; }
  .guide-art-icon-3 { left: calc(50% + 46px); }
}
.guide { max-width: 720px; margin: 0 auto; }
.guide-title { font-size: var(--t32); font-weight: 900; margin-bottom: var(--s2); }
@media (min-width: 720px) { .guide-title { font-size: var(--t48); } }
.guide-lede { margin-left: 0; font-size: var(--t18); color: var(--ink-soft); }
.guide-body { font-size: var(--t18); line-height: 1.65; }
.guide .guide-body h2 { font-size: var(--t24); margin-top: var(--s6); }
.guide .guide-body h3 { font-size: var(--t20); margin-top: var(--s5); }
.guide-body li { margin-bottom: var(--s2); }
.guide-tip { background: #fff3d1; border: var(--edge-thin); border-radius: var(--r); padding: var(--s3) var(--s4); }
.guide-tip strong { font-family: var(--display); font-weight: 900; text-transform: uppercase; letter-spacing: 0.06em; margin-right: 6px; }
.guide-play { max-width: 340px; margin: var(--s4) 0 var(--s5); }
.guide-play .game-box { min-height: 0; }
.guide-games { margin: var(--s7) 0 var(--s4); }
.guide-games .game-grid { margin-bottom: 0; }
@media (min-width: 760px) { .guide-games .game-grid { grid-template-columns: repeat(3, 1fr); } }
.guide-more { margin-top: var(--s6); }

.prose { max-width: 42em; }
.prose h1 { font-size: var(--t32); font-weight: 900; margin-top: var(--s3); }
/* Wider screens: the big headings take the next step up. */
@media (min-width: 720px) {
  .game-head h1, .page-head h1, .prose h1, .handoff-name, .imp-role-word, .stamp { font-size: var(--t48); }
}
.prose h2 { margin-top: 1.6em; font-size: var(--t20); }
.prose li { margin-bottom: 6px; }

/* --- confetti ------------------------------------------------------------------------- */

.confetti { position: fixed; inset: 0; pointer-events: none; z-index: 50; }
.confetti i {
  position: fixed;
  width: 10px;
  height: 14px;
  border-radius: 2px;
  border: 1.5px solid var(--ink);
  animation: confetti 1.1s cubic-bezier(0.15, 0.7, 0.35, 1) forwards;
}
@keyframes confetti {
  from { transform: translate(-50%, -50%) rotate(0); opacity: 1; }
  to { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy) + 120px)) rotate(var(--rot)); opacity: 0; }
}

/* A rubber stamp for the big result moments (Imposter's "Caught!"). */
.stamp {
  display: inline-block;
  font: 900 var(--t32)/1 var(--display);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: var(--s2) var(--s4);
  border: 4px solid currentColor;
  border-radius: var(--r);
  color: var(--red-text);
  background: var(--card);
  transform: rotate(-6deg);
  margin: var(--s2) 0 var(--s4);
}
.stamp.is-good { color: var(--green); }
/* The stamp lands from above, scaled up: clipped to its own strip so the
   oversized first frames can't widen a phone's page (Chrome widens the layout
   to fit them, which pushed the room's chat bar off screen). */
.stamp-wrap { display: block; overflow: hidden; overflow: clip; padding: var(--s3) 0; }
@media (prefers-reduced-motion: no-preference) {
  .stamp { animation: stamp-in 0.45s cubic-bezier(0.2, 1.5, 0.4, 1); }
}
@keyframes stamp-in {
  0% { transform: rotate(-16deg) scale(1.7); opacity: 0; }
  60% { transform: rotate(-4deg) scale(0.94); opacity: 1; }
  100% { transform: rotate(-6deg) scale(1); }
}

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

/* Small phones: keep the wheel and its Spin button on the first screen. */
@media (max-width: 520px) {
  .topbar { padding-top: 10px; }
  .game-head { padding-top: var(--s1); }
  .game-head h1 { font-size: var(--t32); }
  .game-head .lede { font-size: var(--t14); margin-bottom: 6px; }
}
@media (max-height: 640px) {
  .game-head .lede { display: none; }
  .wheel-stage { width: min(100%, 300px); }
  .btn-big { min-height: 56px; padding: 12px 36px; }
}
/* A phone on its side: only ~375px of height, so the wheel goes on the left and
   the heading, Spin and the tools stack beside it. Other games put their title
   away while playing and size the board to the height. */
@media (max-height: 500px) and (orientation: landscape) {
  .game-head { padding-top: 2px; }
  .game-head h1 { font-size: var(--t24); margin-bottom: var(--s2); box-shadow: var(--lift-small); border-width: 2px; }
  [data-wheel] { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 20px; align-items: start; }
  [data-wheel] > .game-main { display: contents; }
  [data-wheel] > *, [data-wheel] > .game-main > * { grid-column: 2; }
  [data-wheel] > .game-main > .wheel-stage { grid-column: 1; grid-row: 1 / span 4; width: min(42vw, calc(100vh - 120px)); margin: 0; }
  /* The dare card covers the wheel, so it has to fit the wheel's height. */
  [data-wheel] .result-card { padding: 10px 12px; border-radius: var(--r); }
  [data-wheel] .result-text { font-size: var(--t16); margin: 2px 0 8px; }
  [data-wheel] .result-who { font-size: var(--t14); }
  [data-wheel] .result-num { display: none; }
  [data-wheel] .result-actions .btn { min-width: 0; min-height: 40px; padding: 6px 16px; }
}

/* Desktop: the game on the left, what you set up on the right — not one long
   phone column stretched to 1000px. */
@media (min-width: 960px) {
  [data-wheel] { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 400px); column-gap: var(--s6); align-items: start; }
  [data-wheel] > .game-head, [data-wheel] > noscript { grid-column: 1 / -1; }
  [data-wheel] > .game-main { grid-column: 1; position: sticky; top: var(--s4); }
  [data-wheel] > .game-side { grid-column: 2; }
  [data-wheel] > .game-side > .panel:first-child { margin-top: 0; }
  .game > [data-setup] { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s6); align-items: start; }
  .game > [data-setup] .setup-side > :first-child { margin-top: var(--s4); }
  .page-dice .game > [data-setup] .setup-side > :first-child { margin-top: var(--s5); }
  .page-dice .pick-grid { grid-template-columns: 1fr; }
  .page-dice [data-play], .page-tod [data-play], .page-imposter .game > div:not([data-setup]), .page-pairs [data-play], .page-pairs [data-end] { max-width: 760px; margin-left: auto; margin-right: auto; }
}
/* The online landing is a short form: a column, not a 1000px-wide name box. */
.page-room [data-landing], .page-room [data-ended], .page-room .room-status { max-width: 620px; margin-left: auto; margin-right: auto; }

/* --- pair rush --------------------------------------------------------------------- */

.tool-left { justify-content: flex-start; }
.tight { margin: 6px 0 0; padding-left: 1.2em; }
.tight li { margin-bottom: var(--s1); }
.select {
  width: 100%;
  margin-top: var(--s2);
  background: var(--card);
  color: var(--ink);
  border: var(--edge-thin);
  border-radius: var(--r-s);
  padding: 10px 12px;
  font: 16px var(--body);
}
.select:focus-visible { border-color: var(--purple); outline: 3px solid var(--purple); outline-offset: 2px; }

.handoff { text-align: center; padding: var(--s6) var(--s4); }
.handoff-name {
  display: inline-block;
  font: 900 var(--t32)/1.1 var(--display);
  color: var(--game-ink);
  background: var(--game);
  border: var(--edge);
  border-radius: var(--r);
  box-shadow: var(--lift);
  padding: var(--s1) var(--s4);
  margin: var(--s1) 0 var(--s5);
  transform: rotate(-2deg);
  overflow-wrap: anywhere;
}
.handoff .lede { color: var(--ink); }

.pr-hud { display: grid; grid-template-columns: 1fr auto 1fr; align-items: end; gap: var(--s2); max-width: 440px; margin: 6px auto 10px; }
.pr-stat { display: grid; position: relative; }
.pr-stat:last-child { text-align: right; grid-column: 3; } /* stays right when the name between is hidden (solo) */
.pr-num { font: 900 var(--t32)/1 var(--display); }
.pr-clock.is-urgent { color: var(--red-text); animation: pulse 0.5s ease-in-out infinite alternate; }
.pr-who { margin: 0; font: 900 var(--t18)/1.2 var(--display); color: var(--ink); text-align: center; align-self: center; }
.pr-pop { position: absolute; left: 56px; bottom: var(--s1); font: 900 var(--t20)/1 var(--display); color: var(--green); opacity: 0; white-space: nowrap; }
.pr-pop.is-on { animation: float-up 0.9s ease-out; }

.pr-stage { position: relative; width: min(100%, 440px); margin: 0 auto; }
.pr-board { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); }
.pr-card {
  appearance: none;
  border: 0;
  padding: 0;
  background: none;
  aspect-ratio: 1;
  perspective: 600px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.pr-card:disabled { cursor: default; }
.pr-inner {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.22s ease;
}
.pr-card.is-up .pr-inner { transform: rotateY(180deg); }
.pr-back, .pr-front {
  position: absolute;
  inset: 0;
  border-radius: var(--r-s);
  border: var(--edge);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  display: grid;
  place-items: center;
}
.pr-back {
  background:
    radial-gradient(circle, rgba(255, 255, 255, 0.25) 2px, transparent 2.6px) 0 0 / 12px 12px,
    var(--purple);
  box-shadow: var(--lift-small);
}
.pr-back::after { content: ""; width: 34%; aspect-ratio: 1; border-radius: 28%; background: var(--red); border: var(--edge-thin); }
.pr-front {
  transform: rotateY(180deg);
  /* A disabled button draws its text at 30% alpha, emoji included; matched
     cards are disabled but must stay bright. */
  color: var(--ink);
  background: var(--card);
  font-size: var(--t32);
  box-shadow: var(--lift-small);
}
@media (min-width: 720px) { .pr-front { font-size: var(--t48); } }
.pr-card.is-matched .pr-front { background: var(--mint); box-shadow: 0 0 0 3px var(--teal), var(--lift-small); }
/* Shake the button, not the face: the face's own transform is what flips it. */
.pr-card.is-miss { animation: shake 0.12s linear 3; }
.pr-card.is-miss .pr-front { background: var(--red-wash); }
.pr-card.is-dealt { animation: pop-in 0.25s cubic-bezier(0.2, 1.4, 0.4, 1) backwards; }

.pr-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font: 900 var(--t72)/1 var(--display);
  color: var(--gold);
  -webkit-text-stroke: 3px var(--ink);
  paint-order: stroke fill;
  text-shadow: 5px 5px 0 var(--ink);
  background: rgba(255, 246, 233, 0.6);
  border-radius: var(--r);
  pointer-events: none;
}
.big-score { font: 900 var(--t72)/1 var(--display); margin: var(--s2) 0; color: var(--ink); }
.big-score-unit { font-size: var(--t24); color: var(--ink-soft); }
.pr-dare { max-width: 460px; margin: 0 auto var(--s4); }

@keyframes float-up {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-26px); }
}
@keyframes pulse {
  from { transform: scale(1); }
  to { transform: scale(1.08); }
}
/* Small phones: brand + Play online still share one row (it needs 366px at the
   normal sizes, so they shrink a step below 375px). */
@media (max-width: 374px) {
  .topbar { column-gap: var(--s2); }
  .brand { font-size: var(--t16); gap: 6px; }
  .brand .mascot { width: 30px; height: 30px; }
  .topbar-cta { padding: var(--s1) 10px; }
}
@media (max-width: 360px) {
  .topnav { gap: 0; }
  .topnav a { padding: var(--s1) 3px; font-size: var(--t12); }
}

/* --- dare tower ------------------------------------------------------------------- */

.label-gap { display: block; margin-top: var(--s3); }
/* The tower stays a night-time table: a dark window in the page. */
.tw-stage {
  position: relative;
  height: 66vh;
  height: 66svh;
  min-height: 380px;
  max-height: 680px;
  margin: var(--s2) calc(-1 * var(--gutter)) 0;
  border-radius: 0;
  overflow: hidden;
  background: #0a0814;
}
@media (min-width: 720px) {
  .tw-stage { margin: var(--s2) 0 0; border-radius: var(--r-l); border: var(--edge); box-shadow: var(--lift-big); }
}
.tw-canvas { display: block; width: 100%; height: 100%; touch-action: none; cursor: grab; }
.tw-top { position: absolute; top: 10px; left: 12px; right: 12px; text-align: center; pointer-events: none; }
.tw-turn { display: inline-block; margin: 0; padding: 2px var(--s3); font-size: var(--t20); background: var(--card); color: var(--ink); border: var(--edge-thin); border-radius: var(--r-s); box-shadow: var(--lift-small); }
.tw-turn:empty { display: none; }
.tw-coach { margin: 6px auto 0; color: #fff; font: 700 var(--t14)/1.35 var(--display); text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9); min-height: 1.4em; }
.tw-coach.is-warn { color: var(--gold); }
.tw-coach.is-danger { color: #ff8a98; }
.tw-meter { position: absolute; left: 12px; bottom: 14px; display: grid; gap: var(--s1); pointer-events: none; }
.tw-meter .label { color: #e9e2fb; }
@media (max-width: 360px) { .tw-coach { font-size: var(--t12); } }
.tw-bar { display: block; width: 96px; height: 10px; border-radius: 99px; background: rgba(255, 255, 255, 0.15); border: 1.5px solid rgba(255, 255, 255, 0.5); overflow: hidden; }
.tw-bar span { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--teal), var(--gold), var(--red)); transition: width 0.4s ease; }
.tw-meter.is-hot .label { color: #ff8a98; }
@media (prefers-reduced-motion: no-preference) {
  .tw-meter.is-hot .tw-bar { animation: shake 0.24s linear infinite; }
}
/* Bottom-right, clear of the tower's base where most picks happen. */
.tw-bottom { position: absolute; right: 12px; bottom: 12px; display: flex; pointer-events: none; }
.tw-bottom .btn { pointer-events: auto; min-width: 0; padding: 10px 26px; min-height: 54px; font-size: var(--t20); }
/* Small phones: the tower fills the width, so the Pull button gets its own row
   underneath instead of covering the lower blocks. */
@media (max-width: 400px) {
  .tw-stage { display: flex; flex-direction: column; }
  .tw-canvas { flex: 1; min-height: 0; height: auto; }
  .tw-bottom { position: static; justify-content: flex-end; padding: var(--s2) var(--s3); min-height: 70px; box-sizing: border-box; } /* same height with or without the button, so the tower never jumps */
  .tw-meter { bottom: 20px; }
}
.tw-result { position: absolute; inset: 0; display: grid; place-items: center; padding: var(--s4); background: rgba(10, 8, 20, 0.55); overflow-y: auto; } /* a long dare on a short screen scrolls inside the tower, never off the page */
.tw-result .result-card { width: 100%; max-width: 380px; }
.tw-result .result-text { font-size: var(--t20); }

/* --- Imposter (one phone and rooms) ------------------------------------------------- */

.imp-role { border: var(--edge); border-radius: var(--r-l); padding: var(--s4); margin: 6px auto var(--s3); max-width: 420px; background: var(--card); box-shadow: var(--lift); text-align: center; }
/* The imposter's card is the dark one. */
.imp-role.is-imposter { background: var(--ink); color: #fff; }
.imp-role-label { color: var(--ink-soft); font: 800 var(--t14)/1.3 var(--display); text-transform: uppercase; letter-spacing: 0.06em; margin: 0; }
.imp-role.is-imposter .imp-role-label { color: #ffb3bd; }
.imp-role.is-imposter .muted { color: #d9d3ea; }
.imp-role-word { font: 900 var(--t32)/1.15 var(--display); margin: var(--s1) 0 6px; overflow-wrap: anywhere; }
.imp-role-mask { display: block; width: 88px; height: 88px; margin: var(--s2) auto; }
.imp-role-mask svg { display: block; width: 100%; height: 100%; }
.imp-who { font-size: var(--t18); margin: 0 0 var(--s1); }
.room-imp-result h2 { font-size: var(--t20); }
.room-imp { text-align: center; }
.imp-clue-form { max-width: 360px; margin: 6px auto; }
.imp-votes, .imp-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: var(--s3); max-width: 460px; margin: var(--s3) auto; }
.imp-last { font-weight: 700; margin: var(--s1) 0; }
.imp-clock { margin: 6px 0 0; }
.imp-clues { list-style: none; padding: 0; margin: var(--s3) auto 0; max-width: 460px; display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.imp-clues li { background: var(--card); border: var(--edge-thin); border-radius: 999px; padding: 2px 12px; font-size: var(--t14); }
.imp-clues li.is-passed { opacity: 0.6; border-style: dashed; }
.imp-reveal { font-size: var(--t18); margin: var(--s1) 0 10px; }
.imp-reveal strong { font-family: var(--display); font-weight: 900; background: var(--gold); border: var(--edge-thin); border-radius: var(--r-xs); padding: 0 6px; }
.imp-clue-recap { margin-top: 10px; }
.imp-words { display: flex; flex-wrap: wrap; gap: 6px var(--s2); margin: 6px 0 0; }
.imp-words span { background: var(--card); border: var(--edge-thin); border-radius: 999px; padding: 2px 10px; font-size: var(--t14); }
.scoreboard tr.is-imposter td:first-child { font-weight: 800; color: var(--red-text); }

/* --- Ads (only on a site built with ads on: web/pages/ads.mjs) ---------------------------- */

/* Labelled, with the space held while the ad loads so nothing jumps; a slot
   Google leaves unfilled folds away. On game pages it sits well below the game. */
.ad-slot { max-width: 760px; margin: var(--s6) auto; text-align: center; }
.ad-slot-game { margin-top: var(--s7); }
.ad-label { margin: 0 0 6px; font: 700 var(--t12)/1.2 var(--display); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft); }
.ad-unit { display: block; min-height: 280px; }
.ad-slot:has(ins[data-ad-status="unfilled"]) { display: none; }

/* --- Would You Rather + Never Have I Ever (one phone and rooms) ----------------------- */

/* One phone: the question card. The two choices stack on a phone, side by side when there's room. */
.deck-card {
  max-width: 560px;
  min-height: 230px;
  margin: var(--s3) auto;
  padding: var(--s5) var(--s4);
  display: grid;
  align-content: center;
  gap: var(--s3);
  text-align: center;
  background: var(--card);
  border: var(--edge);
  border-radius: var(--r-l);
  box-shadow: var(--lift-big);
  animation: deal-in 0.32s cubic-bezier(0.2, 1.4, 0.4, 1);
}
.deck-lead, .split-lead { font: 900 var(--t14)/1.2 var(--display); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-soft); margin: 0; }
.deck-line, .split-line { font: 800 var(--t24)/1.3 var(--display); margin: 0; overflow-wrap: anywhere; text-wrap: balance; }
.deck-options, .split-answers { display: grid; gap: var(--s2); }
.deck-opt { display: grid; align-content: center; gap: 6px; padding: var(--s3) var(--s2); border: var(--edge-thin); border-radius: var(--r); }
.deck-opt-first, .split-opt[data-answer="first"], .split-row-first .split-fill { background: var(--sky); }
.deck-opt-second, .split-opt[data-answer="second"], .split-row-second .split-fill { background: var(--pink); }
.deck-side { font: 800 var(--t12)/1.2 var(--display); letter-spacing: 0.08em; text-transform: uppercase; }
.deck-text { font: 800 var(--t18)/1.3 var(--display); overflow-wrap: anywhere; text-wrap: balance; }
.deck-or, .split-or { align-self: center; font: 900 var(--t14)/1 var(--display); text-transform: uppercase; color: var(--ink-soft); }
.deck-note { text-align: center; min-height: 1.5em; margin: 0; }
.page-deck [data-play] .result-actions { margin: var(--s2) 0 var(--s4); }
/* "I have" / "Never": side by side on any phone, once .btn-big's 200px minimum is lifted (below). */
.split-nhie .split-answers { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
@media (min-width: 560px) {
  .deck-options, .split-wyr .split-answers { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: stretch; }
}
@media (min-width: 720px) {
  .deck-line, .split-line { font-size: var(--t32); }
  .deck-text { font-size: var(--t20); }
}

/* Rooms: answer in secret, guess the split, see the count. */
.room-split { text-align: center; }
.split-question { display: grid; gap: var(--s1); max-width: 560px; margin: var(--s1) auto var(--s3); font-size: var(--t24); }
.split-answers { max-width: 560px; margin: 0 auto var(--s3); }
/* A whole sentence on a button: lighter and tighter than a one-word big button. */
.split-opt.btn-big { min-width: 0; min-height: 56px; padding: 10px var(--s3); font-size: var(--t18); font-weight: 800; line-height: 1.25; }
.split-opt { color: var(--ink); text-wrap: balance; overflow-wrap: anywhere; }
.split-opt:hover { color: var(--ink); }
.split-opt[aria-pressed="true"], .split-opt[aria-pressed="true"]:hover { background: var(--ink); color: #fff; }
.split-opt.is-static { margin: 0; padding: var(--s3); border: var(--edge-thin); border-radius: var(--r); font: 800 var(--t16)/1.3 var(--display); }
.split-guess { max-width: 520px; margin: 0 auto var(--s2); }
.split-guess-q { font-weight: 700; margin: 0 0 var(--s2); overflow-wrap: anywhere; }
.split-chips { display: flex; flex-wrap: wrap; gap: var(--s2); justify-content: center; }
.split-chip { min-width: 52px; min-height: 48px; justify-content: center; font: 800 var(--t18)/1 var(--display); }
.split-clock { margin: 6px 0 0; }
.split-said { font: 800 var(--t20)/1.3 var(--display); max-width: 520px; margin: 0 auto var(--s3); text-wrap: balance; }
.split-bars { display: grid; gap: var(--s3); max-width: 520px; margin: 0 auto var(--s3); text-align: left; }
.split-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "label count" "track track"; gap: 4px var(--s2); align-items: end; }
.split-row-label { grid-area: label; font-weight: 700; overflow-wrap: anywhere; }
.split-row-count { grid-area: count; font: 900 var(--t24)/1 var(--display); }
.split-track { grid-area: track; display: block; height: 18px; overflow: hidden; background: var(--card); border: var(--edge-thin); border-radius: 999px; }
.split-fill { display: block; height: 100%; width: 0; }
.split-mine { font-weight: 700; margin: 0 0 var(--s3); }
.split-mine.is-good { color: var(--green); }
.split-scores { list-style: none; padding: 0; margin: 0 auto var(--s3); max-width: 460px; display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.split-scores li { display: inline-flex; align-items: center; gap: 6px; padding: 2px 4px 2px 12px; background: var(--card); border: var(--edge-thin); border-radius: 999px; font-size: var(--t14); }
.split-scores li.is-you { font-weight: 800; }
.split-scores strong { padding: 0 8px; background: var(--paper-deep); border-radius: 999px; }
.split-plus { color: var(--green); font-weight: 800; }
.result-headline { margin: -6px 0 var(--s3); }

/* --- online rooms ------------------------------------------------------------------- */

.text-input {
  width: 100%;
  background: var(--card);
  border: var(--edge-thin);
  color: var(--ink);
  border-radius: var(--r-s);
  padding: 10px 12px;
  font: 16px var(--body);
  margin-top: 6px;
}
.text-input:focus-visible { border-color: var(--purple); outline: 3px solid var(--purple); outline-offset: 2px; }
.join-row .add-form { margin-top: 6px; }
.join-row .text-input { margin-top: 0; text-transform: uppercase; letter-spacing: 0.12em; font-weight: 700; }

/* Connection trouble and "that room's gone": red words, not a headline. */
.room-status { text-align: center; color: var(--red-text); font-weight: 700; margin: var(--s2) 0; }
.room-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--s2) 10px; margin-top: 6px; flex-wrap: wrap; } /* on a 320px phone the buttons go under the code */
.room-code-line { margin: 0; display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.room-bar-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.lock-badge { display: inline-flex; align-items: center; gap: var(--s1); font: 800 var(--t12)/1 var(--display); color: #fff; background: var(--ink); border-radius: 999px; padding: 4px 10px; }
/* The room code is a ticket: easy to read out across a table. */
.room-code { font: 900 var(--t24)/1.1 var(--display); letter-spacing: 0.08em; color: var(--ink); background: var(--gold); border: var(--edge-thin); border-radius: var(--r-xs); padding: 1px var(--s2); }
.invite-msg { margin: var(--s1) 0 0; min-height: 1em; overflow-wrap: anywhere; }
.room-people { list-style: none; padding: 0; margin: 10px 0; display: flex; flex-wrap: wrap; gap: 6px; }
.person-chip { gap: 6px; }
.person.is-you .person-chip { background: #f1ecff; }
.person.is-away .person-chip { opacity: 0.45; border-style: dashed; }
.person-chip .in { color: var(--green); font-weight: 900; }
.person-chip .wins { display: inline-flex; align-items: center; gap: 2px; color: var(--ink); font-size: var(--t12); font-weight: 800; }
.person-chip .crown { display: inline-flex; color: var(--red); }
.person-chip .crown .ui-icon, .person-chip .wins .ui-icon { width: 1.05em; height: 1.05em; vertical-align: 0; }
.person-chip .wins .ui-icon { color: #b8860b; }

.room-layout { display: grid; gap: var(--s4); }
@media (min-width: 900px) {
  .room-layout { grid-template-columns: minmax(0, 1fr) 320px; align-items: start; }
}
.room-stage { min-height: 220px; }
.room-games { display: grid; gap: var(--s2); }
.game-group { margin: var(--s2) 0 0; font-size: var(--t16); display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) 10px; }
.game-group-note { color: var(--ink-soft); font: 400 var(--t14)/1.3 var(--body); }
.game-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
/* A tile left alone on the last row takes the whole row (five everyone-plays games). */
.game-tile:last-child:nth-child(odd) { grid-column: 1 / -1; }
@media (min-width: 640px) {
  .game-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .game-tile:last-child:nth-child(odd) { grid-column: auto; }
  .game-tile:last-child:nth-child(4n + 1) { grid-column: 1 / -1; }
}
/* Room game tiles are the home page's coloured boxes, smaller. */
.game-tile {
  --box: var(--card);
  --box-ink: var(--ink);
  appearance: none; font: inherit; color: var(--box-ink); text-align: left; cursor: pointer;
  background: var(--box); border: var(--edge); border-radius: var(--r);
  padding: var(--s3); min-height: 104px; display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  box-shadow: var(--lift); transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.game-tile[data-kind="wheel"], .game-tile[data-kind="c4"] { --box: var(--sky); }
.game-tile[data-kind="dice"] { --box: var(--red); --box-ink: #fff; }
.game-tile[data-kind="tod"] { --box: var(--purple); --box-ink: #fff; }
.game-tile[data-kind="imp"] { --box: var(--teal); }
.game-tile[data-kind="pairs"] { --box: var(--gold); }
.game-tile[data-kind="tower"] { --box: var(--orange); }
.game-tile[data-kind="bs"] { --box: var(--navy); --box-ink: #fff; }
.game-tile[data-kind="rps"], .game-tile[data-kind="duel"] { --box: var(--pink); }
.game-tile[data-kind="wyr"] { --box: var(--lime); }
.game-tile[data-kind="nhie"] { --box: var(--lilac); }
@media (hover: hover) {
  .game-tile:hover:not(:disabled) { transform: translate(-1px, -1px); box-shadow: var(--lift-big); }
}
.game-tile:active:not(:disabled) { transform: translate(3px, 3px); box-shadow: 1px 1px 0 var(--ink); }
.game-tile:disabled { background: var(--paper-deep); color: var(--ink-soft); border-style: dashed; border-color: var(--ink-soft); box-shadow: none; cursor: not-allowed; }
.game-tile-icon { display: grid; place-items: center; width: 42px; height: 42px; border-radius: 50%; background: var(--card); border: var(--edge-thin); margin-bottom: var(--s1); }
.game-tile-icon svg { display: block; width: 28px; height: 28px; }
.game-tile:disabled .game-tile-icon { opacity: 0.6; }
.game-tile-name { font: 900 var(--t16)/1.15 var(--display); }
.game-tile-text { font-size: var(--t14); line-height: 1.3; }
.waiting-hint { margin: 0; color: var(--ink); font-weight: 700; }
/* "Waiting for…" lines breathe, so a quiet screen doesn't look frozen. */
.waiting-dots::after { content: "…"; display: inline-block; width: 1.2em; text-align: left; }
@media (prefers-reduced-motion: no-preference) {
  .waiting-dots::after { animation: dots 1.4s steps(4, end) infinite; content: "..."; overflow: hidden; vertical-align: bottom; }
}
@keyframes dots {
  from { width: 0; }
  to { width: 1.2em; }
}
.dare-setup {
  appearance: none; font: inherit; color: var(--ink); text-align: left; cursor: pointer; margin-top: var(--s2);
  display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4);
  background: transparent; border: 2px dashed var(--ink-soft); border-radius: var(--r); width: 100%;
}
.dare-setup.is-on { border: var(--edge); border-color: var(--red); background: var(--card); box-shadow: 4px 4px 0 var(--red); }
.dare-setup:hover { border-color: var(--ink); }
.dare-setup-icon { display: inline-flex; color: var(--red); }
.dare-setup-icon .ui-icon { width: 28px; height: 28px; }
.dare-setup-body { display: grid; gap: 2px; flex: 1; min-width: 0; }
.dare-setup-title { font: 800 var(--t16)/1.3 var(--display); }
.dare-setup-text { color: var(--ink-soft); font-size: var(--t14); }
.dare-setup-go { color: var(--purple); font-weight: 800; font-size: var(--t14); }
.ready-dare { display: flex; align-items: center; justify-content: center; gap: 6px; color: var(--red-text); font-weight: 700; margin: 0 0 var(--s1); }
.dare-add { margin-top: var(--s1); }
.dare-count { margin: 0; }
.room-dare-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; max-height: 38vh; overflow-y: auto; overscroll-behavior: contain; }
.room-dare-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: var(--s2); background: var(--paper); border: var(--edge-thin); border-radius: var(--r-s); padding: var(--s2) 6px var(--s2) 10px; overflow-wrap: anywhere; }
.room-dare-list-text { grid-column: 1; }
.room-dare-list-by { grid-column: 1; color: var(--ink-soft); font-size: var(--t12); }
.room-dare-list .chip-x { grid-column: 2; grid-row: 1 / span 2; }
.room-ready { text-align: center; }
.room-ready h2 { font: 900 var(--t32)/1.15 var(--display); margin-bottom: 6px; }
.room-result { margin-top: 0; }
.room-result .result-card { margin-top: 6px; }
.room-scores { list-style: none; padding: 0; margin: var(--s3) auto 0; max-width: 440px; display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 6px; }
.room-scores li { display: flex; justify-content: space-between; gap: var(--s2); background: var(--paper); border: var(--edge-thin); border-radius: var(--r-s); padding: 6px 10px; }
.room-scores li.is-turn { background: var(--gold); }
.room-clock { color: var(--ink-soft); font-size: var(--t14); font-weight: 700; margin: var(--s1) 0 0; }
.room-clock.is-urgent strong { color: var(--red-text); }

.room-chat { background: var(--card); border: var(--edge); border-radius: var(--r); padding: var(--s3); display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); box-shadow: var(--lift); } /* minmax(0): a long newest line ellipsises instead of widening the page */
.chat-list { list-style: none; margin: 0; padding: 0; height: 220px; overflow-y: auto; overscroll-behavior: contain; display: grid; align-content: start; gap: var(--s1); font-size: var(--t16); overflow-wrap: anywhere; }
@media (min-width: 900px) { .chat-list { height: 380px; } }
.chat-list li strong { color: var(--purple); }
.chat-list li.chat-mine strong { color: var(--red-text); }
.chat-sys { color: var(--ink-soft); font-style: italic; font-size: var(--t14); }
.chat-form .text-input { margin-top: 0; }
.chat-toggle { display: none; }
.chat-title { display: inline-flex; align-items: center; gap: 6px; font-family: var(--display); font-weight: 800; }
/* Phones: the chat is a bar pinned to the bottom of the screen while you're in
   the room, showing the newest message; tap it to open the chat over the game. */
@media (max-width: 899px) {
  .room-chat { position: sticky; bottom: 0; z-index: 5; box-shadow: 0 -4px 0 var(--ink); border-radius: var(--r) var(--r) 0 0; padding-bottom: max(10px, env(safe-area-inset-bottom)); }
  .room-chat:not(.is-open) > :not(.chat-toggle):not([data-chat-err]) { display: none; }
  .room-chat:not(.is-open) [data-chat-err]:empty { display: none; }
  /* Open, it's pinned to the screen: a sticky element can't rise above the
     game area, which on a short phone pushed the message box off the bottom. */
  .room-chat.is-open { position: fixed; left: var(--gutter); right: var(--gutter); bottom: 0; }
  .room-chat.is-open .chat-list { height: 38vh; height: 38svh; }
  .chat-toggle {
    display: flex; align-items: center; gap: var(--s2); width: 100%; min-width: 0; min-height: 44px; padding: var(--s1) var(--s2);
    background: none; border: 0; color: var(--ink); font: 700 var(--t16)/1.2 var(--body); text-align: left; cursor: pointer;
  }
  .chat-title { flex: none; }
  .chat-peek { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-soft); font-weight: 400; font-size: var(--t14); }
  .room-chat.is-open .chat-peek { visibility: hidden; }
  .chat-unread { flex: none; min-width: 22px; padding: 1px 7px; border-radius: 99px; background: var(--red); color: #fff; font-size: var(--t12); font-weight: 800; text-align: center; } /* 5.0:1 */
  .chat-caret { display: inline-flex; margin-left: auto; }
  .chat-caret::before { transform: translateY(2px) rotate(-135deg); } /* closed: up, the chat opens upwards */
  .room-chat.is-open .chat-caret::before { transform: translateY(-3px) rotate(45deg); }
}

.dialog { position: fixed; inset: 0; z-index: 40; background: rgba(35, 27, 58, 0.55); display: grid; place-items: center; padding: var(--s4); }
.dialog-card { width: 100%; max-width: 420px; background: var(--card); border: var(--edge); border-radius: var(--r-l); padding: var(--s5) var(--s4) var(--s4); display: grid; gap: var(--s2); box-shadow: var(--lift-big); max-height: calc(100dvh - 32px); overflow-y: auto; }
.dialog-card h2 { font-size: var(--t24); margin: 0; }
/* The invite's QR code: white, with its own quiet zone, big enough to scan from across a table. */
.qr-box { display: grid; place-items: center; min-height: 200px; }
.qr { display: block; width: min(240px, 70vw); height: auto; border: var(--edge); border-radius: var(--r-s); }
.invite-code { display: flex; align-items: baseline; justify-content: center; gap: 10px; margin: 2px 0 var(--s1); }
.invite-code .room-code { font-size: var(--t32); letter-spacing: 0.12em; }
.dialog-actions { display: grid; gap: var(--s2); margin-top: var(--s2); }
.room-toast {
  position: fixed; left: 50%; bottom: var(--s5); transform: translateX(-50%); z-index: 45;
  background: var(--ink); color: #fff; border-radius: 999px; padding: 10px 18px; margin: 0;
  font-weight: 700; box-shadow: 3px 3px 0 var(--red); max-width: calc(100% - 32px);
}
.room-tod { text-align: center; }
.room-tod .tod-choose { display: flex; flex-wrap: wrap; gap: var(--s3); justify-content: center; margin: 6px 0 var(--s1); }
.room-tod .tod-choose .link-btn { flex-basis: 100%; }
.room-tod .result-card { max-width: 460px; margin: var(--s1) auto 0; }
.room-challenge .challenge-title { color: var(--ink); }
.rematch-row { margin-top: var(--s3); }
.room-wheel { text-align: center; }
.room-wheel .wheel-stage { width: min(100%, 360px); }
.room-wheel-list { text-align: left; max-width: 460px; margin: 14px auto 0; font-size: var(--t14); }
.room-wheel-list li { grid-template-columns: 30px 1fr; }
.room-tower .tw-stage { margin-top: 0; }
@media (min-width: 900px) { .room-tower .tw-stage { height: 560px; } }
/* Grid items default to min-width:auto, so a wide canvas (the tower's drawing
   buffer) would stretch the column past the screen. */
.room-layout > * { min-width: 0; }
.tw-canvas { max-width: 100%; }

/* --- head-to-head ----------------------------------------------------------------- */
.room-c4, .room-rps { text-align: center; }
.c4-board {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--s1);
  max-width: 420px;
  margin: var(--s2) auto var(--s3);
  padding: var(--s2);
  background: var(--sky);
  border: var(--edge);
  border-radius: var(--r);
  box-shadow: var(--lift);
}
.c4-col { appearance: none; border: 0; background: none; padding: 0; display: grid; gap: var(--s1); cursor: pointer; border-radius: var(--r-s); }
.c4-col:not(:disabled):hover { background: rgba(255, 255, 255, 0.25); }
.c4-col:disabled { cursor: default; }
.c4-col:focus-visible { outline-color: var(--ink); } /* purple on sky is 2.3:1 */
.c4-cell { aspect-ratio: 1; border-radius: 50%; background: var(--paper); border: var(--edge-thin); }
.c4-cell.d1, .c4-dot.d1 { background: var(--red); }
.c4-cell.d2, .c4-dot.d2 { background: var(--gold); }
.c4-cell.is-last { box-shadow: 0 0 0 3px #fff; }
.c4-cell.is-line { box-shadow: 0 0 0 3px var(--ink), 0 0 0 6px #fff; }
.c4-dot { display: inline-block; width: 14px; height: 14px; border-radius: 50%; border: var(--edge-thin); margin-right: 6px; vertical-align: middle; }
.c4-legend li { justify-content: flex-start; }
.rps-score { font-size: var(--t18); margin: var(--s1) 0 10px; }
.rps-score strong { font: 900 var(--t24)/1 var(--display); color: var(--ink); }
.rps-picks { display: grid; grid-template-columns: repeat(3, minmax(0, 110px)); gap: 10px; justify-content: center; margin: 6px 0 var(--s1); }
.rps-btn { flex-direction: column; min-width: 0; width: 100%; aspect-ratio: 1; border-radius: var(--r); gap: var(--s1); padding: var(--s2) var(--s1); }
.rps-emoji { font-size: var(--t32); line-height: 1; }
.rps-emoji.big { font-size: var(--t48); }
.rps-mine { font-size: var(--t20); font-weight: 800; }
.rps-reveal { display: flex; justify-content: center; gap: 28px; margin: var(--s2) 0; }
.rps-side { display: grid; gap: var(--s1); padding: 10px 14px; border-radius: var(--r); border: 2px solid transparent; }
.rps-side.is-win { background: var(--mint); border: var(--edge-thin); box-shadow: var(--lift-small); }
/* Rock, paper, scissors… the fists shake three times before the hands show. */
@media (prefers-reduced-motion: no-preference) {
  .rps-shaking .rps-emoji { display: inline-block; animation: rps-shake 0.3s ease-in-out 3; transform-origin: 50% 90%; }
}
@keyframes rps-shake {
  0%, 100% { transform: translateY(0) rotate(0); }
  50% { transform: translateY(-14px) rotate(-10deg); }
}

/* --- contact form ------------------------------------------------------------------- */

.contact-form { margin: var(--s4) 0 var(--s2); background: var(--card); border: var(--edge); border-radius: var(--r); padding: var(--s4); box-shadow: var(--lift); }
.contact-form .label { display: block; }
.contact-form .opt { text-transform: none; letter-spacing: 0; font-weight: 400; margin-left: var(--s1); }
.contact-form textarea.text-input { resize: vertical; min-height: 8em; line-height: 1.45; }
.contact-form .small { font-size: var(--t14); margin: 6px 0 0; }
.contact-form .btn { margin-top: 14px; min-width: 140px; }
.contact-form .hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.contact-thanks { margin: 18px 0; padding: 18px; border: var(--edge); border-radius: var(--r); background: var(--card); box-shadow: var(--lift); }
.contact-thanks:focus { outline: none; }
.contact-thanks h2 { margin-top: 0; }
.room-dare-list .chip-x { width: 36px; height: 36px; }
.contact-thanks p:last-child { margin-bottom: 0; }
[data-best]:empty { display: none; } /* "your best" appears after a first game; no gap before */
@media (max-width: 380px) {
  .btn-big { font-size: var(--t18); padding-left: var(--s4); padding-right: var(--s4); } /* "Battle the computer" on one line on a 320px phone */
}

/* --- Battleships (solo page and rooms) --- */
/* The sea stays dark: a navy board with an ink edge. */
.bs-sea { display: grid; gap: 3px; width: 100%; max-width: 380px; margin: 0 auto; padding: 6px; border-radius: var(--r); background: var(--navy); border: var(--edge); box-shadow: var(--lift); }
.bs-sea.is-small { max-width: 240px; gap: 2px; padding: var(--s1); border-width: 2px; box-shadow: var(--lift-small); }
.bs-row { display: grid; grid-template-columns: 14px repeat(8, 1fr); gap: inherit; align-items: center; }
.bs-labels span, .bs-label { font-size: var(--t12); font-weight: 700; color: #c9d6f0; text-align: center; line-height: 1.2; }
.bs-sea.is-small .bs-labels span, .bs-sea.is-small .bs-label { font-size: var(--t12); }
.bs-cell { appearance: none; border: 0; padding: 0; margin: 0; aspect-ratio: 1; border-radius: var(--r-xs); background: #2b4f8a; position: relative; display: grid; place-items: center; font: inherit; color: inherit; }
.bs-sea.is-small .bs-cell { border-radius: 4px; } /* a 26px square: the board's own geometry */
button.bs-cell { cursor: pointer; }
.is-aiming button.bs-cell:hover, .is-aiming button.bs-cell:focus-visible { background: #3d68ad; outline: 2px solid var(--gold); outline-offset: -2px; }
.bs-place-sea button.bs-cell:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.bs-cell.is-ship { background: #c9c2de; }
.bs-cell.is-shown { background: rgba(201, 194, 222, 0.45); box-shadow: inset 0 0 0 2px #c9c2de; }
.bs-cell.is-picked { background: var(--gold); }
.bs-cell.is-miss::after { content: ""; width: 26%; aspect-ratio: 1; border-radius: 50%; background: #dbe6ff; opacity: 0.85; }
.bs-cell.is-hit { background: var(--red); }
/* The hit mark is drawn: two white bars. */
.bs-cell.is-hit::after { content: ""; width: 52%; aspect-ratio: 1; background: linear-gradient(45deg, transparent 41%, #fff 41% 59%, transparent 59%), linear-gradient(-45deg, transparent 41%, #fff 41% 59%, transparent 59%); }
.bs-cell.is-sunk { background: #7a1020; }
.bs-cell.is-last { box-shadow: 0 0 0 2px #fff; z-index: 1; }
.bs-side { margin: 14px 0 6px; position: relative; }
.bs-side .label { text-align: center; display: block; margin-bottom: 6px; }
.bs-status { text-align: center; min-height: 1.4em; margin: var(--s1) 0 var(--s2); font: 900 var(--t20)/1.25 var(--display); }
.page-bs .bs-status.display { font-size: var(--t20); }
.bs-hint { text-align: center; min-height: 2.6em; margin: var(--s2) 0 0; }
.room-bs { text-align: center; }
.room-bs .is-urgent { color: var(--red-text); }
@media (prefers-reduced-motion: no-preference) {
  .bs-cell.is-last.is-hit, .bs-cell.is-last.is-miss::after { animation: bs-land 260ms ease-out; } /* only the newest shot: every shot redraws the sea */
}
@keyframes bs-land { from { transform: scale(0.6); } to { transform: scale(1); } }
/* A hit or a sinking flashes over the sea it happened on. */
.bs-flash {
  position: fixed;
  left: 50%;
  top: 50%;
  z-index: 3;
  pointer-events: none;
  font: 900 var(--t48)/1 var(--display);
  text-transform: uppercase;
  color: #fff;
  background: var(--red);
  border: var(--edge);
  border-radius: var(--r);
  box-shadow: var(--lift-big);
  padding: var(--s2) var(--s4);
  transform: translate(-50%, -50%) rotate(-6deg);
  white-space: nowrap;
}
.bs-flash.is-sunk { background: var(--gold); color: var(--ink); }
.bs-flash.is-miss { background: var(--card); color: var(--ink); font-size: var(--t32); }
@media (prefers-reduced-motion: no-preference) {
  .bs-flash { animation: flash-pop 0.9s ease-out forwards; }
}
@keyframes flash-pop {
  0% { transform: translate(-50%, -50%) rotate(-12deg) scale(0.4); opacity: 0; }
  20% { transform: translate(-50%, -50%) rotate(-5deg) scale(1.1); opacity: 1; }
  75% { transform: translate(-50%, -50%) rotate(-6deg) scale(1); opacity: 1; }
  100% { transform: translate(-50%, -50%) rotate(-6deg) scale(1); opacity: 0; }
}
@media (min-width: 760px) {
  .bs-seas { display: grid; grid-template-columns: 3fr 2fr; gap: var(--s5); align-items: start; }
}

/* --- Dice Duel (rooms) --- */
.room-duel { text-align: center; }
.duel-table { gap: 14px; flex-wrap: wrap; }
.duel-side { min-width: 132px; justify-items: center; }
.duel-dice { display: flex; gap: var(--s2); }
.duel-die { width: 52px; height: 52px; border-radius: var(--r-s); background: var(--card); border: var(--edge); display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); padding: 5px; box-shadow: var(--lift-small); }
.duel-die .pip { width: 9px; height: 9px; border-radius: 50%; background: var(--ink); place-self: center; }
.duel-die.is-blank { background: var(--paper-deep); border-style: dashed; box-shadow: none; display: grid; place-items: center; grid-template-columns: 1fr; grid-template-rows: 1fr; }
.duel-q { color: var(--ink-soft); font: 900 var(--t20)/1 var(--display); }
.duel-total { font: 900 var(--t32)/1.1 var(--display); color: var(--ink); }
.duel-line { font: 800 var(--t18)/1.3 var(--display); }
.room-duel .is-urgent { color: var(--red-text); }
@media (prefers-reduced-motion: no-preference) {
  .duel-dice.is-new .duel-die { animation: duel-land 320ms ease-out; }
}
@keyframes duel-land { from { transform: rotate(-25deg) scale(0.6); } to { transform: none; } }

/* A phone on its side, in a game (kept last so it wins over each game's own
   rules): the title goes while playing and the boards size to the height. */
@media (max-height: 500px) and (orientation: landscape) {
  .game:has(> [data-setup][hidden]) .game-head { display: none; }
  .pr-stage, .pr-hud { width: min(100%, calc(100vh - 110px)); }
  .pr-hud { margin: 0 auto var(--s1); }
  .pr-board { gap: 6px; }
  [data-play] .bs-sea:not(.is-small) { max-width: min(380px, calc(100vh - 110px)); }
  .handoff { padding: var(--s2) 0; }
  .handoff-name { margin-bottom: var(--s3); }
  .imp-role { padding: var(--s3); margin-bottom: var(--s2); }
  .imp-role-word { margin: 0; }
  .imp-role-mask { width: 56px; height: 56px; margin: var(--s1) auto; }
  .dice-stage { gap: var(--s2); margin: var(--s2) 0; }
  .die { width: 96px; height: 96px; padding: 10px; }
  .die i { width: 16px; height: 16px; }
}
