:root {
  --bg: #07071a;
  --bg2: #0d0d2b;
  --panel: rgba(22, 20, 64, 0.72);
  --panel-solid: #15133f;
  --line: rgba(163, 107, 255, 0.28);
  --text: #eef0ff;
  --muted: #9a9dd0;
  --pink: #ff3d9a;
  --cyan: #19e6ff;
  --lime: #b6ff3b;
  --yellow: #ffe14d;
  --purple: #a36bff;
  --red: #ff4b5c;
  --orange: #ff9f43;
  --green: #3dff8f;
  --a: var(--pink);
  --b: var(--cyan);
  --radius: 18px;
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  /* One motion scale for the whole app. Everything that moves picks a
     duration and an easing from here, so nothing feels like it belongs to a
     different program. Out-easing for things arriving, spring for things the
     player just touched. */
  --ease-out: cubic-bezier(.22, .68, .28, 1);
  --ease-in-out: cubic-bezier(.45, .05, .3, 1);
  --spring: cubic-bezier(.34, 1.56, .48, 1);
  --t-tap: .12s;
  --t-quick: .2s;
  --t-move: .32s;
  --t-enter: .45s;
  --head: "Orbitron", "Segoe UI", system-ui, sans-serif;
  --body: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text); font-family: var(--body); }
body {
  overscroll-behavior: none;
  background:
    radial-gradient(1200px 600px at 50% -10%, rgba(163, 107, 255, 0.18), transparent 60%),
    radial-gradient(800px 500px at 100% 100%, rgba(25, 230, 255, 0.10), transparent 60%),
    radial-gradient(800px 500px at 0% 100%, rgba(255, 61, 154, 0.10), transparent 60%),
    var(--bg);
}
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    linear-gradient(rgba(163, 107, 255, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(163, 107, 255, 0.07) 1px, transparent 1px);
  background-size: 34px 34px;
  mask-image: linear-gradient(to bottom, rgba(0,0,0,.9), rgba(0,0,0,.25));
}
button, input { font: inherit; color: inherit; }
button { cursor: pointer; touch-action: manipulation; }
a { color: var(--cyan); }
[hidden] { display: none !important; }

#app {
  position: relative; z-index: 1;
  min-height: 100dvh;
  max-width: 540px; margin: 0 auto;
  display: flex; flex-direction: column;
  padding-top: var(--safe-top);
}
#top {
  position: sticky; top: 0; z-index: 5;
  /* Slimmer than it was. Four controls live up here now, so the bar earns its
     place by being compact rather than by being tall. */
  display: flex; align-items: center; gap: 6px;
  padding: calc(6px + var(--safe-top)) 11px 6px;
  margin-top: calc(-1 * var(--safe-top));
  background: linear-gradient(to bottom, rgba(7,7,26,.96), rgba(7,7,26,.85));
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  min-height: 46px;
}
#top:empty { display: none; }
#main { flex: 1; padding: 14px 16px calc(88px + var(--safe-bottom)); }

.logo {
  font-family: var(--head); font-weight: 900; letter-spacing: 0.06em;
  background: linear-gradient(90deg, var(--pink), var(--purple), var(--cyan));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 10px rgba(255, 61, 154, 0.45));
}
.logo.big { font-size: clamp(30px, 9vw, 44px); text-align: center; line-height: 1.1; }
.logo.small { font-size: 17px; }
h1, h2, h3 { font-family: var(--head); margin: 0; letter-spacing: 0.04em; }
h2 { font-size: 18px; }
h3 { font-size: 14px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.12em; font-weight: 700; }
.muted { color: var(--muted); }
.center { text-align: center; }
.stack { display: flex; flex-direction: column; gap: 14px; }
.row { display: flex; align-items: center; gap: 10px; }
.grow { flex: 1; min-width: 0; }
.spacer { flex: 1; }

.panel {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px; box-shadow: 0 10px 30px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.04);
}

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 52px; padding: 12px 18px; border-radius: 14px;
  border: 1px solid transparent; font-weight: 700; font-size: 16px; letter-spacing: 0.02em;
  background: linear-gradient(135deg, var(--pink), var(--purple));
  color: #fff; box-shadow: 0 0 18px rgba(255, 61, 154, 0.35), 0 8px 20px rgba(0,0,0,.3);
  transition: transform .08s ease, filter .15s ease, opacity .15s ease;
}
.btn:active { transform: scale(0.97); filter: brightness(1.15); }
.btn:disabled { opacity: .45; filter: grayscale(.4); box-shadow: none; }
.btn.cyan { background: linear-gradient(135deg, var(--cyan), #3b7bff); color: #041018; box-shadow: 0 0 18px rgba(25, 230, 255, 0.35), 0 8px 20px rgba(0,0,0,.3); }
.btn.lime { background: linear-gradient(135deg, var(--lime), #3dff8f); color: #061a08; box-shadow: 0 0 18px rgba(182, 255, 59, 0.35), 0 8px 20px rgba(0,0,0,.3); }
.btn.ghost { background: rgba(255,255,255,.04); border-color: var(--line); color: var(--text); box-shadow: none; }
.btn.danger { background: linear-gradient(135deg, var(--red), #ff2e88); box-shadow: 0 0 18px rgba(255, 75, 92, 0.35); }
.btn.small { width: auto; min-height: 40px; padding: 8px 14px; font-size: 14px; border-radius: 12px; }
.btn.auto { width: auto; }
.icon-btn {
  width: 40px; height: 40px; border-radius: 12px; border: 1px solid var(--line);
  background: rgba(255,255,255,.04); color: var(--text); font-size: 18px; display: inline-flex; align-items: center; justify-content: center;
}
.icon-btn:active { background: rgba(255,255,255,.1); }

.field { display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: 13px; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }
input[type=text], input[type=password] {
  width: 100%; min-height: 50px; padding: 12px 14px; border-radius: 14px;
  border: 1px solid var(--line); background: rgba(5, 5, 20, 0.7); color: var(--text); outline: none;
  font-size: 16px;
}
input:focus { border-color: var(--cyan); box-shadow: 0 0 0 3px rgba(25, 230, 255, 0.18); }
.error {
  background: rgba(255, 75, 92, 0.14); border: 1px solid rgba(255, 75, 92, 0.5); color: #ffb3bb;
  padding: 10px 14px; border-radius: 12px; font-size: 14px;
}
.hint { font-size: 13px; color: var(--muted); line-height: 1.45; }

.pill {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  border: 1px solid currentColor;
}
.pill.coop { color: var(--lime); }
.pill.vs { color: var(--orange); }
.pill.a { color: var(--a); }
.pill.b { color: var(--b); }

/* Presence has to be readable at a glance on a phone in daylight, so offline is
   red rather than a dark grey that reads as "no dot at all", and online pulses.
   The ring is what makes both visible against a busy panel. */
.dot { width: 10px; height: 10px; border-radius: 50%; background: var(--red); display: inline-block; vertical-align: middle;
  box-shadow: 0 0 0 2px rgba(255, 75, 92, .20), 0 0 6px rgba(255, 75, 92, .45); }
.dot.on { background: var(--green); box-shadow: 0 0 0 2px rgba(61, 255, 143, .22), 0 0 10px var(--green); animation: dotPulse 2.4s ease-in-out infinite; }
@keyframes dotPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.28); } }
@media (prefers-reduced-motion: reduce) { .dot.on { animation: none; } }
.fsub .dot { margin-right: 3px; }
.fsub .pres { font-weight: 700; }
.fsub .pres.on { color: var(--green); }
.fsub .pres.off { color: var(--red); opacity: .85; }

/* home */
.hero { text-align: center; padding: 18px 0 4px; }
.hero .sub { color: var(--muted); font-size: 14px; margin-top: 6px; }
.room-list { display: flex; flex-direction: column; gap: 10px; }
.room-item {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 12px 14px; border-radius: 14px; border: 1px solid var(--line); background: rgba(255,255,255,.03); color: var(--text);
}
.room-item:active { background: rgba(255,255,255,.08); }
.room-item .code { font-family: var(--head); font-weight: 700; letter-spacing: .18em; color: var(--cyan); text-shadow: 0 0 10px rgba(25,230,255,.5); }
.people { display: flex; flex-wrap: wrap; gap: 8px; }
.person { display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 999px; border: 1px solid var(--line); background: rgba(255,255,255,.03); font-size: 14px; }
.code-form { display: flex; gap: 8px; }
.code-form input { text-transform: uppercase; letter-spacing: .3em; font-family: var(--head); font-weight: 700; text-align: center; }

/* room */
.room-code { font-family: var(--head); font-weight: 900; font-size: 34px; letter-spacing: .28em; color: var(--cyan); text-shadow: 0 0 14px rgba(25,230,255,.6); text-align: center; }
.players { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.player-card {
  border-radius: 14px; padding: 12px; border: 1px solid var(--line); background: rgba(255,255,255,.03);
  display: flex; flex-direction: column; gap: 6px; min-height: 84px;
}
.player-card.a { border-color: rgba(255,61,154,.55); box-shadow: inset 0 0 24px rgba(255,61,154,.08); }
.player-card.b { border-color: rgba(25,230,255,.55); box-shadow: inset 0 0 24px rgba(25,230,255,.08); }
.player-card .name { font-weight: 800; font-size: 16px; display: flex; align-items: center; gap: 8px; }
.player-card.a .name { color: var(--a); } .player-card.b .name { color: var(--b); }
.player-card .status { font-size: 12px; color: var(--muted); }
.player-card .ready { color: var(--lime); font-weight: 700; font-size: 12px; }
.games { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.game-card {
  text-align: left; padding: 12px; border-radius: 14px; border: 1px solid var(--line); background: rgba(255,255,255,.03); color: var(--text);
  display: flex; flex-direction: column; gap: 6px; min-height: 120px; position: relative;
}
.game-card .icon { font-size: 28px; line-height: 1; }
.game-card .gname { font-family: var(--head); font-weight: 700; font-size: 13px; letter-spacing: .04em; }
.game-card .tag { font-size: 12px; color: var(--muted); line-height: 1.3; }
.game-card.selected { border-color: var(--lime); box-shadow: 0 0 0 2px rgba(182,255,59,.35), 0 0 22px rgba(182,255,59,.25); background: rgba(182,255,59,.06); }
.game-card .pill { position: absolute; top: 10px; right: 10px; font-size: 10px; padding: 2px 7px; }
.score-strip { display: flex; justify-content: center; gap: 14px; font-size: 14px; color: var(--muted); flex-wrap: wrap; }
.score-strip b { color: var(--text); }

/* game chrome */
.turnbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.turn-pill { font-weight: 800; font-size: 14px; padding: 8px 14px; border-radius: 999px; border: 1px solid var(--line); background: rgba(255,255,255,.04); }
.turn-pill.mine { border-color: var(--lime); color: var(--lime); box-shadow: 0 0 14px rgba(182,255,59,.3); animation: pulse 1.4s ease-in-out infinite; }
/* a bot mid-thought: the pill keeps its place and grows three dots */
.turn-pill.is-thinking { display: inline-flex; align-items: center; gap: 7px; border-color: color-mix(in srgb, var(--cyan) 55%, transparent); }
.scores { display: flex; gap: 12px; font-family: var(--head); font-weight: 700; font-size: 15px; }
.scores .a { color: var(--a); } .scores .b { color: var(--b); }
@keyframes pulse { 0%,100% { box-shadow: 0 0 10px rgba(182,255,59,.25);} 50% { box-shadow: 0 0 20px rgba(182,255,59,.55);} }
.status-line { text-align: center; color: var(--muted); font-size: 14px; margin-top: 14px; min-height: 20px; }

/* overlay */
#overlay {
  position: fixed; inset: 0; z-index: 30; background: rgba(4,4,18,.78); backdrop-filter: blur(8px);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.modal { width: 100%; max-width: 420px; text-align: center; animation: pop .25s ease-out; }
.modal .big { font-family: var(--head); font-weight: 900; font-size: 30px; line-height: 1.15; margin: 8px 0; }
.modal .big.win { color: var(--lime); text-shadow: 0 0 18px rgba(182,255,59,.6); }
.modal .big.lose { color: var(--red); text-shadow: 0 0 18px rgba(255,75,92,.6); }
.modal .big.a { color: var(--a); text-shadow: 0 0 18px rgba(255,61,154,.6); }
.modal .big.b { color: var(--b); text-shadow: 0 0 18px rgba(25,230,255,.6); }
.modal .emoji { font-size: 56px; line-height: 1; }
.modal .actions { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
@keyframes pop { from { transform: scale(.85); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* toasts + floaters */
#toasts { position: fixed; top: calc(64px + var(--safe-top)); left: 0; right: 0; z-index: 40; display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none; padding: 0 16px; }
.toast { background: rgba(20,18,60,.95); border: 1px solid var(--line); border-radius: 14px; padding: 7px 12px; font-size: 13px; line-height: 1.35; max-width: min(420px, 100%); box-shadow: 0 8px 24px rgba(0,0,0,.4); animation: toastin .25s ease-out; }
/* Three stacked toasts covered the thing they were telling you about. Older
   ones shrink back and fade so the newest is always the readable one. */
#toasts .toast:nth-last-child(2) { opacity: .7; transform: scale(.94); }
#toasts .toast:nth-last-child(3) { opacity: .45; transform: scale(.88); }
#toasts .toast:nth-last-child(n+4) { display: none; }
.toast.err { border-color: rgba(255,75,92,.6); color: #ffb3bb; }
.toast.chat { border-color: rgba(25,230,255,.5); }
@keyframes toastin { from { transform: translateY(-10px); opacity: 0; } to { transform: none; opacity: 1; } }
#floaters { position: fixed; inset: 0; pointer-events: none; z-index: 35; overflow: hidden; }
.floater { position: absolute; bottom: 20%; font-size: 64px; animation: floatup 2.2s ease-out forwards; filter: drop-shadow(0 0 12px rgba(255,255,255,.4)); }
@keyframes floatup { 0% { transform: translateY(0) scale(.6); opacity: 0; } 15% { opacity: 1; transform: translateY(-20px) scale(1.1);} 100% { transform: translateY(-260px) scale(1); opacity: 0; } }

/* chat */
.fab {
  position: fixed; right: 16px; bottom: calc(18px + var(--safe-bottom)); z-index: 20;
  width: 56px; height: 56px; border-radius: 50%; border: 1px solid var(--line);
  background: linear-gradient(135deg, #1c1a55, #2a1e6b); color: #fff; font-size: 24px;
  box-shadow: 0 0 18px rgba(163,107,255,.4), 0 8px 20px rgba(0,0,0,.4);
}
#chat-badge { position: absolute; top: -4px; right: -4px; min-width: 22px; height: 22px; padding: 0 6px; border-radius: 11px; background: var(--pink); color: #fff; font-size: 12px; font-weight: 800; display: flex; align-items: center; justify-content: center; box-shadow: 0 0 10px var(--pink); }
#chat-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 25; max-width: 540px; margin: 0 auto;
  height: min(62dvh, 520px); display: flex; flex-direction: column;
  background: rgba(13, 12, 42, 0.97); border: 1px solid var(--line); border-bottom: none; border-radius: 22px 22px 0 0;
  box-shadow: 0 -12px 40px rgba(0,0,0,.5); padding-bottom: var(--safe-bottom);
  animation: sheetin .22s ease-out;
}
@keyframes sheetin { from { transform: translateY(40px); opacity: 0; } to { transform: none; opacity: 1; } }
.sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid var(--line); }
#chat-list { flex: 1; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }
.msg { max-width: 82%; padding: 8px 12px; border-radius: 14px; font-size: 15px; line-height: 1.35; word-wrap: break-word; }
.msg.a { align-self: flex-start; background: rgba(255,61,154,.16); border: 1px solid rgba(255,61,154,.4); border-bottom-left-radius: 4px; }
.msg.b { align-self: flex-start; background: rgba(25,230,255,.13); border: 1px solid rgba(25,230,255,.4); border-bottom-left-radius: 4px; }
.msg.me { align-self: flex-end; border-bottom-left-radius: 14px; border-bottom-right-radius: 4px; }
.msg .who { display: block; font-size: 11px; font-weight: 700; opacity: .8; margin-bottom: 2px; letter-spacing: .04em; }
.msg.sys { align-self: center; background: none; border: none; color: var(--muted); font-size: 12px; }
.msg.react { font-size: 26px; padding: 2px 8px; background: none; border: none; }
#chat-reacts { display: flex; gap: 6px; padding: 6px 12px 0; overflow-x: auto; }
#chat-reacts button { font-size: 22px; background: rgba(255,255,255,.05); border: 1px solid var(--line); border-radius: 12px; width: 44px; height: 40px; flex: 0 0 auto; }
#chat-form { display: flex; gap: 8px; padding: 10px 12px 12px; }
#chat-form input { min-height: 44px; }

/* ---------- Connect Four ---------- */
.c4-board {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; padding: 10px;
  border-radius: 18px; background: linear-gradient(160deg, #2a1a6e, #171040);
  border: 2px solid var(--purple); box-shadow: 0 0 24px rgba(163,107,255,.35), inset 0 0 40px rgba(0,0,0,.4);
  touch-action: manipulation; user-select: none;
}
.c4-cell { aspect-ratio: 1; border-radius: 50%; background: #07071a; box-shadow: inset 0 2px 6px rgba(0,0,0,.8); position: relative; }
.c4-cell.A { background: var(--a); box-shadow: 0 0 12px var(--a), inset 0 -4px 8px rgba(0,0,0,.35); }
.c4-cell.B { background: var(--b); box-shadow: 0 0 12px var(--b), inset 0 -4px 8px rgba(0,0,0,.35); }
.c4-cell.last { animation: dropin .35s cubic-bezier(.2,.8,.3,1.2); }
.c4-cell.win::after { content: ""; position: absolute; inset: 22%; border-radius: 50%; background: #fff; box-shadow: 0 0 10px #fff; animation: blink .8s infinite; }
@keyframes dropin { from { transform: translateY(-300%); } to { transform: none; } }
@keyframes blink { 50% { opacity: .2; } }
.c4-cols { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; padding: 0 10px; margin-bottom: 6px; }
.c4-cols button { height: 34px; border-radius: 10px; border: 1px dashed var(--line); background: rgba(182,255,59,.06); color: var(--lime); font-size: 16px; }
.c4-cols button:disabled { opacity: .25; }
.c4-cols button:active { background: rgba(182,255,59,.25); }

/* ---------- Dots & Boxes ---------- */
.dots-wrap { display: flex; justify-content: center; }
.dots-svg { width: 100%; max-width: 420px; touch-action: manipulation; user-select: none; }
.dots-svg .dot { fill: #d7d9ff; }
.dots-svg .ghost { stroke: rgba(255,255,255,.10); stroke-width: 4; stroke-linecap: round; }
.dots-svg .hit { stroke: transparent; stroke-width: 26; stroke-linecap: round; pointer-events: stroke; }
.dots-svg .hit.mine:active { stroke: rgba(182,255,59,.35); }
.dots-svg .line.A { stroke: var(--a); stroke-width: 7; stroke-linecap: round; filter: drop-shadow(0 0 5px var(--a)); }
.dots-svg .line.B { stroke: var(--b); stroke-width: 7; stroke-linecap: round; filter: drop-shadow(0 0 5px var(--b)); }
.dots-svg .line.last { stroke-width: 9; }
.dots-svg .box.A { fill: rgba(255,61,154,.28); }
.dots-svg .box.B { fill: rgba(25,230,255,.25); }
.dots-svg .box-label { font-family: var(--head); font-weight: 900; font-size: 22px; text-anchor: middle; dominant-baseline: central; }
.dots-svg .box-label.A { fill: var(--a); } .dots-svg .box-label.B { fill: var(--b); }

/* ---------- Mind Meld ---------- */
.mm-prompt { text-align: center; padding: 18px 12px; }
.mm-prompt .round { font-family: var(--head); font-size: 13px; letter-spacing: .2em; color: var(--muted); text-transform: uppercase; }
.mm-prompt .big { font-family: var(--head); font-weight: 800; font-size: 22px; margin-top: 8px; color: var(--yellow); text-shadow: 0 0 14px rgba(255,225,77,.5); }
.mm-history { display: flex; flex-direction: column; gap: 8px; }
.mm-pair { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px; }
.mm-word { padding: 10px 12px; border-radius: 12px; font-weight: 700; text-align: center; border: 1px solid; word-break: break-word; }
.mm-word.A { color: var(--a); border-color: rgba(255,61,154,.5); background: rgba(255,61,154,.08); }
.mm-word.B { color: var(--b); border-color: rgba(25,230,255,.5); background: rgba(25,230,255,.08); }
.mm-word.wait { color: var(--muted); border-style: dashed; font-weight: 500; }
.mm-mid { color: var(--muted); font-size: 18px; }
.mm-form { display: flex; gap: 8px; }
.mm-locked { text-align: center; padding: 14px; border: 1px dashed var(--lime); border-radius: 14px; color: var(--lime); }

/* ---------- Bomb Squad ---------- */
.bomb-head { position: sticky; top: calc(58px + var(--safe-top)); z-index: 4; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 12px 16px; border-radius: 16px; background: #100b1e; border: 1px solid rgba(255,75,92,.45); box-shadow: 0 0 22px rgba(255,75,92,.2); }
.bomb-timer { font-family: var(--head); font-weight: 900; font-size: 40px; letter-spacing: .08em; color: var(--red); text-shadow: 0 0 16px rgba(255,75,92,.8); font-variant-numeric: tabular-nums; }
.bomb-timer.low { animation: blink .5s infinite; }
.strikes { display: flex; gap: 6px; }
.strike { width: 26px; height: 26px; border-radius: 6px; border: 1px solid rgba(255,75,92,.5); display: flex; align-items: center; justify-content: center; font-weight: 900; color: rgba(255,75,92,.25); }
.strike.on { color: var(--red); background: rgba(255,75,92,.2); box-shadow: 0 0 10px rgba(255,75,92,.6); }
.role-tag { font-family: var(--head); font-size: 11px; letter-spacing: .2em; color: var(--muted); }
.edgework { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
.edge { padding: 10px 12px; border-radius: 12px; background: rgba(255,255,255,.04); border: 1px solid var(--line); }
.edge .lbl { font-size: 11px; color: var(--muted); letter-spacing: .12em; text-transform: uppercase; }
.edge .val { font-family: var(--head); font-weight: 800; font-size: 18px; margin-top: 4px; letter-spacing: .1em; }
.edge.serial { grid-column: 1 / -1; }
.edge.serial .val { font-size: 26px; color: var(--yellow); text-shadow: 0 0 12px rgba(255,225,77,.5); letter-spacing: .2em; }
.ind { display: inline-flex; align-items: center; gap: 6px; margin-right: 10px; font-family: var(--head); font-weight: 700; }
.ind .led { width: 10px; height: 10px; border-radius: 50%; background: #3a3a55; }
.ind.lit .led { background: var(--lime); box-shadow: 0 0 8px var(--lime); }
.module { border-radius: 16px; border: 1px solid var(--line); background: linear-gradient(160deg, #1a1740, #0f0d2a); padding: 14px; position: relative; }
.module.solved { border-color: rgba(61,255,143,.6); box-shadow: 0 0 18px rgba(61,255,143,.2); }
.module .led { position: absolute; top: 12px; right: 12px; width: 12px; height: 12px; border-radius: 50%; background: var(--red); box-shadow: 0 0 8px var(--red); }
.module.solved .led { background: var(--green); box-shadow: 0 0 10px var(--green); }
.module h4 { margin: 0 0 10px; font-family: var(--head); font-size: 13px; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.module.solved h4::after { content: " · DEFUSED"; color: var(--green); }
.wires { display: flex; flex-direction: column; gap: 10px; }
.wire { display: flex; align-items: center; gap: 10px; height: 44px; border-radius: 10px; background: rgba(0,0,0,.25); padding: 0 10px; border: 1px solid transparent; }
.wire .num { width: 18px; font-size: 12px; color: var(--muted); font-family: var(--head); }
.wire .strand { flex: 1; height: 12px; border-radius: 6px; position: relative; }
.wire.selected { border-color: var(--yellow); box-shadow: 0 0 10px rgba(255,225,77,.4); }
.wire.cut .strand { opacity: .55; }
.wire.cut .strand::after { content: ""; position: absolute; left: 45%; width: 10%; top: -4px; bottom: -4px; background: #0f0d2a; }
.wire .cname { font-size: 12px; color: var(--muted); width: 52px; text-align: right; text-transform: capitalize; }
.wc-red { background: #ff3b3b; box-shadow: 0 0 8px #ff3b3b; }
.wc-blue { background: #3b6bff; box-shadow: 0 0 8px #3b6bff; }
.wc-yellow { background: #ffe14d; box-shadow: 0 0 8px #ffe14d; }
.wc-black { background: #222; border: 1px solid #666; }
.wc-white { background: #f4f4ff; box-shadow: 0 0 8px #fff; }
.wire-actions { margin-top: 10px; }
.bigbtn-wrap { display: flex; align-items: center; justify-content: center; gap: 18px; padding: 8px 0; }
.bigbtn {
  width: 150px; height: 150px; border-radius: 50%; border: 6px solid rgba(255,255,255,.15); font-family: var(--head); font-weight: 900; font-size: 15px; letter-spacing: .06em;
  box-shadow: 0 8px 0 rgba(0,0,0,.5), 0 0 24px rgba(255,255,255,.15); user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; touch-action: none;
}
.bigbtn:active, .bigbtn.holding { transform: translateY(6px); box-shadow: 0 2px 0 rgba(0,0,0,.5); }
.bigbtn.red { background: radial-gradient(circle at 35% 30%, #ff7a7a, #c60023); color: #fff; }
.bigbtn.blue { background: radial-gradient(circle at 35% 30%, #7aa0ff, #0a2fb8); color: #fff; }
.bigbtn.yellow { background: radial-gradient(circle at 35% 30%, #fff6a8, #e0b800); color: #2a2200; }
.bigbtn.white { background: radial-gradient(circle at 35% 30%, #ffffff, #b9bccc); color: #222; }
.strip { width: 26px; height: 130px; border-radius: 8px; background: #1b1a33; border: 1px solid var(--line); }
.strip.blue { background: #3b6bff; box-shadow: 0 0 16px #3b6bff; }
.strip.white { background: #fff; box-shadow: 0 0 16px #fff; }
.strip.yellow { background: #ffe14d; box-shadow: 0 0 16px #ffe14d; }
.strip.red { background: #ff3b3b; box-shadow: 0 0 16px #ff3b3b; }
.keypad { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.key { height: 76px; border-radius: 14px; border: 1px solid var(--line); background: #0a0920; color: #fff; font-size: 34px; box-shadow: inset 0 -4px 0 rgba(0,0,0,.5); }
.key.lit { border-color: var(--green); color: var(--green); box-shadow: 0 0 14px rgba(61,255,143,.5); }
.simon { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; max-width: 260px; margin: 0 auto; }
.simon-pad { aspect-ratio: 1; border-radius: 16px; border: none; opacity: .45; transition: opacity .12s, transform .12s; }
.simon-pad.flash, .simon-pad:active { opacity: 1; transform: scale(1.04); }
.simon-pad.red { background: #ff3b3b; box-shadow: 0 0 18px #ff3b3b; }
.simon-pad.blue { background: #3b6bff; box-shadow: 0 0 18px #3b6bff; }
.simon-pad.green { background: #2eff7a; box-shadow: 0 0 18px #2eff7a; }
.simon-pad.yellow { background: #ffe14d; box-shadow: 0 0 18px #ffe14d; }
.simon-stages { display: flex; gap: 6px; justify-content: center; margin: 10px 0; }
.simon-stages span { width: 12px; height: 12px; border-radius: 50%; background: #2a2850; }
.simon-stages span.done { background: var(--green); box-shadow: 0 0 8px var(--green); }
.simon-stages span.cur { background: var(--yellow); box-shadow: 0 0 8px var(--yellow); }
.progress-leds { display: flex; gap: 8px; }
.progress-leds span { flex: 1; height: 10px; border-radius: 5px; background: rgba(255,75,92,.3); }
.progress-leds span.done { background: var(--green); box-shadow: 0 0 8px var(--green); }

/* manual */
.manual { display: flex; flex-direction: column; gap: 10px; }
.manual details { border: 1px solid var(--line); border-radius: 14px; background: #f7f3e6; color: #1d1a12; overflow: hidden; }
.manual summary { padding: 12px 14px; font-family: var(--head); font-weight: 700; letter-spacing: .06em; font-size: 14px; cursor: pointer; background: #ece6d2; list-style: none; display: flex; align-items: center; justify-content: space-between; }
.manual summary::after { content: "＋"; font-size: 18px; }
.manual details[open] summary::after { content: "－"; }
.manual .body { padding: 12px 14px 14px; font-size: 15px; line-height: 1.5; }
.manual .body p { margin: 0 0 8px; }
.manual ol { margin: 6px 0 10px; padding-left: 22px; }
.manual li { margin-bottom: 6px; }
.manual .step { font-weight: 700; }
.manual .note { background: #fff8d6; border-left: 4px solid #e0b800; padding: 8px 10px; border-radius: 6px; font-size: 14px; margin: 8px 0; }
.chip { display: inline-block; padding: 1px 8px; border-radius: 999px; font-weight: 700; font-size: 13px; border: 1px solid rgba(0,0,0,.2); vertical-align: middle; }
.chip.red { background: #ff5c5c; color: #fff; } .chip.blue { background: #3b6bff; color: #fff; } .chip.yellow { background: #ffe14d; color: #3a3000; }
.chip.black { background: #222; color: #fff; } .chip.white { background: #fff; color: #222; } .chip.green { background: #2ecc71; color: #fff; }
.kp-cols { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; }
.kp-col { display: flex; flex-direction: column; gap: 4px; background: #fff; border: 1px solid #cfc8b0; border-radius: 8px; padding: 6px 2px; }
.kp-col .h { font-family: var(--head); font-size: 11px; text-align: center; color: #7a7260; }
.kp-col .s { font-size: 24px; text-align: center; line-height: 1.25; }
.simon-table { width: 100%; border-collapse: collapse; font-size: 14px; margin-top: 6px; }
.simon-table th, .simon-table td { border: 1px solid #cfc8b0; padding: 6px 4px; text-align: center; }
.simon-table th { background: #ece6d2; font-size: 12px; }
.talk-box { text-align: center; padding: 14px; border: 1px dashed var(--line); border-radius: 14px; color: var(--muted); font-size: 14px; line-height: 1.5; }

.shake { animation: shake .4s; }
@keyframes shake { 0%,100% { transform: none; } 20% { transform: translateX(-8px); } 40% { transform: translateX(8px); } 60% { transform: translateX(-6px); } 80% { transform: translateX(6px); } }

.pause-card { text-align: center; }

/* =========================================================
   v2: seats C/D, tabs, avatars, home, store, quests, games
   ========================================================= */
:root { --c: var(--lime); --d: var(--yellow); }
.pill.c { color: var(--c); } .pill.d { color: var(--d); }
.scores .c { color: var(--c); } .scores .d { color: var(--d); }
.msg.c { align-self: flex-start; background: rgba(182,255,59,.13); border: 1px solid rgba(182,255,59,.4); border-bottom-left-radius: 4px; }
.msg.d { align-self: flex-start; background: rgba(255,225,77,.13); border: 1px solid rgba(255,225,77,.4); border-bottom-left-radius: 4px; }
.mm-word.C { color: var(--c); border-color: rgba(182,255,59,.5); background: rgba(182,255,59,.08); }
.mm-word.D { color: var(--d); border-color: rgba(255,225,77,.5); background: rgba(255,225,77,.08); }
.avatar { display: inline-block; vertical-align: middle; flex: 0 0 auto; }

/* tab bar */
#main.with-tabs { padding-bottom: calc(88px + var(--safe-bottom)); }
#tabs {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; max-width: 540px; margin: 0 auto;
  /* Four now, not six. Friends, Me and Dev moved to the avatar menu in the
     top bar, which is what bought each remaining target its width back. */
  /* Edge to edge, no gutters. Four cells with margins around them read as
     four buttons sitting on a bar; four cells that touch each other and the
     screen edges read as the bar itself. */
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0;
  padding: 0 0 var(--safe-bottom);
  background: rgba(9, 9, 30, 0.96); backdrop-filter: blur(12px); border-top: 1px solid var(--line);
}
/* Four tabs across a phone leaves each one a wide, mostly-empty box. Each
   button now fills its whole cell — a tapped one is a solid pill rather than a
   small icon adrift in space — which is what makes the row read as full. */
#tabs button {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; padding: 12px 4px 13px; width: 100%; height: 100%; min-width: 0;
  border: 0; border-radius: 0; background: none;
  color: var(--muted); font-size: 11.5px; font-weight: 800; letter-spacing: .03em;
  transition: color var(--t-quick) var(--ease-out), background var(--t-quick) var(--ease-out);
}
/* hairline between cells, so four touching buttons still read as four */
#tabs button + button::before {
  content: ''; position: absolute; left: 0; top: 22%; bottom: 22%;
  width: 1px; background: rgba(255,255,255,.07);
}
#tabs button .ico { font-size: 22px; line-height: 1; transition: transform var(--t-move) var(--spring); }
#tabs button:active { background: rgba(255,255,255,.05); }
#tabs button.active {
  background: linear-gradient(180deg, rgba(255,207,92,.18), rgba(255,207,92,.02));
}
/* the lit cell gets a bar along its top edge, where the eye looks when the
   page below it changes */
#tabs button.active::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; width: auto;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
  box-shadow: 0 0 12px var(--gold);
}

.tab-badge { position: absolute; top: 2px; right: 14%; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; background: var(--pink); color: #fff; font-size: 10px; display: flex; align-items: center; justify-content: center; }
.coins { display: inline-flex; align-items: center; gap: 5px; padding: 5px 10px; border-radius: 999px; background: rgba(255,225,77,.12); border: 1px solid rgba(255,225,77,.45); color: var(--yellow); font-weight: 800; font-size: 13px; font-family: var(--head); }
.coins.big { font-size: 20px; padding: 8px 16px; }

/* banners (inbox) */
#banners { padding: 0 16px; display: flex; flex-direction: column; gap: 8px; }
#banners:not(:empty) { padding-top: 12px; }
.banner { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 14px; border: 1px solid rgba(182,255,59,.5); background: rgba(182,255,59,.08); font-size: 14px; animation: toastin .25s ease-out; }
.banner.invite { border-color: rgba(25,230,255,.55); background: rgba(25,230,255,.08); }
.banner.friend { border-color: rgba(255,61,154,.55); background: rgba(255,61,154,.08); }
.banner .grow { line-height: 1.3; }
.banner .btn.small { min-height: 36px; padding: 6px 12px; }

/* home */
.hero-card { display: flex; align-items: center; gap: 14px; padding: 14px; border-radius: var(--radius); background: var(--panel); border: 1px solid var(--line); }
.hero-card .name { font-family: var(--head); font-weight: 800; font-size: 18px; }
.hero-card .title { font-size: 12px; color: var(--yellow); letter-spacing: .06em; text-transform: uppercase; }
.hero-card .meta { font-size: 12px; color: var(--muted); margin-top: 4px; }
.segmented { display: flex; gap: 4px; padding: 4px; border-radius: 12px; background: rgba(5,5,20,.6); border: 1px solid var(--line); }
.segmented button { flex: 1; min-width: 0; min-height: 38px; border: none; border-radius: 9px; background: transparent; color: var(--muted); font-weight: 700; font-size: 14px; }
.segmented button.on { background: linear-gradient(135deg, var(--pink), var(--purple)); color: #fff; box-shadow: 0 0 12px rgba(255,61,154,.35); }
.segmented button:disabled { opacity: .3; }
.game-pick { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; scroll-snap-type: x mandatory; }
.game-pick .game-card { min-width: 132px; scroll-snap-align: start; min-height: 108px; }
.game-card.locked { opacity: .4; }
.game-card .cap { font-size: 11px; color: var(--muted); }
.mode-note { font-size: 12px; color: var(--muted); line-height: 1.4; }

/* how many people are on right now, under the Play online heading */
.online-now { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; color: var(--muted); margin: -4px 0 2px; }
.online-now b { color: var(--lime); font-size: 15px; }
.online-now small { color: var(--muted); opacity: .8; font-size: 12px; }
.online-now small::before { content: "·"; margin: 0 6px; }
.online-now .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--lime); box-shadow: 0 0 8px var(--lime); flex: 0 0 auto; animation: pulse-dot 2.4s ease-in-out infinite; }
@keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .online-now .dot { animation: none; } }
.searching { text-align: center; padding: 18px; }
.searching .spinner { width: 42px; height: 42px; margin: 0 auto 10px; border-radius: 50%; border: 4px solid rgba(255,255,255,.1); border-top-color: var(--cyan); animation: spin .9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.toggle { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 0; }
.switch { width: 48px; height: 28px; border-radius: 14px; background: #2a2850; position: relative; border: 1px solid var(--line); flex: 0 0 auto; }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #8d90c9; transition: transform .15s; }
.switch.on { background: rgba(182,255,59,.35); border-color: var(--lime); }
.switch.on::after { transform: translateX(20px); background: var(--lime); box-shadow: 0 0 8px var(--lime); }

/* friends */
.friend { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 14px; border: 1px solid var(--line); background: rgba(255,255,255,.03); }
.friend .fname { font-weight: 800; }
.friend .fsub { font-size: 12px; color: var(--muted); }
.friend .actions { display: flex; gap: 6px; }
.friend .btn.small { min-height: 34px; padding: 4px 10px; font-size: 13px; }

/* leaderboard */
.lb-row { display: grid; grid-template-columns: 34px 44px minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 12px; border: 1px solid transparent; }
.lb-row.me { border-color: var(--lime); background: rgba(182,255,59,.06); }
.lb-row .rank { font-family: var(--head); font-weight: 800; color: var(--muted); text-align: center; }
.lb-row:nth-child(1) .rank { color: var(--yellow); } .lb-row:nth-child(2) .rank { color: #d7d9ff; } .lb-row:nth-child(3) .rank { color: var(--orange); }
.lb-row .val { font-family: var(--head); font-weight: 800; color: var(--cyan); }

/* store */
.store-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
.item { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 10px 6px; border-radius: 14px; border: 1px solid var(--line); background: rgba(255,255,255,.03); text-align: center; }
.item .emoji { font-size: 30px; line-height: 1.1; }
.item .iname { font-size: 12px; font-weight: 700; line-height: 1.2; }
.item .price { font-size: 12px; color: var(--yellow); font-weight: 800; }
.item .btn.small { min-height: 30px; padding: 3px 10px; font-size: 12px; width: 100%; }
.item.owned { border-color: rgba(61,255,143,.5); }
.item.equipped { border-color: var(--lime); box-shadow: 0 0 12px rgba(182,255,59,.3); }
.item.premium { border-color: rgba(255,209,102,.6); background: rgba(255,209,102,.05); }
.packs { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
.pack { padding: 12px 8px; border-radius: 14px; border: 1px solid rgba(255,225,77,.45); background: rgba(255,225,77,.06); text-align: center; position: relative; }
.pack .amt { font-family: var(--head); font-weight: 900; font-size: 18px; color: var(--yellow); }
.pack .badge { position: absolute; top: -8px; left: 50%; transform: translateX(-50%); font-size: 10px; padding: 2px 8px; border-radius: 999px; background: var(--pink); color: #fff; font-weight: 800; white-space: nowrap; }

/* quests / daily */
.quest { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 14px; border: 1px solid var(--line); background: rgba(255,255,255,.03); }
.quest .bar { height: 6px; border-radius: 3px; background: rgba(255,255,255,.08); margin-top: 6px; overflow: hidden; }
.quest .bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--cyan), var(--lime)); }
.quest.done { border-color: var(--lime); }
.daily-days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.daily-days span { text-align: center; font-size: 11px; padding: 6px 2px; border-radius: 8px; background: rgba(255,255,255,.04); border: 1px solid transparent; color: var(--muted); }
.daily-days span.got { background: rgba(182,255,59,.15); border-color: var(--lime); color: var(--lime); }
.daily-days span.next { border-color: var(--yellow); color: var(--yellow); }

/* avatar editor */
.parts { display: flex; flex-wrap: wrap; gap: 8px; }
.part { width: 54px; height: 54px; border-radius: 14px; border: 1px solid var(--line); background: rgba(255,255,255,.04); display: flex; align-items: center; justify-content: center; font-size: 22px; position: relative; color: var(--text); }
.part.on { border-color: var(--lime); box-shadow: 0 0 10px rgba(182,255,59,.4); }
.part.lock { opacity: .5; }
.part .lk { position: absolute; bottom: 2px; right: 4px; font-size: 10px; }
.swatch { width: 100%; height: 100%; border-radius: 12px; }

/* room v2 */
.seats { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.seat { border-radius: 14px; padding: 10px; border: 1px solid var(--line); background: rgba(255,255,255,.03); display: flex; align-items: center; gap: 10px; min-height: 76px; }
.seat.A { border-color: rgba(255,61,154,.55); } .seat.B { border-color: rgba(25,230,255,.55); } .seat.C { border-color: rgba(182,255,59,.55); } .seat.D { border-color: rgba(255,225,77,.55); }
.seat .sname { font-weight: 800; font-size: 14px; display: flex; align-items: center; gap: 6px; }
.seat.A .sname { color: var(--a); } .seat.B .sname { color: var(--b); } .seat.C .sname { color: var(--c); } .seat.D .sname { color: var(--d); }
.seat .ssub { font-size: 11px; color: var(--muted); }
.seat .ready { color: var(--lime); font-weight: 800; font-size: 11px; }
.seat.empty { justify-content: center; border-style: dashed; color: var(--muted); font-size: 13px; flex-direction: column; gap: 6px; }
.seat .team-tag { font-size: 10px; letter-spacing: .1em; text-transform: uppercase; padding: 2px 6px; border-radius: 6px; background: rgba(255,255,255,.06); }
.team0 .team-tag { color: var(--a); } .team1 .team-tag { color: var(--b); }
.mode-badge { font-family: var(--head); font-size: 10px; letter-spacing: .16em; padding: 3px 8px; border-radius: 6px; border: 1px solid var(--line); color: var(--muted); }
.mode-badge.ranked { color: var(--yellow); border-color: rgba(255,225,77,.5); }
.mode-badge.public { color: var(--cyan); border-color: rgba(25,230,255,.5); }
.players-row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.pchip { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px 3px 3px; border-radius: 999px; border: 1px solid var(--line); background: rgba(255,255,255,.04); font-size: 12px; font-weight: 700; }
.pchip.turn { border-color: var(--lime); box-shadow: 0 0 10px rgba(182,255,59,.35); }
.pchip.A { color: var(--a); } .pchip.B { color: var(--b); } .pchip.C { color: var(--c); } .pchip.D { color: var(--d); }
.pchip .cnt { color: var(--text); font-family: var(--head); font-size: 12px; }
.rewards { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-top: 10px; }
.rewards span { font-size: 13px; padding: 4px 10px; border-radius: 999px; background: rgba(255,225,77,.12); border: 1px solid rgba(255,225,77,.4); color: var(--yellow); font-weight: 700; }

/* ---------- Ludo ---------- */
.ludo-wrap { display: flex; justify-content: center; }
.ludo { width: 100%; max-width: 440px; touch-action: manipulation; user-select: none; }
.ludo .cell { fill: #1a1840; stroke: #2c2a5e; stroke-width: 0.04; }
.ludo .cell.safe { fill: #2a2860; }
.ludo .base { stroke: none; }
.ludo .base.A { fill: rgba(255,61,154,.22); } .ludo .base.B { fill: rgba(25,230,255,.2); } .ludo .base.C { fill: rgba(182,255,59,.2); } .ludo .base.D { fill: rgba(255,225,77,.2); }
.ludo .home.A { fill: rgba(255,61,154,.35); } .ludo .home.B { fill: rgba(25,230,255,.35); } .ludo .home.C { fill: rgba(182,255,59,.35); } .ludo .home.D { fill: rgba(255,225,77,.35); }
.ludo .spot { fill: rgba(255,255,255,.08); stroke: rgba(255,255,255,.15); stroke-width: .05; }
.ludo .center { fill: #0d0c26; stroke: #3a3880; stroke-width: .06; }
.ludo .tok { stroke: #0b0a1f; stroke-width: .12; }
.ludo .tok.A { fill: var(--a); } .ludo .tok.B { fill: var(--b); } .ludo .tok.C { fill: var(--c); } .ludo .tok.D { fill: var(--d); }
.ludo .tok.can { stroke: #fff; stroke-width: .16; animation: tokpulse .9s ease-in-out infinite; cursor: pointer; }
@keyframes tokpulse { 50% { r: 0.46; } }
.ludo .star { font-size: 0.7px; fill: #d7d9ff; text-anchor: middle; dominant-baseline: central; pointer-events: none; }
.dice-row { display: flex; align-items: center; justify-content: center; gap: 14px; margin: 12px 0; }
.die { width: 58px; height: 58px; border-radius: 14px; background: #f4f4ff; color: #0b0a1f; display: grid; place-items: center; font-family: var(--head); font-weight: 900; font-size: 30px; box-shadow: 0 0 16px rgba(255,255,255,.4), inset 0 -4px 0 rgba(0,0,0,.2); }
.die.empty { background: rgba(255,255,255,.08); color: var(--muted); box-shadow: none; border: 1px dashed var(--line); }
.die.rolling { animation: shake .4s; }
.gamelog { font-size: 12px; color: var(--muted); text-align: center; min-height: 16px; }

/* ---------- Color Clash ---------- */
.cc-table { display: flex; flex-direction: column; gap: 10px; }
.cc-center { display: flex; align-items: center; justify-content: center; gap: 18px; padding: 10px 0; }
.card { width: 64px; height: 92px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-family: var(--head); font-weight: 900; font-size: 26px; color: #fff; border: 3px solid #fff; box-shadow: 0 6px 14px rgba(0,0,0,.45); position: relative; flex: 0 0 auto; text-shadow: 0 2px 0 rgba(0,0,0,.35); }
.card.small { width: 46px; height: 66px; font-size: 18px; border-width: 2px; }
.card.r { background: #ff3b3b; } .card.b { background: #2f6bff; } .card.g { background: #2ecc71; } .card.y { background: #ffcf2e; color: #3a3000; text-shadow: none; }
.card.w { background: conic-gradient(#ff3b3b 0 25%, #ffcf2e 0 50%, #2ecc71 0 75%, #2f6bff 0); }
.card.back { background: repeating-linear-gradient(135deg, #1a1a3a, #1a1a3a 6px, #2a2860 6px, #2a2860 12px); border-color: #a36bff; }
.card.playable { border-color: var(--lime); box-shadow: 0 0 16px rgba(182,255,59,.6), 0 6px 14px rgba(0,0,0,.45); transform: translateY(-8px); }
.card .corner { position: absolute; top: 4px; left: 6px; font-size: 11px; }
.hand { display: flex; gap: 8px; overflow-x: auto; padding: 12px 6px 6px; scroll-snap-type: x proximity; }
.hand .card { scroll-snap-align: center; }
.color-chip { width: 28px; height: 28px; border-radius: 50%; border: 2px solid #fff; }
.color-chip.r { background: #ff3b3b; } .color-chip.b { background: #2f6bff; } .color-chip.g { background: #2ecc71; } .color-chip.y { background: #ffcf2e; }
.wild-pick { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.wild-pick button { height: 70px; border-radius: 14px; border: 3px solid #fff; font-weight: 900; font-size: 16px; color: #fff; }
.deck-btn { display: flex; flex-direction: column; align-items: center; gap: 4px; background: none; border: none; color: var(--muted); font-size: 12px; }

/* ---------- Treasure ---------- */
.island { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 4px; padding: 8px; border-radius: 16px; background: linear-gradient(160deg, #123a2f, #0b2a24); border: 2px solid #2ee6c5; box-shadow: 0 0 22px rgba(46,230,197,.3); }
.tile { aspect-ratio: 1; border-radius: 8px; border: none; background: #1f6b52; color: #fff; font-weight: 900; font-size: 15px; display: flex; align-items: center; justify-content: center; box-shadow: inset 0 -3px 0 rgba(0,0,0,.3); font-family: var(--head); }
.tile.dug { background: #3b2a1a; box-shadow: inset 0 3px 6px rgba(0,0,0,.5); }
.tile.gold { background: #ffd166; color: #3a2a00; box-shadow: 0 0 12px rgba(255,209,102,.8); }
.tile.bomb { background: #ff4b5c; box-shadow: 0 0 12px rgba(255,75,92,.8); }
.tile.sonar { outline: 2px solid var(--cyan); }
.tile:disabled { opacity: .9; }
.tile.armed { outline: 2px dashed var(--cyan); }
.lives { font-size: 18px; letter-spacing: 2px; }

/* ---------- Sketch ---------- */
.sk-canvas-wrap { position: relative; width: 100%; aspect-ratio: 1; max-width: 100%; border-radius: 16px; overflow: hidden; border: 2px solid var(--purple); background: #fff; touch-action: none; }
.sk-canvas-wrap canvas { width: 100%; height: 100%; display: block; }
.sk-tools { display: flex; gap: 6px; align-items: center; margin-top: 8px; overflow-x: auto; padding-bottom: 4px; }
.sk-tools .sw { width: 30px; height: 30px; border-radius: 50%; border: 2px solid transparent; flex: 0 0 auto; }
.sk-tools .sw.on { border-color: #fff; box-shadow: 0 0 8px #fff; }
.sk-tools .bw { width: 34px; height: 34px; border-radius: 10px; border: 1px solid var(--line); background: rgba(255,255,255,.05); display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.sk-tools .bw.on { border-color: var(--lime); }
.sk-tools .bw i { display: block; border-radius: 50%; background: #fff; }
.sk-hint { font-family: var(--head); letter-spacing: .3em; font-size: 22px; text-align: center; color: var(--yellow); text-shadow: 0 0 12px rgba(255,225,77,.5); margin: 8px 0; }
.sk-word { font-family: var(--head); font-size: 20px; text-align: center; color: var(--lime); margin: 8px 0; }
.sk-timer { font-family: var(--head); font-weight: 900; font-size: 22px; color: var(--cyan); }
.sk-feed { display: flex; flex-direction: column; gap: 4px; max-height: 120px; overflow-y: auto; font-size: 13px; }
.sk-feed .g { padding: 4px 8px; border-radius: 8px; background: rgba(255,255,255,.04); }
.sk-feed .g.hit { color: var(--lime); font-weight: 700; }
.sk-feed .g.close { color: var(--yellow); }
.choices { display: grid; gap: 8px; }

/* bottom sheet */
#sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 26; max-width: 540px; margin: 0 auto; max-height: 80dvh; overflow-y: auto; background: rgba(13,12,42,.98); border: 1px solid var(--line); border-bottom: none; border-radius: 22px 22px 0 0; box-shadow: 0 -12px 40px rgba(0,0,0,.5); padding: 18px 16px calc(18px + var(--safe-bottom)); animation: sheetin .22s ease-out; }
#sheet h2 { margin-bottom: 4px; }

.code-form.plain input { text-transform: none; letter-spacing: normal; font-family: var(--body); font-weight: 500; text-align: left; }

/* rename field */
.name-status { font-size: 12px; color: var(--muted); line-height: 1.4; min-height: 16px; }
.name-status.ok { color: var(--lime); font-weight: 700; }
.name-status.bad { color: var(--red); font-weight: 700; }

/* long names (up to 32 chars) must not blow out compact layouts */
.hero-card .name, .friend .fname, .seat .sname, .lb-row > div > div:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hero-card > .grow, .friend .grow, .seat .grow, .lb-row > div { min-width: 0; }
.pchip { max-width: 46vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scores span { max-width: 30vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-item .pchip { max-width: 38vw; }
.mm-word { overflow-wrap: anywhere; }

/* =========================================================================
   v3 — six tabs, gems, tiers, crates, pets, DMs and the new games
   ========================================================================= */

/* The six-tab cell override lived here and outlived the six tabs — it was
   still forcing a six-column grid onto a four-tab bar, which is why each cell
   was 65px wide on a 390px phone instead of 97. The bar is sized once, up in
   the nav block, and nowhere else. */

/* wallet */
.coins.gems { background: rgba(163,107,255,.14); border-color: rgba(163,107,255,.5); color: #cbb1ff; }
.wallet { display: flex; flex-direction: column; gap: 4px; align-items: flex-end; flex: 0 0 auto; }
#top .coins { padding: 4px 8px; font-size: 12px; }

/* ranked tiers */
.tier-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 999px; font-family: var(--head); font-weight: 800; font-size: 11px; color: var(--tc, var(--text)); background: color-mix(in srgb, var(--tc, #fff) 14%, transparent); border: 1px solid color-mix(in srgb, var(--tc, #fff) 45%, transparent); }
.tier-badge.big { font-size: 15px; padding: 5px 12px; margin-top: 4px; }
.tier-bar { height: 8px; border-radius: 999px; background: rgba(255,255,255,.08); overflow: hidden; margin: 8px 0 4px; }
.tier-bar i { display: block; height: 100%; border-radius: 999px; transition: width .4s ease; }
.tier-bar.legend i { background: linear-gradient(90deg, var(--orange), var(--yellow), var(--pink)); }
.tier-card .big-rating { font-family: var(--head); font-weight: 900; font-size: 30px; color: var(--cyan); }
.ladder { display: flex; flex-direction: column; gap: 3px; max-height: 320px; overflow-y: auto; }
.ladder-row { display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-radius: 10px; font-size: 13px; border: 1px solid transparent; }
.ladder-row .e { width: 22px; text-align: center; }
.ladder-row .grow { color: var(--tc); font-weight: 700; }
.ladder-row.me { border-color: var(--tc); background: color-mix(in srgb, var(--tc) 12%, transparent); }
.ladder-row.legend { background: rgba(255,159,67,.08); }

/* tap a name anywhere to see who they are */
.who { background: none; border: 0; padding: 0; font: inherit; color: inherit; text-align: left; border-bottom: 1px dotted rgba(255,255,255,.28); }
.lb-row[data-act="who"] { cursor: pointer; }
.who-head { display: flex; gap: 14px; align-items: center; margin: 8px 0 4px; }
.who-head .grow { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.who-title { font-family: var(--head); font-weight: 800; font-size: 13px; color: var(--yellow); }
.who-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 12px; }
.who-games { list-style: none; padding: 0; margin: 0 0 14px; display: grid; gap: 4px; }
.who-games li { display: flex; align-items: center; gap: 9px; font-size: 13px; padding: 6px 9px; border-radius: 9px; background: rgba(255,255,255,.03); }
.who-games em { font-style: normal; font-size: 12px; color: var(--muted); }

/* gem-exclusive items */
.item { position: relative; }
.gem-only { position: absolute; top: 6px; left: 50%; transform: translateX(-50%); white-space: nowrap; font-size: 9px; font-weight: 800; letter-spacing: .04em; padding: 2px 7px; border-radius: 999px; background: linear-gradient(135deg, var(--cyan), var(--purple)); color: #080820; }
.item.r-legendary .gem-only { box-shadow: 0 0 10px rgba(25,230,255,.5); }

/* the weekly hatchery line-up */
.hatch-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
.hatch-card { display: flex; flex-direction: column; gap: 6px; padding: 10px; border-radius: 14px; border: 1px solid color-mix(in srgb, var(--rc, #fff) 45%, transparent); background: color-mix(in srgb, var(--rc, #fff) 8%, rgba(255,255,255,.02)); }
.hatch-card .hemoji { font-size: 28px; line-height: 1; }
.hatch-card b { font-size: 14px; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hatch-card .fac-tag { font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.hatch-card .row { min-width: 0; }
.hatch-card .grow { min-width: 0; }
.hatch-card .btn { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hatch-card .rarity { font-size: 11px; font-weight: 800; letter-spacing: .04em; }
.hstats { display: flex; flex-wrap: wrap; gap: 3px 8px; font-size: 11px; color: var(--muted); min-width: 0; }
.hstats span { white-space: nowrap; }
/* which week's set you're looking at */
.wheel-week { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 4px 10px; font-size: 12px; color: var(--cyan); padding: 7px 10px; border-radius: 10px; background: rgba(25,230,255,.07); border: 1px solid rgba(25,230,255,.18); }
.wheel-week .muted { color: var(--muted); }
.board-left small { display: block; font-size: 11px; color: var(--muted); }

/* prize wheels */
.wheel-wrap { position: relative; display: flex; justify-content: center; padding: 4px 0 2px; }
.wheel-svg { width: min(100%, 290px); height: auto; }
.wheel-rotor { transform-origin: 128px 128px; transform: rotate(var(--spin, 0deg));
  /* Long, fast start, and a slow crawl over the last few degrees — the crawl
     is the whole feeling of a wheel, so it gets most of the duration. */
  transition: transform 3.6s cubic-bezier(.12, .78, .12, 1); }
.wheel-wrap.spinning .wheel-svg { filter: drop-shadow(0 0 18px rgba(163,107,255,.5)); }
.wheel-wrap.spinning .slice text { opacity: .35; }
/* The slice that won, once it has stopped under the pin. */
.slice.landed path { fill-opacity: .95 !important; }
.slice.landed { animation: sliceWin 1.5s ease-out 2; transform-origin: 128px 128px; }
@keyframes sliceWin { 0%, 100% { filter: none; } 45% { filter: brightness(1.7) drop-shadow(0 0 10px #fff); } }
.wheel-wrap::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: 50%; opacity: 0; transition: opacity .4s ease; }
.wheel-wrap.won::after { opacity: 1; box-shadow: 0 0 60px 10px rgba(255,225,77,.35) inset; }
@media (prefers-reduced-motion: reduce) {
  .wheel-rotor { transition: none; }
  .slice.landed { animation: none; }
  .wheel-wrap.spinning .slice text { opacity: 1; }
}
.wheel-pin { position: absolute; top: -2px; left: 50%; transform: translateX(-50%); font-size: 22px; color: var(--lime); filter: drop-shadow(0 0 8px var(--lime)); z-index: 2; line-height: 1; }
.wheel-wrap.spinning .wheel-pin { animation: pin-tick .12s ease-in-out infinite; }
@keyframes pin-tick { 0%, 100% { transform: translateX(-50%) rotate(-7deg); } 50% { transform: translateX(-50%) rotate(7deg); } }
.slice[data-act] { cursor: pointer; }
.slice[data-act]:hover path { fill-opacity: .78; }
.slice[data-act]:active path { fill-opacity: .9; }
.slice.claimed text { filter: grayscale(1); }
.board-bar { display: flex; justify-content: space-between; font-size: 12px; color: var(--lime); }
.board-bar .muted { color: var(--muted); }
.board-left { list-style: none; padding: 0; margin: 8px 0 0; display: grid; gap: 4px; }
.board-left li { display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 5px 8px; border-radius: 9px; background: rgba(255,255,255,.03); border-left: 3px solid var(--rc, #fff); }
.board-left em { font-style: normal; font-size: 11px; color: var(--rc, var(--muted)); font-weight: 800; }
.item.r-legendary, .item.r-epic, .item.r-rare { border-color: color-mix(in srgb, var(--rc) 55%, transparent); }
.item .rarity { font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.pack .bonus { font-size: 11px; color: var(--lime); font-weight: 700; }

.crate-reveal { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 26px 14px; border-radius: 18px; border: 1px solid color-mix(in srgb, var(--rc, #fff) 50%, transparent); background: radial-gradient(circle at 50% 35%, color-mix(in srgb, var(--rc, #fff) 18%, transparent), transparent 70%); margin: 10px 0; }
.crate-reveal .emoji { font-size: 64px; filter: drop-shadow(0 0 18px var(--rc, #fff)); }
.crate-reveal.spin .emoji { animation: crateshake .35s ease-in-out infinite; }
.crate-reveal .rname { font-family: var(--head); font-weight: 900; letter-spacing: .18em; font-size: 13px; }
.crate-reveal .iname { font-family: var(--head); font-weight: 800; font-size: 20px; }
.crate-reveal .lime { color: var(--lime); }
@keyframes crateshake { 0%,100% { transform: rotate(-8deg) scale(1); } 50% { transform: rotate(8deg) scale(1.08); } }

/* pets */
.pet-emoji { font-size: 30px; line-height: 1; }
.pet-emoji.xl { font-size: 48px; }
.pet-egg { line-height: 1; }
.pet-egg.xl { font-size: 62px; }
/* A drawn pet. The span is the layout box; the svg inside fills it, so the
   grid never has to know a pet is a drawing rather than a glyph. */
.pet-pic { display: inline-block; flex: none; line-height: 0; }
/* `overflow: visible` lets the drawing paint outside its box, and anything
   painted outside the box still counts toward the page's scroll width — which
   is how a 52px pet icon pushed a phone 40px sideways. Nothing in the artwork
   leaves the viewBox, so clipping costs nothing. */
.pet-pic svg { display: block; width: 100%; height: 100%; overflow: hidden; }
.pet-pic.breathe { animation: petBreathe 3.2s ease-in-out infinite; }
.pet-pic.bounce { animation: petBounce 1.1s ease-in-out infinite; }
@keyframes petBreathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.045); } }
@keyframes petBounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7%); } }
.pet-sheet { display: flex; flex-direction: column; align-items: center; gap: 4px; margin: 4px 0 10px; }
.egg-big { font-size: 40px; }
.pet-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
.pet-tile { padding: 10px; border-radius: 14px; border: 1px solid color-mix(in srgb, var(--rc, #fff) 45%, transparent); background: rgba(255,255,255,.03); display: flex; flex-direction: column; gap: 6px; }
.pet-tile.active { box-shadow: 0 0 0 1px var(--lime) inset; }
.pet-tile .pname { font-weight: 800; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pet-tile .pw { font-family: var(--head); font-weight: 800; color: var(--cyan); font-size: 13px; }
.pet-tile .btn.small { min-height: 28px; font-size: 11px; padding: 2px 8px; flex: 1; }
.pet-stats { display: flex; gap: 8px; font-size: 11px; color: var(--muted); flex-wrap: wrap; }
.pet-stats.big { font-size: 15px; justify-content: space-between; margin: 8px 0; }
.xpbar { height: 5px; border-radius: 999px; background: rgba(255,255,255,.08); overflow: hidden; }
.xpbar i { display: block; height: 100%; background: var(--cyan); }
#petname-form { margin-top: 6px; }

/* me — stat grid */
.stat-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.stat { padding: 10px 6px; border-radius: 12px; background: rgba(255,255,255,.03); border: 1px solid var(--line); text-align: center; }
.stat .v { font-family: var(--head); font-weight: 800; font-size: 19px; color: var(--cyan); }
.stat .l { font-size: 11px; color: var(--muted); margin-top: 2px; }
.stat .s { font-size: 10px; color: var(--muted); opacity: .75; }
.game-stat { display: flex; align-items: center; gap: 10px; }
.game-stat .gi { font-size: 20px; width: 24px; text-align: center; }
.game-stat .bar { height: 5px; border-radius: 999px; background: rgba(255,255,255,.08); overflow: hidden; margin-top: 4px; }
.game-stat .bar i { display: block; height: 100%; background: var(--lime); }

/* direct messages */
.dm-btn { position: relative; }
.dm-count { position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; background: var(--pink); color: #fff; font-size: 10px; display: flex; align-items: center; justify-content: center; }
.dm-peek { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; }
.dm-list { display: flex; flex-direction: column; gap: 6px; max-height: 46dvh; overflow-y: auto; padding: 8px 0; }
.dm-list .msg { max-width: 82%; padding: 8px 12px; border-radius: 14px; background: rgba(255,255,255,.06); align-self: flex-start; font-size: 14px; line-height: 1.35; overflow-wrap: anywhere; }
.dm-list .msg.me { align-self: flex-end; background: linear-gradient(135deg, rgba(255,61,154,.35), rgba(163,107,255,.35)); }
.dm-list .msg.sys { align-self: center; background: none; color: var(--muted); font-size: 13px; }
.dm-list .msg .when { display: block; font-size: 10px; color: var(--muted); margin-top: 3px; }
#dm-form { display: flex; gap: 8px; margin-top: 6px; }
#dm-form input { flex: 1; min-width: 0; }
.sheet-head.plain { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.small-seg button { font-size: 12px; min-height: 34px; }

/* round / hand summaries shared by the new games */
.round-panel { margin-top: 12px; padding: 14px; border-radius: 16px; border: 1px solid var(--line); background: rgba(5,5,20,.7); text-align: center; display: flex; flex-direction: column; gap: 8px; }
.round-panel .big { font-family: var(--head); font-weight: 800; font-size: 19px; }
.reveal-rows { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.reveal-rows > div { display: flex; justify-content: space-between; gap: 10px; padding: 4px 8px; border-radius: 8px; background: rgba(255,255,255,.04); }
.reveal-rows .good { color: var(--lime); font-weight: 800; }
.reveal-rows .bad { color: var(--red); font-weight: 800; }

/* dominoes */
svg.dom rect { fill: #f4f2ff; stroke: #2a2a55; stroke-width: 1.5; }
svg.dom line { stroke: #2a2a55; stroke-width: 1.5; }
svg.dom circle { fill: #1b1b3d; }
.dom-line { display: flex; align-items: center; gap: 3px; overflow-x: auto; padding: 10px 6px; border-radius: 14px; background: rgba(5,5,20,.55); border: 1px solid var(--line); min-height: 56px; }
.dom-laid { flex: 0 0 auto; }
.dom-ends { text-align: center; font-size: 12px; color: var(--muted); margin: 6px 0; }
.dom-hand { display: flex; gap: 6px; overflow-x: auto; padding: 6px 2px; }
.dom-tile { flex: 0 0 auto; background: none; border: 2px solid transparent; border-radius: 8px; padding: 2px; opacity: .55; }
.dom-tile.can { opacity: 1; border-color: var(--lime); box-shadow: 0 0 12px rgba(182,255,59,.25); }

/* playing cards */
.pcard { width: 42px; height: 60px; flex: 0 0 auto; border-radius: 7px; background: #f6f5ff; border: 1px solid #2a2a55; color: #14142e; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0; font-weight: 800; padding: 0; }
.pcard.red { color: #c0224a; }
.pcard .r { font-size: 16px; line-height: 1; }
.pcard .s { font-size: 15px; line-height: 1; }
.pcard.dim { opacity: .42; }
.pcard.back { background: repeating-linear-gradient(45deg, #38386e, #38386e 4px, #2a2a55 4px, #2a2a55 8px); }
.hand-row { display: flex; gap: 4px; overflow-x: auto; padding: 8px 2px; }
.spades-mid { min-height: 92px; display: flex; align-items: center; justify-content: center; }
.trick { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
.trick.faded { opacity: .5; }
.trick .tk { display: flex; flex-direction: column; align-items: center; gap: 3px; font-size: 10px; }
.trick .won { width: 100%; text-align: center; font-size: 12px; color: var(--lime); }
.bid-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 5px; margin: 8px 0; }
.bid-grid .btn.small { min-height: 36px; padding: 2px; font-size: 13px; }
.pchip.t0 { border-color: rgba(255,61,154,.5); }
.pchip.t1 { border-color: rgba(25,230,255,.5); }

/* liar's dice */
.die { font-size: 34px; line-height: 1; }
.die.hit { color: var(--lime); text-shadow: 0 0 10px rgba(182,255,59,.6); }
.my-dice { display: flex; gap: 6px; justify-content: center; padding: 10px; border-radius: 14px; background: rgba(5,5,20,.55); border: 1px solid var(--line); }
.bid-now { text-align: center; font-size: 15px; margin: 10px 0; }
.bid-box { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.stepper { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px; border-radius: 12px; background: rgba(5,5,20,.6); border: 1px solid var(--line); }
.stepper button { width: 46px; height: 40px; border-radius: 10px; border: 1px solid var(--line); background: rgba(255,255,255,.06); color: var(--text); font-size: 22px; font-weight: 800; }
.stepper span { display: flex; flex-direction: column; align-items: center; font-family: var(--head); font-size: 22px; font-weight: 800; }
.stepper small { font-family: var(--body); font-size: 10px; color: var(--muted); letter-spacing: .1em; text-transform: uppercase; font-weight: 600; }

/* checkers */
.ck-board { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 0; width: min(92vw, 420px); margin: 10px auto; border-radius: 12px; overflow: hidden; border: 2px solid var(--line); }
.ck-sq { aspect-ratio: 1; border: none; padding: 0; display: flex; align-items: center; justify-content: center; position: relative; }
.ck-sq.light { background: #d9d5f2; }
.ck-sq.dark { background: #4a3f78; }
.ck-sq.last { box-shadow: inset 0 0 0 2px rgba(255,225,77,.75); }
.ck-sq.sel { box-shadow: inset 0 0 0 3px var(--lime); }
.ck-sq.target { box-shadow: inset 0 0 0 3px var(--cyan); }
.ck-p { width: 74%; aspect-ratio: 1; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 15px; color: rgba(0,0,0,.55); }
.ck-p.a { background: radial-gradient(circle at 35% 30%, #ff86c0, #d41c72); box-shadow: 0 2px 0 rgba(0,0,0,.35); }
.ck-p.b { background: radial-gradient(circle at 35% 30%, #7fe9ff, #0f9ec0); box-shadow: 0 2px 0 rgba(0,0,0,.35); }
.ck-p.king { box-shadow: 0 2px 0 rgba(0,0,0,.35), 0 0 12px rgba(255,225,77,.8); }
.ck-dot { width: 26%; aspect-ratio: 1; border-radius: 50%; background: var(--cyan); opacity: .8; }

/* pet arena */
.arena { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
.vs-mark { text-align: center; font-family: var(--head); font-weight: 900; color: var(--muted); letter-spacing: .2em; font-size: 12px; }
.pet-card { padding: 10px 12px; border-radius: 14px; border: 1px solid var(--line); background: rgba(255,255,255,.03); }
.pet-top { display: flex; align-items: center; gap: 10px; }
.pet-card .pname { font-weight: 800; }
.hpbar { height: 10px; border-radius: 999px; background: rgba(255,255,255,.1); overflow: hidden; margin: 4px 0 3px; }
.hpbar i { display: block; height: 100%; background: linear-gradient(90deg, var(--lime), #7ee36a); transition: width .35s ease; }
.hpbar.low i { background: linear-gradient(90deg, var(--red), var(--orange)); }
.pet-log { margin-top: 10px; display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--muted); max-height: 96px; overflow-y: auto; }

@media (max-width: 380px) {
  .store-grid, .packs { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .stat-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .pet-grid { grid-template-columns: minmax(0, 1fr); }
  .pcard { width: 36px; height: 52px; }
  .bid-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

/* =========================================================================
   v4 — full-body avatars, bots, the dev menu and seven more games
   ========================================================================= */

/* the tab bar grows a seventh cell for admins */
/* .has-dev is gone: the dev menu is a row in the avatar menu now, so the bar
   never grows a seventh column and never shrinks its labels to fit one. */

/* avatars */
.avatar.full { display: block; }
.hero-card.tall { align-items: flex-start; }
.hero-card.tall .avatar.full { margin-top: -4px; }
.avatar-stage { padding: 8px 0 4px; }
.parts .part .lbl { font-size: 10px; line-height: 1.1; text-transform: capitalize; color: var(--muted); }
.parts .part .ico { font-size: 20px; line-height: 1; }
.parts.wide { display: grid; grid-template-columns: repeat(auto-fill, minmax(74px, 1fr)); gap: 6px; }
.parts.wide .part { width: auto; height: 62px; flex-direction: column; gap: 2px; padding: 4px; }
.parts.wide .part .lbl { white-space: normal; text-align: center; overflow: hidden; }

/* bots */
.bot-tag { font-size: 9px; font-weight: 800; letter-spacing: .1em; padding: 1px 5px; border-radius: 5px; background: rgba(25,230,255,.16); border: 1px solid rgba(25,230,255,.45); color: var(--cyan); vertical-align: middle; }
.seat.isbot { border-style: dashed; }

/* dev menu */
.dev-badge { font-family: var(--head); font-weight: 800; font-size: 12px; letter-spacing: .12em; padding: 4px 10px; border-radius: 8px; background: rgba(255,159,67,.16); border: 1px solid rgba(255,159,67,.5); color: var(--orange); }
.dev-head { border-color: rgba(255,159,67,.35); }
.dev-row { display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 10px; border-radius: 10px; border: 1px solid var(--line); background: rgba(255,255,255,.03); color: var(--text); text-align: left; font-size: 13px; }
.dev-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
.dev-grid label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); }
.dev-num { width: 100%; min-height: 36px; border-radius: 9px; border: 1px solid var(--line); background: rgba(5,5,20,.6); color: var(--text); padding: 0 8px; font-size: 14px; }
.dev-grid .btn.small { min-height: 30px; font-size: 12px; padding: 2px 8px; }
.dev-give { display: flex; flex-wrap: wrap; gap: 6px; }
.dev-give .btn.small { min-height: 32px; font-size: 12px; padding: 2px 10px; flex: 0 0 auto; }
.dev-items { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 5px; max-height: 260px; overflow-y: auto; margin-top: 8px; }
.dev-item { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-radius: 9px; border: 1px solid var(--line); background: rgba(255,255,255,.03); color: var(--text); font-size: 12px; text-align: left; }
.dev-item.has { border-color: var(--lime); color: var(--lime); }
.dev-audit { display: flex; flex-direction: column; gap: 4px; font-size: 12px; max-height: 220px; overflow-y: auto; }

/* Reversi */
.rv-board { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); width: min(92vw, 400px); margin: 10px auto; border-radius: 12px; overflow: hidden; border: 2px solid var(--line); background: #1f6b46; }
.rv-sq { aspect-ratio: 1; border: 1px solid rgba(0,0,0,.35); background: #2a8459; display: flex; align-items: center; justify-content: center; padding: 0; }
.rv-sq.can { background: #35a06c; }
.rv-sq.last { box-shadow: inset 0 0 0 2px var(--yellow); }
.rv-d { width: 78%; aspect-ratio: 1; border-radius: 50%; box-shadow: 0 2px 0 rgba(0,0,0,.35); }
.rv-d.a { background: radial-gradient(circle at 35% 30%, #ff86c0, #d41c72); }
.rv-d.b { background: radial-gradient(circle at 35% 30%, #7fe9ff, #0f9ec0); }
.rv-hint { font-size: 11px; font-weight: 800; color: rgba(255,255,255,.75); }

/* Battleship */
.bs-grid { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 2px; width: min(92vw, 360px); margin: 6px auto; }
.bs-sq { aspect-ratio: 1; border-radius: 4px; border: 1px solid rgba(255,255,255,.08); background: rgba(25,60,120,.5); display: flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 800; color: #fff; padding: 0; }
.bs-sq.small { border-radius: 3px; }
.bs-sq.ship { background: #6a7099; }
.bs-sq.hit { background: var(--red); }
.bs-sq.miss { background: rgba(255,255,255,.12); color: var(--muted); }
.bs-sq.target:not([disabled]):active { background: var(--cyan); }
.bs-head { text-align: center; font-family: var(--head); font-size: 13px; letter-spacing: .12em; color: var(--muted); margin-top: 10px; }
.bs-head.small { font-size: 11px; }
.fleet-key { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; font-size: 11px; color: var(--muted); margin-top: 6px; }
.fleet-key .sunk { opacity: .5; }
.bs-last { text-align: center; margin: 8px 0; font-weight: 700; font-size: 14px; }
.bs-last.hit { color: var(--red); }
.bs-last.miss { color: var(--muted); }

/* Dice Yacht */
.ydice { display: flex; gap: 8px; justify-content: center; margin: 10px 0; }
.yd { width: 52px; height: 58px; border-radius: 12px; border: 2px solid var(--line); background: rgba(255,255,255,.05); font-size: 34px; line-height: 1; color: var(--text); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 0; }
.yd.held { border-color: var(--lime); background: rgba(182,255,59,.12); }
.yd .hold-tag { font-size: 9px; letter-spacing: .1em; color: var(--lime); height: 10px; }
.ycard-wrap { overflow-x: auto; margin-top: 10px; }
.ycard { width: 100%; border-collapse: collapse; font-size: 12px; }
.ycard th, .ycard td { padding: 4px 6px; border-bottom: 1px solid var(--line); text-align: center; }
.ycard th:first-child { text-align: left; font-weight: 700; }
.ycard th small { display: block; font-weight: 500; color: var(--muted); font-size: 10px; }
.ycard tr.upper th:first-child { color: var(--cyan); }
.ycard td.me { background: rgba(163,107,255,.1); }
.ycard td.filled { font-weight: 800; }
.ycard .pick { width: 100%; min-height: 26px; border-radius: 7px; border: 1px solid var(--lime); background: rgba(182,255,59,.14); color: var(--lime); font-weight: 800; }
.ycard tr.sum th, .ycard tr.sum td { border-top: 2px solid var(--line); font-size: 13px; }

/* Word Duel */
.wd-head { text-align: center; font-family: var(--head); letter-spacing: .1em; font-size: 14px; margin: 6px 0; }
.wd-board { display: flex; flex-direction: column; gap: 4px; align-items: center; }
.wd-row { display: flex; gap: 4px; }
.wd-t { width: 42px; height: 42px; border-radius: 7px; border: 2px solid var(--line); display: flex; align-items: center; justify-content: center; font-family: var(--head); font-weight: 800; font-size: 20px; }
.wd-t.green { background: #3ba55d; border-color: #3ba55d; color: #fff; }
.wd-t.yellow { background: #c9a227; border-color: #c9a227; color: #fff; }
.wd-t.grey { background: #3a3a56; border-color: #3a3a56; color: #d7d9ff; }
.wd-typed { text-align: center; font-family: var(--head); font-size: 20px; letter-spacing: .3em; min-height: 26px; color: var(--cyan); margin: 8px 0; }
.wd-keys { display: flex; flex-direction: column; gap: 5px; align-items: center; }
.wd-krow { display: flex; gap: 4px; }
.wd-k { min-width: 28px; height: 42px; padding: 0 4px; border-radius: 6px; border: 1px solid var(--line); background: rgba(255,255,255,.08); color: var(--text); font-weight: 700; font-size: 13px; }
.wd-k.wide { min-width: 48px; font-size: 11px; }
.wd-k.green { background: #3ba55d; color: #fff; }
.wd-k.yellow { background: #c9a227; color: #fff; }
.wd-k.grey { background: #24243a; color: #6f719c; }
.wd-others { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.wd-other { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.wd-mini { display: inline-flex; gap: 1px; }
.wd-mini i { width: 6px; height: 6px; border-radius: 1px; background: #3a3a56; }
.wd-mini i.green { background: #3ba55d; }
.wd-mini i.yellow { background: #c9a227; }

/* Memory Match */
.mm-board { display: grid; gap: 6px; width: min(94vw, 420px); margin: 10px auto; }
.mm-card { aspect-ratio: 3/4; border-radius: 10px; border: 2px solid var(--line); background: linear-gradient(135deg, rgba(163,107,255,.3), rgba(25,230,255,.2)); display: flex; align-items: center; justify-content: center; font-size: 26px; padding: 0; transition: transform .15s; }
.mm-card.up { background: rgba(255,255,255,.08); border-color: var(--cyan); }
.mm-card.just { box-shadow: 0 0 0 2px var(--yellow); }
.mm-card.taken { opacity: .45; border-style: dashed; }
.mm-card.taken.a { border-color: var(--pink); }
.mm-card.taken.b { border-color: var(--cyan); }
.mm-card.taken.c { border-color: var(--lime); }
.mm-card.taken.d { border-color: var(--yellow); }
.mm-card:not(.up) .mm-face { opacity: .35; font-size: 20px; }

/* Ultimate Tic-Tac-Toe */
.ut-board { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; width: min(94vw, 400px); margin: 10px auto; }
.ut-b { position: relative; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2px; padding: 3px; border-radius: 8px; border: 1px solid var(--line); background: rgba(5,5,20,.5); }
.ut-b.target { border-color: var(--lime); box-shadow: 0 0 10px rgba(182,255,59,.28); }
.ut-b.won { opacity: .85; }
.ut-b.bigwin { box-shadow: 0 0 0 2px var(--yellow); }
.ut-c { aspect-ratio: 1; border-radius: 4px; border: none; background: rgba(255,255,255,.05); color: var(--text); font-size: 14px; font-weight: 800; padding: 0; }
.ut-c.a { color: var(--pink); }
.ut-c.b { color: var(--cyan); }
.ut-c.can { background: rgba(182,255,59,.16); }
.ut-c.last { box-shadow: inset 0 0 0 1.5px var(--yellow); }
.ut-big { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 46px; font-weight: 900; pointer-events: none; }
.ut-big.a { color: rgba(255,61,154,.75); }
.ut-big.b { color: rgba(25,230,255,.75); }
.ut-big.drawn { color: rgba(154,157,208,.5); }

/* Code Breaker */
.cb-head { text-align: center; font-family: var(--head); letter-spacing: .1em; font-size: 13px; color: var(--muted); margin: 6px 0 10px; }
.cb-history { display: flex; flex-direction: column; gap: 4px; max-height: 42dvh; overflow-y: auto; }
.cb-row { display: grid; grid-template-columns: 22px auto minmax(0, 1fr) auto; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 9px; background: rgba(255,255,255,.04); font-size: 12px; }
.cb-n { color: var(--muted); font-weight: 800; }
.cb-pegs { display: inline-flex; gap: 4px; }
.cb-pegs i { width: 16px; height: 16px; border-radius: 50%; border: 1px solid rgba(0,0,0,.4); }
.cb-fb .exact { color: var(--lime); }
.cb-fb .near { color: var(--yellow); }
.cb-by { color: var(--muted); font-size: 11px; }
.cb-entry { margin-top: 12px; display: flex; flex-direction: column; gap: 10px; align-items: center; }
.cb-slots { display: flex; gap: 8px; }
.cb-slot { width: 44px; height: 44px; border-radius: 50%; border: 2px dashed var(--line); background: rgba(255,255,255,.04); padding: 0; }
.cb-slot.set { border-style: solid; border-color: rgba(255,255,255,.4); }
.cb-palette { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.cb-p { width: 40px; height: 40px; border-radius: 50%; border: 2px solid rgba(255,255,255,.25); padding: 0; }
.cb-p:disabled { opacity: .35; }
.cb-answer { text-align: center; margin-top: 12px; display: flex; align-items: center; gap: 8px; justify-content: center; }

@media (max-width: 380px) {
  .dev-grid, .dev-items { grid-template-columns: minmax(0, 1fr); }
  .wd-t { width: 36px; height: 36px; font-size: 17px; }
  .wd-k { min-width: 25px; height: 38px; font-size: 12px; }
  .yd { width: 44px; height: 50px; font-size: 28px; }
}

/* link out to the public guide pages (where the ads live) */
.guides-link { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: var(--radius); border: 1px solid var(--line); background: var(--panel); text-decoration: none; color: var(--text); }
.guides-link .gi { font-size: 26px; }
.guides-link .grow { display: flex; flex-direction: column; min-width: 0; }
.guides-link b { font-size: 15px; }
.guides-link small { color: var(--muted); font-size: 12px; }

/* ---------- ads ---------- */
/* Every ad on the site is labelled. A player who cannot tell an ad from the
   game has been tricked, and a kid-facing site cannot afford that. */
.ad-tag { font-family: var(--head); font-size: 10px; letter-spacing: .18em; text-transform: uppercase; color: var(--muted); border: 1px solid var(--line); border-radius: 6px; padding: 1px 6px; }

.ad-slot { position: relative; margin: 2px 0; padding: 18px 8px 8px; border-radius: 14px; background: rgba(255,255,255,.02); border: 1px solid var(--line); min-height: 60px; overflow: hidden; }
.ad-slot > .ad-tag { position: absolute; top: 6px; left: 8px; }
.ad-slot ins { display: block; width: 100%; }

/* the rewarded-ad button carries its own sub-label, because "why not" is the
   only question a disabled button ever raises */
.ad-btn { display: flex; flex-direction: column; align-items: center; gap: 1px; line-height: 1.2; }
.ad-btn small { font-weight: 600; font-size: 11px; opacity: .78; letter-spacing: .02em; }

.earn-row { display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 14px; background: rgba(255,255,255,.03); border: 1px solid var(--line); }
.earn-row.off { opacity: .62; }
.earn-emoji { font-size: 26px; width: 34px; text-align: center; flex: none; }
.earn-name { font-weight: 800; font-size: 14px; }
.earn-name b { color: var(--lime); }
.earn-sub { font-size: 12px; color: var(--muted); line-height: 1.35; margin: 1px 0 5px; }
.earn-cap { font-size: 11px; color: var(--muted); margin-top: 3px; }
/* the text column has to be allowed to shrink, or a long offer name pushes the
   whole row past the edge of a narrow phone */
.earn-row > .grow { min-width: 0; }
.earn-row .earn-name, .earn-row .earn-sub { overflow-wrap: anywhere; }
.earn-row .ad-btn { flex: 0 0 auto; width: 102px; padding: 8px 6px; font-size: 13px; white-space: normal; }
.ad-btn small { white-space: normal; line-height: 1.15; }
.bar.slim { height: 4px; }

/* house ad — full-screen, clearly marked, and it cannot be mistaken for play */
.ad-overlay { position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; padding: 18px; background: rgba(4,4,18,.86); backdrop-filter: blur(6px); animation: fade .18s ease; }
.ad-card { width: min(420px, 100%); border-radius: 20px; background: var(--panel-solid); border: 1px solid var(--line); box-shadow: 0 24px 60px rgba(0,0,0,.55); overflow: hidden; }
.ad-head { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-bottom: 1px solid var(--line); }
.ad-count { font-family: var(--head); font-size: 15px; color: var(--cyan); min-width: 28px; text-align: right; }
.ad-body { padding: 30px 20px; text-align: center; background: radial-gradient(circle at 50% 0%, rgba(163,107,255,.22), transparent 70%); }
.ad-icon { font-size: 58px; line-height: 1; }
.ad-name { font-family: var(--head); font-size: 22px; margin-top: 10px; }
.ad-line { color: var(--muted); font-size: 13px; margin-top: 6px; line-height: 1.45; }
.ad-bar { height: 4px; background: rgba(255,255,255,.08); }
.ad-bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--cyan), var(--lime)); transition: width 1s linear; }
.ad-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 14px; }
.ad-note { font-size: 12px; color: var(--muted); }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

/* ---------- dev: payment self-check ---------- */
.paycheck { display: flex; flex-direction: column; gap: 6px; }
.pc { display: flex; gap: 9px; align-items: flex-start; padding: 8px 10px; border-radius: 11px; background: rgba(255,255,255,.03); border-left: 3px solid var(--muted); }
.pc.ok { border-left-color: var(--lime); }
.pc.bad { border-left-color: var(--red); }
.pci { font-weight: 900; width: 14px; flex: none; }
.pc.ok .pci { color: var(--lime); }
.pc.bad .pci { color: var(--red); }
.pcn { font-weight: 700; font-size: 13px; }
.pcd { font-size: 12px; color: var(--muted); line-height: 1.4; word-break: break-word; }

/* ---------- confetti, pops ---------- */
/* Both live in #floaters, which sits above everything and takes no pointer
   events, so nothing here can ever swallow a tap. */
.confetti { position: absolute; pointer-events: none; will-change: transform, opacity;
  animation: confettiFly var(--dur, 1200ms) cubic-bezier(.16, .8, .36, 1) forwards; }
@keyframes confettiFly {
  0% { transform: translate(-50%, -50%) scale(.4) rotate(0deg); opacity: 0; }
  12% { opacity: 1; transform: translate(-50%, -50%) scale(1.15) rotate(calc(var(--rot) * .15)); }
  100% { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy) + 120px)) scale(.8) rotate(var(--rot)); opacity: 0; }
}
.pop { position: fixed; transform: translate(-50%, 0); pointer-events: none; font-family: var(--head);
  font-size: 20px; font-weight: 900; letter-spacing: .02em; text-shadow: 0 2px 10px rgba(0,0,0,.6);
  animation: popUp 1.3s cubic-bezier(.2, .9, .3, 1) forwards; }
.pop.good { color: var(--lime); }
.pop.gem { color: var(--cyan); }
.pop.bad { color: var(--red); }
@keyframes popUp {
  0% { opacity: 0; transform: translate(-50%, 6px) scale(.7); }
  18% { opacity: 1; transform: translate(-50%, -10px) scale(1.18); }
  35% { transform: translate(-50%, -16px) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -54px) scale(.95); }
}
@media (prefers-reduced-motion: reduce) { .pop { animation-duration: .01ms; } }

/* ---------- dev: redeem codes ---------- */
.code-form-grid label { min-width: 0; }
.dev-num.wide { width: 100%; }
.code-row { display: flex; align-items: center; gap: 8px; padding: 9px 11px; border-radius: 12px;
  background: rgba(255,255,255,.03); border: 1px solid var(--line); border-left: 3px solid var(--lime); }
.code-row.dead { border-left-color: var(--muted); opacity: .62; }
.code-row > .grow { min-width: 0; }
.crow-top { display: flex; align-items: center; gap: 8px; }
.ccode { font-family: var(--head); font-size: 15px; letter-spacing: .06em; overflow-wrap: anywhere; }
.cstate { font-size: 10px; text-transform: uppercase; letter-spacing: .12em; padding: 1px 6px; border-radius: 6px; border: 1px solid var(--line); color: var(--muted); }
.cstate.live { color: var(--lime); border-color: rgba(182,255,59,.4); }
.cstate.expired, .cstate.usedup { color: var(--orange); border-color: rgba(255,159,67,.4); }
.crow-sub { font-size: 12px; line-height: 1.4; overflow-wrap: anywhere; }
.name-status.ok { color: var(--lime); }
.name-status.bad { color: var(--red); }

/* ---------- pets mode ---------- */
/* Idle motion on the pets: a den full of perfectly still animals reads as a
   screenshot, and these are the thing the whole mode is about. */
.breathe { display: inline-block; animation: breathe 3.2s ease-in-out infinite; }
@keyframes breathe { 0%, 100% { transform: scale(1) translateY(0); } 50% { transform: scale(1.06) translateY(-3px); } }
.wiggle { display: inline-block; animation: wiggle 2.6s ease-in-out infinite; transform-origin: 50% 85%; }
@keyframes wiggle { 0%, 70%, 100% { transform: rotate(0); } 78% { transform: rotate(-9deg); } 86% { transform: rotate(8deg); } 93% { transform: rotate(-4deg); } }
.bounce { display: inline-block; animation: bounceY .9s cubic-bezier(.3,.7,.4,1) infinite; }
@keyframes bounceY { 0%, 100% { transform: translateY(0); } 40% { transform: translateY(-9px); } 60% { transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce) { .breathe, .wiggle, .bounce { animation: none; } }

.pet-hero .pet-emoji.xl, .pet-hero .pet-pic { filter: drop-shadow(0 6px 16px rgba(163,107,255,.45)); }
.pet-tile.away { opacity: .72; }
.away-tag { font-size: 11px; color: var(--cyan); margin-top: 4px; }

.slotline { font-size: 13px; color: var(--muted); }
.slotline b { color: var(--text); font-size: 15px; }

.gemrule { border-radius: 14px; padding: 10px 12px; border: 1px solid rgba(25,230,255,.28);
  background: linear-gradient(135deg, rgba(25,230,255,.10), rgba(163,107,255,.08)); }
.gr-title { font-weight: 800; font-size: 13px; margin-bottom: 3px; }
.gr-body { font-size: 12px; color: var(--muted); line-height: 1.5; }
.gr-body b { color: var(--cyan); }

.exp-card { display: flex; flex-direction: column; gap: 8px; padding: 11px; border-radius: 15px;
  background: rgba(255,255,255,.03); border: 1px solid var(--line); border-left: 3px solid var(--rc, var(--line)); }
.exp-card + .exp-card { margin-top: 9px; }
.exp-card.ready { border-color: rgba(182,255,59,.5); box-shadow: 0 0 0 1px rgba(182,255,59,.18), 0 0 22px rgba(182,255,59,.10); }
.exp-card .pname { font-weight: 800; font-size: 14px; }
.exp-bar i { background: linear-gradient(90deg, var(--cyan), var(--lime)); }
.haul { display: flex; flex-wrap: wrap; gap: 6px; }
.haul span { font-size: 12px; font-weight: 700; padding: 3px 8px; border-radius: 8px; background: rgba(255,255,255,.06); }
.haul .gem { color: var(--cyan); background: rgba(25,230,255,.13); }

.trip-pick { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 2px; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; -webkit-mask-image: linear-gradient(to right, #000 88%, transparent); mask-image: linear-gradient(to right, #000 88%, transparent); }
.trip-pick::-webkit-scrollbar { display: none; }
.trip { flex: 1 0 auto; min-width: 58px; display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 7px 6px; border-radius: 11px; border: 1px solid var(--line); background: rgba(255,255,255,.03); color: var(--text); cursor: pointer; }
.trip.on { border-color: var(--cyan); background: rgba(25,230,255,.14); box-shadow: 0 0 12px rgba(25,230,255,.22); }
.trip .te { font-size: 17px; line-height: 1; }
.trip .tn { font-size: 11px; font-weight: 800; }
.trip .tr { font-size: 10px; color: var(--muted); }
.trip.on .tr { color: var(--cyan); }

.next-stage { border: 1px solid rgba(163,107,255,.35); }
.next-stage.boss { border-color: rgba(255,209,102,.5); box-shadow: 0 0 26px rgba(255,209,102,.12) inset; }
.ns-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ns-tag { font-family: var(--head); font-size: 12px; letter-spacing: .14em; text-transform: uppercase; color: var(--purple); }
.next-stage.boss .ns-tag { color: var(--yellow); }

/* minmax(0, 1fr) rather than 1fr: a plain 1fr keeps each column at least as
   wide as its own min-content, so the longer of the two names quietly steals
   the other side's width and squeezes it to one letter per line. */
.versus { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: start; gap: 8px; text-align: center; }
.vs-side { min-width: 0; }
.vs-side .pname { font-weight: 800; font-size: 13px; margin-top: 2px; overflow-wrap: break-word; hyphens: auto; }
.vs-side .pet-emoji.xl { font-size: 44px; line-height: 1.1; display: block; }
.vs-side .pet-pic { margin: 0 auto; }
.vs-mid { font-family: var(--head); font-size: 15px; color: var(--muted); letter-spacing: .1em; }
.vs-mid .mv { font-size: 24px; animation: popIn .35s ease; display: inline-block; }
@keyframes popIn { from { transform: scale(.3); opacity: 0; } to { transform: scale(1); opacity: 1; } }

.chapter { display: flex; align-items: center; gap: 10px; padding: 9px 4px; border-bottom: 1px solid var(--line); }
.chapter:last-child { border-bottom: none; }
.chapter.locked { opacity: .48; }
.chapter.done .chemoji { filter: drop-shadow(0 0 8px var(--lime)); }
.chemoji { font-size: 26px; width: 32px; text-align: center; flex: none; }
.chapter > .grow { min-width: 0; }

/* ---------- campaign fight ---------- */
.fight { max-width: 460px; }
.fight-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.fight-line { font-size: 13px; color: var(--muted); min-height: 34px; margin-top: 8px; line-height: 1.4; }
.fight-line b { color: var(--text); }
.hpbar { position: relative; height: 12px; border-radius: 99px; background: rgba(255,255,255,.10); overflow: hidden; margin-top: 6px; }
.hpbar i { display: block; height: 100%; border-radius: 99px; transition: width .35s cubic-bezier(.3,.8,.4,1); }
.hpbar.you i { background: linear-gradient(90deg, var(--lime), var(--green)); }
.hpbar.foe i { background: linear-gradient(90deg, var(--red), var(--orange)); }
.hpbar span { position: absolute; inset: 0; font-size: 9px; font-weight: 800; line-height: 12px; text-align: center; text-shadow: 0 1px 3px rgba(0,0,0,.8); }
.versus.live .vs-side.vs-hit .pet-emoji, .versus.live .vs-side.vs-hit .pet-pic { animation: lunge .4s ease; }
.versus.live .vs-side.vs-hurt .pet-emoji, .versus.live .vs-side.vs-hurt .pet-pic { animation: recoil .4s ease; }
@keyframes lunge { 0%, 100% { transform: translateX(0) scale(1); } 45% { transform: translateX(10px) scale(1.12); } }
@keyframes recoil { 0%, 100% { transform: translateX(0); filter: none; } 30% { transform: translateX(-9px); filter: brightness(2.4) saturate(.3); } }
.fight-end { margin-top: 10px; }
.fight-end .big { font-family: var(--head); font-size: 24px; margin-bottom: 8px; }
.fight-end .big.win { color: var(--lime); text-shadow: 0 0 20px rgba(182,255,59,.5); }
.shake { animation: shakeS .22s ease; }
.shake-hard { animation: shakeH .32s ease; }
@keyframes shakeS { 0%,100% { transform: translate(0,0); } 25% { transform: translate(-3px,1px); } 60% { transform: translate(3px,-1px); } }
@keyframes shakeH { 0%,100% { transform: translate(0,0); } 20% { transform: translate(-7px,3px) rotate(-.5deg); } 50% { transform: translate(6px,-3px) rotate(.5deg); } 80% { transform: translate(-3px,1px); } }
@media (prefers-reduced-motion: reduce) {
  .shake, .shake-hard, .versus.live .vs-side.vs-hit .pet-emoji, .versus.live .vs-side.vs-hurt .pet-emoji,
  .versus.live .vs-side.vs-hit .pet-pic, .versus.live .vs-side.vs-hurt .pet-pic,
  .pet-pic.breathe, .pet-pic.bounce { animation: none; }
}

/* ==========================================================================
   ARCADE PASS
   The whole site moves now. Three rules kept it from becoming a migraine:
   every animation is transform/opacity only (never layout), everything that
   loops is slow and low-contrast so it reads as atmosphere rather than as
   something demanding attention, and the entire thing switches off under
   prefers-reduced-motion at the bottom of this block.
   ========================================================================== */

/* --- living background: two drifting auroras and a slow star layer --- */
body::after {
  content: ""; position: fixed; inset: -20%; pointer-events: none; z-index: 0;
  background:
    radial-gradient(420px 320px at 20% 30%, rgba(163, 107, 255, .13), transparent 62%),
    radial-gradient(380px 300px at 80% 70%, rgba(25, 230, 255, .10), transparent 62%),
    radial-gradient(300px 260px at 60% 15%, rgba(255, 61, 154, .09), transparent 62%);
  animation: aurora 34s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes aurora {
  0% { transform: translate3d(-3%, -2%, 0) scale(1); }
  50% { transform: translate3d(3%, 2%, 0) scale(1.08); }
  100% { transform: translate3d(-2%, 3%, 0) scale(1.02); }
}
#app::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    radial-gradient(1.4px 1.4px at 12% 18%, rgba(255,255,255,.55), transparent),
    radial-gradient(1.2px 1.2px at 78% 26%, rgba(182,255,59,.45), transparent),
    radial-gradient(1.6px 1.6px at 34% 62%, rgba(25,230,255,.45), transparent),
    radial-gradient(1.2px 1.2px at 88% 74%, rgba(255,255,255,.40), transparent),
    radial-gradient(1.3px 1.3px at 58% 88%, rgba(255,61,154,.40), transparent),
    radial-gradient(1.1px 1.1px at 6% 82%, rgba(255,255,255,.35), transparent);
  background-size: 100% 100%;
  animation: twinkle 7s ease-in-out infinite alternate;
}
@keyframes twinkle { from { opacity: .35; } to { opacity: .9; } }

/* --- screen entrance: content arrives instead of appearing --- */
#main.enter > .stack > * { animation: riseIn .4s cubic-bezier(.2,.8,.3,1) backwards; }
#main.enter > .stack > *:nth-child(1) { animation-delay: 0ms; }
#main.enter > .stack > *:nth-child(2) { animation-delay: 45ms; }
#main.enter > .stack > *:nth-child(3) { animation-delay: 90ms; }
#main.enter > .stack > *:nth-child(4) { animation-delay: 130ms; }
#main.enter > .stack > *:nth-child(5) { animation-delay: 165ms; }
#main.enter > .stack > *:nth-child(n+6) { animation-delay: 195ms; }
@keyframes riseIn { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }

/* --- buttons: press, and a ripple from wherever the finger landed --- */
.btn { position: relative; overflow: hidden; transition: transform .1s ease, filter .15s ease, box-shadow .2s ease; }
.btn:not(:disabled):active { transform: scale(.955); }
.ripple { position: absolute; border-radius: 50%; transform: translate(-50%, -50%) scale(0);
  background: radial-gradient(circle, rgba(255,255,255,.55), rgba(255,255,255,0) 70%);
  pointer-events: none; animation: rippleOut .55s ease-out forwards; }
@keyframes rippleOut { to { transform: translate(-50%, -50%) scale(1); opacity: 0; } }

/* the primary call to action breathes, so the next thing to do is obvious */
.btn.lime:not(:disabled), .btn.cyan:not(:disabled) { animation: ctaGlow 3.4s ease-in-out infinite; }
@keyframes ctaGlow { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.1); } }

/* --- panels and cards --- */
.panel { transition: border-color .25s ease, box-shadow .25s ease; }
.hero-card { position: relative; overflow: hidden; }
/* a slow sheen crossing the hero card — the one piece of pure decoration here */
.hero-card::after {
  content: ""; position: absolute; top: -60%; left: -40%; width: 40%; height: 220%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.10), transparent);
  transform: rotate(14deg); animation: sheen 6.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes sheen { 0%, 62% { left: -40%; } 100% { left: 130%; } }

/* --- the tab bar --- */
#tabs button { transition: background .16s ease, color .18s ease; }
#tabs button.on .ico { animation: tabPop .42s cubic-bezier(.2,1.5,.4,1); }
@keyframes tabPop { 0% { transform: scale(1); } 40% { transform: scale(1.35) translateY(-3px); } 100% { transform: scale(1); } }

/* --- the wallet, when it changes --- */
.wallet .coins { transition: transform .2s cubic-bezier(.2,1.6,.4,1); }
.wallet .coins.bumped { animation: bump .55s cubic-bezier(.2,1.5,.4,1); }
@keyframes bump { 0% { transform: scale(1); } 35% { transform: scale(1.3); filter: brightness(1.5); } 100% { transform: scale(1); } }

/* --- toasts arrive with a spring --- */
.toast { animation: toastIn .34s cubic-bezier(.2,1.4,.4,1); }
@keyframes toastIn { from { opacity: 0; transform: translateY(16px) scale(.94); } to { opacity: 1; transform: none; } }

/* --- generic game juice: anything tappable in a board reacts --- */
.tile, .card, .tok, .cell, .peg, .ycard, .mm-word, .seat, .game-card, .item, .pet-tile, .hatch-card, .room-item {
  transition: transform .12s ease, box-shadow .2s ease, border-color .2s ease;
}
.tile:active, .card.playable:active, .tok.can:active, .cell:active, .game-card:active, .item:active, .room-item:active { transform: scale(.96); }
.game-card.selected { animation: selectedPulse 2.6s ease-in-out infinite; }
@keyframes selectedPulse { 0%, 100% { box-shadow: 0 0 0 1px var(--a), 0 0 12px rgba(255,61,154,.25); } 50% { box-shadow: 0 0 0 1px var(--a), 0 0 22px rgba(255,61,154,.55); } }

/* whoever's turn it is should be impossible to miss */
.seat.turn, .player-card.turn { animation: turnGlow 1.8s ease-in-out infinite; }
@keyframes turnGlow { 0%, 100% { box-shadow: 0 0 0 1px var(--line); } 50% { box-shadow: 0 0 0 2px var(--lime), 0 0 18px rgba(182,255,59,.35); } }

/* --- the result card lands --- */
.modal { animation: modalIn .38s cubic-bezier(.2,1.3,.35,1); }
@keyframes modalIn { from { opacity: 0; transform: translateY(24px) scale(.94); } to { opacity: 1; transform: none; } }
.modal .big.win, .modal .big { animation: titleIn .5s cubic-bezier(.2,1.5,.4,1) .1s backwards; }
@keyframes titleIn { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }

/* --- the one global off switch --- */
@media (prefers-reduced-motion: reduce) {
  body::after, #app::before, .hero-card::after,
  .btn.lime:not(:disabled), .btn.cyan:not(:disabled),
  #tabs button.on .ico, .wallet .coins.bumped, .toast, .modal, .modal .big,
  #main.enter > .stack > *, .game-card.selected, .seat.turn, .player-card.turn, .ripple {
    animation: none !important;
  }
  * { transition-duration: .01ms !important; }
}

/* ---------- log in, then sign up ---------- */
/* A labelled rule between the two, so the second panel reads as an alternative
   rather than as a second half of the first form. */
.auth-or { display: flex; align-items: center; gap: 12px; margin: 4px 2px; }
.auth-or::before, .auth-or::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.auth-or span { font-family: var(--head); font-size: 11px; letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }
.signup-cta h2 { margin-bottom: 2px; }

/* ---------- letting things actually shrink ---------- */
/* A flex or grid item's default minimum size is its content, so a long name or
   a wide row pushes its whole container past the edge of the phone rather than
   wrapping or scrolling. These are the places where that bit. */
.seat > .grow, .seat .sname, .friend > .grow, .lb-row > .grow,
.room-item > .grow, .exp-card > .grow, .code-row > .grow, .pc > .grow { min-width: 0; }
.seat .sname { flex-wrap: wrap; }
.seat .sname, .seat .ssub { overflow-wrap: anywhere; }

/* Horizontal scrollers have to be allowed to be narrower than what they hold,
   or the scroller itself becomes the thing that overflows. */
.game-pick, .trip-pick, #chat-reacts, .segmented { min-width: 0; }
.game-pick { -webkit-overflow-scrolling: touch; }

/* Three-across grids are too tight below about 360px. */
@media (max-width: 359px) {
  .store-grid, .packs, .stat-grid, .who-stats { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .hatch-grid, .pet-grid, .dev-grid, .dev-items { grid-template-columns: minmax(0, 1fr); }
  .seats { grid-template-columns: minmax(0, 1fr); }
  #chat-reacts button { width: 38px; height: 36px; font-size: 19px; }
}

/* ---------- the top bar on a narrow phone ---------- */
/* The room bar carries a back button, the game name, the room code, a mode
   badge and an invite button; the in-game bar carries scores for up to four
   players. Below about 380px that is more than fits, so the bar clips rather
   than pushing the whole page sideways, and the least useful item — the game
   name, which the board itself makes obvious — gives up its space first. */
#top { overflow: hidden; }
#top > * { min-width: 0; }
#top .logo.small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scores { min-width: 0; overflow-x: auto; scrollbar-width: none; }
.scores::-webkit-scrollbar { display: none; }
@media (max-width: 379px) {
  #top .logo.small { display: none; }
  #top { gap: 8px; padding-left: 10px; padding-right: 10px; }
}

/* The reaction strip scrolls; it must not be allowed to widen the sheet. */
#chat-sheet { overflow: hidden; }
#chat-reacts { max-width: 100%; }

/* ---------- adding people where you meet them ---------- */
.add-friend { width: 24px; height: 24px; font-size: 15px; line-height: 1; flex: none;
  border-radius: 8px; border: 1px solid rgba(182,255,59,.45); color: var(--lime); background: rgba(182,255,59,.10); }
.add-friend:active { background: rgba(182,255,59,.25); }
.add-friend:disabled { opacity: .4; }
.friend-yes { font-size: 13px; opacity: .75; flex: none; }
.friend-yes.pending { opacity: .55; }

.played-with { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.pw-label { font-family: var(--head); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
.pw-row { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-top: 7px; }
.pw-chip { display: flex; align-items: center; gap: 5px; padding: 4px 8px 4px 4px; border-radius: 999px;
  background: rgba(255,255,255,.05); border: 1px solid var(--line); max-width: 100%; min-width: 0; }
.pw-chip .who { font-size: 13px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 120px; }

/* ---------- manual sale ---------- */
.sell-box { margin-top: 10px; padding: 11px 12px; border-radius: 14px;
  border: 1px solid rgba(182,255,59,.28); background: linear-gradient(135deg, rgba(182,255,59,.07), rgba(46,230,197,.05)); }
.sale-code { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px;
  padding: 9px 12px; border-radius: 12px; background: rgba(5,5,20,.55); border: 1px dashed var(--lime); }
.sale-code b { font-family: var(--head); font-size: 19px; letter-spacing: .12em; color: var(--lime); overflow-wrap: anywhere; }
.sale-code .muted { flex-basis: 100%; }

/* Wheel contents, grouped by what the prize actually is. */
.board-group { margin-top: 10px; }
.board-group h4 { margin: 0 0 5px; font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); font-weight: 800; }
.board-group + .board-group { border-top: 1px solid var(--line); padding-top: 9px; }

/* Pet rows: the name is the flexible part, so it is the part that truncates.
   Without min-width:0 a long name pushes the row wider than the screen. */
.pname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row > .grow { min-width: 0; }
.row > .grow > b, .row > .grow > div > b { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }

/* ---------- interactive battles ---------- */
/* A fight you play needs three things the old playback did not: something to
   press, a reason to press one thing over another, and feedback that lands
   before the next decision is asked for. */
.live-fight { gap: 10px; }
.live-fight .versus { align-items: start; }
.moves { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 4px; }
.move {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 6px 8px; border-radius: 14px; cursor: pointer;
  border: 2px solid var(--line); background: rgba(22, 20, 64, .72); color: var(--text);
  transition: transform .14s var(--ease-out), box-shadow .2s var(--ease-out), border-color .2s var(--ease-out), opacity .2s linear;
}
.move .me { font-size: 22px; line-height: 1; }
.move .mn { font-weight: 800; font-size: 13px; letter-spacing: .02em; }
.move small { font-size: 10px; color: var(--muted); letter-spacing: .04em; }
.move.attack { border-color: rgba(25, 230, 255, .45); }
.move.special { border-color: rgba(255, 61, 154, .5); }
.move.guard { border-color: rgba(182, 255, 59, .45); }
.move:not(:disabled):hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0, 0, 0, .45); }
.move:not(:disabled):active { transform: translateY(0) scale(.97); }
.move.special:not(:disabled) { box-shadow: 0 0 16px rgba(255, 61, 154, .25); }
.move.locked, .move:disabled { opacity: .4; cursor: default; }
.fight-foot { display: flex; gap: 8px; justify-content: center; margin-top: 2px; }

/* Energy as pips: "3 of 9" is a number, pips are a feeling. */
.pips { display: flex; gap: 3px; justify-content: center; align-items: center; margin-top: 5px; }
.pips i { width: 8px; height: 8px; border-radius: 50%; background: rgba(255, 255, 255, .16); transition: background .25s var(--ease-out), box-shadow .25s var(--ease-out); }
.pips i.on { background: var(--yellow); box-shadow: 0 0 7px rgba(255, 225, 77, .75); }
.pips b { font-size: 10px; color: var(--yellow); font-weight: 800; margin-left: 2px; }
.guarding { font-size: 11px; color: var(--lime); font-weight: 800; margin-top: 3px; letter-spacing: .04em; }

/* Health that reads at a glance: it changes colour as it drains, and the bar
   eases rather than jumping, so a big hit looks like a big hit. */
.hpbar i { transition: width .45s var(--ease-out), background .35s linear; }
.hpbar.half i { background: var(--yellow); }
.hpbar.low i { background: var(--red); }
.hpbar.low { animation: hpPanic 1.1s ease-in-out infinite; }
@keyframes hpPanic { 0%, 100% { box-shadow: 0 0 0 rgba(255, 75, 92, 0); } 50% { box-shadow: 0 0 12px rgba(255, 75, 92, .6); } }
.vs-mid .mv.pop { display: inline-block; animation: mvPop .42s var(--ease-out); }
@keyframes mvPop { 0% { transform: scale(.4) rotate(-12deg); opacity: 0; } 60% { transform: scale(1.25) rotate(4deg); opacity: 1; } 100% { transform: scale(1) rotate(0); } }
.evolve-note { animation: evoGlow 1.6s ease-in-out infinite; }
@keyframes evoGlow { 0%, 100% { text-shadow: none; } 50% { text-shadow: 0 0 14px var(--lime); } }

@media (prefers-reduced-motion: reduce) {
  .move, .hpbar i, .pips i { transition: none; }
  .hpbar.low, .vs-mid .mv.pop, .evolve-note { animation: none; }
}
@media (max-width: 380px) {
  .move { padding: 8px 4px 7px; }
  .move .mn { font-size: 12px; }
  .move .me { font-size: 19px; }
}

/* ---------- motion pass ---------- */
/* Everything the player touches answers immediately. A press that does not
   move is the single loudest way an app feels dead, and it costs nothing. */
.btn, .move, .part, .item, .game-card, .tab, .segmented button, .trip, .chapter, .pack, .code-row .btn {
  transition: transform var(--t-tap) var(--ease-out), box-shadow var(--t-quick) var(--ease-out),
              background-color var(--t-quick) var(--ease-out), border-color var(--t-quick) var(--ease-out),
              opacity var(--t-quick) linear;
}
.btn:not(:disabled):active, .part:active, .item:active, .game-card:active,
.segmented button:active, .trip:active, .chapter:active, .pack:active { transform: scale(.96); }
.btn:not(:disabled):hover { transform: translateY(-1px); }

/* Long lists: let the browser skip layout for rows that are not on screen.
   On a mid-range phone this is the difference between a list that scrolls and
   one that stutters. */
.lb-list, .board-left, .items-grid, .pet-grid, .hatch-grid, .chapter-list, .code-rows {
  content-visibility: auto;
  contain-intrinsic-size: auto 400px;
}

/* Things that arrive should arrive, not appear. */
#main.enter > * { animation: riseIn var(--t-enter) var(--ease-out) both; }
#main.enter > *:nth-child(2) { animation-delay: .04s; }
#main.enter > *:nth-child(3) { animation-delay: .08s; }
#main.enter > *:nth-child(n+4) { animation-delay: .12s; }
@keyframes riseIn { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }

/* Sheets and modals rise from the thumb rather than blinking into place. */
.modal { animation: modalIn var(--t-move) var(--spring) both; }
@keyframes modalIn { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .btn, .move, .part, .item, .game-card, .segmented button, .trip, .chapter, .pack { transition: none; }
  .btn:not(:disabled):active, .btn:not(:disabled):hover, .part:active, .item:active,
  .game-card:active, .segmented button:active, .trip:active, .chapter:active, .pack:active { transform: none; }
  #main.enter > *, .modal { animation: none; }
}

/* ============================================================
   GAME SKIN
   ------------------------------------------------------------
   What separates a studio game UI from a web app is not colour,
   it is DEPTH. Every surface is either raised or sunk, every edge
   catches a light from above, and every important thing is framed.
   This layer adds that using only borders, gradients and shadows —
   no image assets to load, nothing to go fuzzy on a big screen.
   ============================================================ */
:root {
  --gold: #ffcf5c;
  --gold-dim: #a9761f;
  --plate: linear-gradient(180deg, #221c52 0%, #16123a 48%, #110e2e 100%);
  --plate-lip: linear-gradient(180deg, rgba(255,255,255,.22), rgba(255,255,255,0) 42%);
  --rim: rgba(255, 207, 92, .55);
  --rim-soft: rgba(163, 107, 255, .42);
  --sink: inset 0 2px 6px rgba(0,0,0,.6), inset 0 -1px 0 rgba(255,255,255,.06);
}

/* ---------- framed panels ---------- */
.panel {
  position: relative;
  background: var(--plate);
  border: 1px solid var(--rim-soft);
  box-shadow:
    0 14px 34px rgba(0,0,0,.55),
    0 2px 0 rgba(0,0,0,.5),
    inset 0 1px 0 rgba(255,255,255,.14),
    inset 0 -14px 28px rgba(0,0,0,.35);
}
/* the inner hairline that makes a panel read as a plate rather than a div */
.panel::before {
  content: ""; position: absolute; inset: 4px; border-radius: calc(var(--radius) - 5px);
  border: 1px solid rgba(255,255,255,.07); pointer-events: none;
}
/* corner ornaments, drawn from two borders each */
.panel::after {
  content: ""; position: absolute; inset: 7px; pointer-events: none; border-radius: 3px;
  background:
    linear-gradient(var(--rim), var(--rim)) left top / 12px 2px no-repeat,
    linear-gradient(var(--rim), var(--rim)) left top / 2px 12px no-repeat,
    linear-gradient(var(--rim), var(--rim)) right top / 12px 2px no-repeat,
    linear-gradient(var(--rim), var(--rim)) right top / 2px 12px no-repeat,
    linear-gradient(var(--rim), var(--rim)) left bottom / 12px 2px no-repeat,
    linear-gradient(var(--rim), var(--rim)) left bottom / 2px 12px no-repeat,
    linear-gradient(var(--rim), var(--rim)) right bottom / 12px 2px no-repeat,
    linear-gradient(var(--rim), var(--rim)) right bottom / 2px 12px no-repeat;
  opacity: .5;
}
.panel > h3 {
  position: relative; display: inline-block; margin-bottom: 2px;
  color: var(--gold); text-shadow: 0 1px 0 rgba(0,0,0,.8), 0 0 12px rgba(255,207,92,.35);
}
.panel > h3::after {
  content: ""; display: block; height: 2px; margin-top: 5px; border-radius: 2px;
  background: linear-gradient(90deg, var(--gold), transparent);
}

/* ---------- buttons with a lip and a base ---------- */
/* Two shadows do the work: a dark one directly under the button for the body,
   and a hard offset for the base it sits on. Pressing moves the button down
   onto its base, which is why it feels like a button and not a rectangle. */
.btn {
  position: relative; overflow: hidden;
  border: 1px solid rgba(0,0,0,.55);
  box-shadow:
    0 4px 0 rgba(0,0,0,.45),
    0 10px 22px rgba(0,0,0,.45),
    inset 0 1px 0 rgba(255,255,255,.45),
    inset 0 -8px 16px rgba(0,0,0,.28);
  text-shadow: 0 1px 2px rgba(0,0,0,.45);
}
.btn::before {
  content: ""; position: absolute; inset: 1px 1px auto; height: 45%;
  border-radius: 13px 13px 40% 40%;
  background: var(--plate-lip); pointer-events: none;
}
/* a slow sweep of light, so the primary action is never quite still */
.btn:not(.ghost):not(:disabled)::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 38%;
  left: -50%; transform: skewX(-18deg);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.3), transparent);
  animation: btnSheen 4.5s var(--ease-in-out) infinite; pointer-events: none;
}
@keyframes btnSheen { 0%, 62% { left: -50%; } 88%, 100% { left: 130%; } }
.btn:not(:disabled):active { transform: translateY(3px) scale(.99); box-shadow: 0 1px 0 rgba(0,0,0,.45), 0 4px 10px rgba(0,0,0,.4), inset 0 1px 0 rgba(255,255,255,.3); }
.btn.ghost { box-shadow: 0 2px 0 rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.08); border-color: var(--rim-soft); }
.btn.lime, .btn.cyan { border-color: rgba(0,0,0,.45); }

/* ---------- currency, sunk into the bar ---------- */
.coins {
  background: linear-gradient(180deg, #0a0820, #141034);
  border: 1px solid var(--rim); box-shadow: var(--sink), 0 0 14px rgba(255,207,92,.18);
  text-shadow: 0 0 8px rgba(255,225,77,.5);
}
.coins.gems { border-color: rgba(25,230,255,.5); box-shadow: var(--sink), 0 0 14px rgba(25,230,255,.2); }

/* ---------- top bar as a banner plate ---------- */
#top {
  background: linear-gradient(180deg, #171246 0%, #100d30 70%, rgba(7,7,26,.92) 100%);
  border-bottom: 2px solid var(--gold-dim);
  box-shadow: 0 6px 20px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.12);
}

/* ---------- the nav, raised off the floor ---------- */
#tabs {
  background: linear-gradient(180deg, #191350, #0b0925);
  border-top: 2px solid var(--gold-dim);
  box-shadow: 0 -8px 26px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.1);
}
/* Tall cells that reach the bottom of the screen, so the bar is a floor rather
   than a strip with icons on it. */
#tabs button { min-height: 62px; }
#tabs button .ico { transition: transform var(--t-quick) var(--spring), filter var(--t-quick) linear; }
/* the active tab lifts and lights up, which is how a player finds their place */
#tabs button.active { color: var(--gold); }
#tabs button.active .ico { transform: translateY(-3px) scale(1.18); filter: drop-shadow(0 4px 10px rgba(255,207,92,.6)); }

/* ---------- rarity frames ---------- */
/* One rule, four looks. The border carries the tier and the glow carries the
   excitement, so a legendary reads as legendary at thumbnail size. */
.item, .hatch-card, .pack, .game-card, .pet-tile {
  position: relative;
  background: var(--plate);
  box-shadow: 0 8px 20px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.1);
}
.item[data-rarity="rare"], .hatch-card[style*="19e6ff"] { border-color: rgba(25,230,255,.6); }
.item[data-rarity="epic"] { border-color: rgba(163,107,255,.65); box-shadow: 0 8px 20px rgba(0,0,0,.45), 0 0 16px rgba(163,107,255,.25), inset 0 1px 0 rgba(255,255,255,.1); }
.item[data-rarity="legendary"] {
  border-color: var(--gold);
  box-shadow: 0 8px 20px rgba(0,0,0,.45), 0 0 22px rgba(255,207,92,.35), inset 0 1px 0 rgba(255,255,255,.14);
}
.item[data-rarity="legendary"]::after {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
  background: linear-gradient(120deg, transparent 38%, rgba(255,207,92,.28) 50%, transparent 62%);
  background-size: 260% 100%; animation: legendSweep 3.4s linear infinite;
}
@keyframes legendSweep { from { background-position: 180% 0; } to { background-position: -80% 0; } }

/* ---------- ambient motes ---------- */
/* Three drifting lights behind everything. Cheap: three elements, transform
   only, and they sit behind the app so they never intercept a tap. */
body::after {
  content: ""; position: fixed; inset: -10% -10% auto; height: 120%; z-index: 0; pointer-events: none;
  background:
    radial-gradient(3px 3px at 12% 20%, rgba(255,207,92,.8), transparent 60%),
    radial-gradient(2px 2px at 78% 32%, rgba(25,230,255,.7), transparent 60%),
    radial-gradient(2.5px 2.5px at 42% 68%, rgba(255,61,154,.6), transparent 60%),
    radial-gradient(2px 2px at 88% 78%, rgba(182,255,59,.5), transparent 60%),
    radial-gradient(2px 2px at 24% 88%, rgba(163,107,255,.6), transparent 60%);
  animation: motes 26s var(--ease-in-out) infinite alternate;
  opacity: .75;
}
@keyframes motes {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-14px, -26px, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .btn:not(.ghost):not(:disabled)::after,
  .item[data-rarity="legendary"]::after,
  body::after { animation: none; }
  #tabs button, #tabs button .ico { transition: none; }
}

/* ---------- headers that earn their height ---------- */
/* The wallet used to be repeated here on every tab while the top bar already
   showed it. Removing that let the header shrink, which moves everything below
   it up into comfortable thumb range on a phone. */
.hero-card {
  position: relative;
  gap: 12px; padding: 11px 13px;
  background: var(--plate);
  border: 1px solid var(--rim-soft);
  box-shadow: 0 10px 24px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.12);
}
.hero-card::before {
  content: ""; position: absolute; inset: 3px; border-radius: calc(var(--radius) - 4px);
  border: 1px solid rgba(255,255,255,.06); pointer-events: none;
}
.hero-card .name { font-size: 17px; text-shadow: 0 1px 0 rgba(0,0,0,.7); }
.hero-card .meta { margin-top: 2px; }
/* the Store and Pets headers carry a paragraph of explanation; it can be
   smaller than the player's own name without losing anything */
.hero-card .meta, .hero-card p { font-size: 12px; line-height: 1.4; }

/* ---------- segmented pickers, sunk like a physical switch ---------- */
.segmented {
  background: linear-gradient(180deg, #0a0820, #12102e);
  border: 1px solid rgba(0,0,0,.6); box-shadow: var(--sink);
}
.segmented button.on {
  box-shadow: 0 2px 0 rgba(0,0,0,.4), 0 0 14px rgba(255,61,154,.4), inset 0 1px 0 rgba(255,255,255,.35);
  text-shadow: 0 1px 2px rgba(0,0,0,.5);
}

/* ---------- game cards ---------- */
.game-card { border: 1px solid var(--rim-soft); }
.game-card.selected {
  border-color: var(--gold);
  box-shadow: 0 0 0 1px rgba(255,207,92,.5), 0 0 22px rgba(255,207,92,.3), 0 8px 20px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.14);
  background: linear-gradient(180deg, rgba(255,207,92,.1), transparent 60%), var(--plate);
}

/* ---------- stacked segmented control ---------- */
/* Four sections across a 320px phone only works if the icon sits above the
   word instead of beside it. */
.segmented.seg-stack { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 5px; }
.segmented.seg-stack button {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  min-height: 54px; padding: 5px 2px; font-size: 11px; letter-spacing: .02em;
}
.segmented.seg-stack .si { font-size: 18px; line-height: 1; transition: transform var(--t-quick) var(--spring); }
.segmented.seg-stack .sl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.segmented.seg-stack button.on .si { transform: translateY(-1px) scale(1.15); }
@media (max-width: 340px) { .segmented.seg-stack button { font-size: 10px; } }
@media (prefers-reduced-motion: reduce) { .segmented.seg-stack .si { transition: none; } }

/* The empty-den egg was taller than the panel it introduced. A header should
   say what screen you are on, not occupy a third of it. */
.pet-hero .pet-egg, .pet-egg.xl { font-size: 44px; }
.pet-hero .pet-pic { width: 62px !important; height: 62px !important; }

/* Four stats on one line. Wrapping them onto two made every hatchery card
   taller than it needed to be, which pushed the pets themselves off screen. */
.hstats { gap: 2px 6px; flex-wrap: nowrap; justify-content: space-between; }
.hstats span { font-size: 10.5px; display: inline-flex; align-items: center; gap: 2px; }
@media (max-width: 360px) { .hstats span { font-size: 9.5px; } }

/* Gem-exclusive pieces get the loudest frame in the game, because they are the
   one thing playing cannot get you. */
.item.gem-only, .item:has(.gem-only) {
  border-color: var(--cyan);
  box-shadow: 0 8px 20px rgba(0,0,0,.45), 0 0 26px rgba(25,230,255,.38), inset 0 1px 0 rgba(255,255,255,.16);
}

/* ---------- ranked series ---------- */
/* The next board is already dealt behind this card, so it is an announcement
   rather than a loading screen. It leaves on its own. */
.leg-card { text-align: center; gap: 6px; padding: 22px 26px; max-width: 320px; }
.leg-card .leg-no { font-family: var(--head); font-size: 13px; letter-spacing: .22em; color: var(--gold); text-transform: uppercase; }
.leg-card .leg-score { display: flex; align-items: center; justify-content: center; gap: 12px; font-family: var(--head); font-size: 42px; font-weight: 900; line-height: 1; margin: 6px 0 2px; }
.leg-card .leg-score span { color: var(--muted); transition: color var(--t-quick) linear; }
.leg-card .leg-score span.lead { color: var(--lime); text-shadow: 0 0 16px rgba(182,255,59,.6); }
.leg-card .leg-score i { font-style: normal; color: var(--muted); font-size: 26px; }
.leg-card .leg-game { display: flex; align-items: center; justify-content: center; gap: 8px; font-size: 19px; }
.leg-card .lg-ico { font-size: 26px; }
.leg-card p { font-size: 13px; margin-top: 2px; }
/* the handover: what just happened, where it stands, what is next */
.leg-card { cursor: pointer; animation: leg-in .34s cubic-bezier(.2,.9,.25,1) both; }
@keyframes leg-in { from { opacity: 0; transform: translateY(14px) scale(.96); } }
.leg-card .leg-took {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  font-size: 13px; font-weight: 700; color: var(--muted);
}
.leg-card .leg-mark {
  display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%;
  background: rgba(255,255,255,.08); font-size: 11px; font-weight: 900; color: var(--muted);
}
.leg-card.good .leg-mark { background: color-mix(in srgb, var(--lime) 22%, transparent); color: var(--lime); }
.leg-card.bad .leg-mark { background: color-mix(in srgb, var(--red) 22%, transparent); color: var(--red); }
.leg-card .leg-was { font-size: 12px; color: var(--muted); margin-top: -2px; }
.leg-card .leg-next {
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line);
  display: grid; gap: 6px; animation: leg-next-in .4s .18s cubic-bezier(.2,.9,.25,1) both;
}
@keyframes leg-next-in { from { opacity: 0; transform: translateY(10px); } }
.leg-card .leg-bar {
  margin-top: 12px; height: 3px; border-radius: 999px; overflow: hidden;
  background: rgba(255,255,255,.1);
}
.leg-card .leg-bar i { display: block; height: 100%; background: var(--gold); transform-origin: left center;
  animation-name: leg-run; animation-timing-function: linear; animation-fill-mode: both; }
@keyframes leg-run { from { transform: scaleX(1); } to { transform: scaleX(0); } }
.leg-card .leg-skip { color: var(--muted); font-size: 11px; opacity: .75; }
@media (prefers-reduced-motion: reduce) {
  .leg-card, .leg-card .leg-next { animation: none; }
  .leg-card .leg-bar i { animation: none; transform: scaleX(1); }
}

/* ---------- the end of a ranked match ---------- */
/* A leg is not a game you play again, so there is no Play again here. What the
   match owes you is the verdict, the games it took, and the rating it moved. */
.series-end { text-align: center; gap: 8px; max-width: 360px; }
.series-end .se-crest { font-size: 46px; line-height: 1; animation: se-crest .5s cubic-bezier(.2,.9,.25,1) both; }
@keyframes se-crest { from { opacity: 0; transform: scale(.5) rotate(-12deg); } }
.series-end .se-title {
  font-family: var(--head); font-weight: 900; font-size: 30px; letter-spacing: .01em; line-height: 1.05;
}
.series-end.won .se-title { color: var(--lime); text-shadow: 0 0 22px rgba(182,255,59,.45); }
.series-end.lost .se-title { color: var(--red); }
.series-end.drew .se-title { color: var(--gold); }
.series-end .se-sub { color: var(--muted); font-size: 13px; margin: 0; }
.series-end .se-score {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  font-family: var(--head); font-size: 44px; font-weight: 900; line-height: 1; margin: 4px 0 2px;
}
/* Your number takes the verdict's colour and theirs stays out of the way. A
   plain "whoever is ahead goes green" lit the other player's score up in your
   winning colour on the screen that tells you you lost. */
.series-end .se-score span { color: var(--muted); }
.series-end.won .se-score .mine { color: var(--lime); text-shadow: 0 0 16px rgba(182,255,59,.55); }
.series-end.lost .se-score .mine { color: var(--red); }
.series-end.drew .se-score .mine { color: var(--gold); }
.series-end .se-score i { font-style: normal; color: var(--muted); font-size: 26px; }
.series-end .se-legs { display: grid; gap: 6px; margin-top: 4px; text-align: left; }
.se-leg {
  display: flex; align-items: center; gap: 9px; padding: 7px 10px; border-radius: 12px;
  border: 1px solid var(--line); background: rgba(255,255,255,.03);
}
.se-leg .se-ico { font-size: 20px; }
.se-leg b { display: block; font-size: 13px; }
.se-leg small { display: block; font-size: 10.5px; color: var(--muted); }
.se-leg .se-mark { font-family: var(--head); font-weight: 900; font-size: 13px; color: var(--muted); }
.se-leg.win { border-color: color-mix(in srgb, var(--lime) 45%, transparent); }
.se-leg.win .se-mark { color: var(--lime); }
.se-leg.loss { border-color: color-mix(in srgb, var(--red) 40%, transparent); }
.se-leg.loss .se-mark { color: var(--red); }
.se-leg.skip { opacity: .45; }
.se-leg.skip .se-mark { font-size: 10px; font-weight: 700; letter-spacing: .04em; }
@media (prefers-reduced-motion: reduce) { .series-end .se-crest { animation: none; } }
/* the series score, always visible in a ranked room */
.series-pill { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: 999px;
  background: linear-gradient(180deg, #0a0820, #141034); border: 1px solid var(--rim);
  font-family: var(--head); font-size: 12px; font-weight: 800; color: var(--gold);
  /* the shot clock sits beside it now; a score that wraps to two lines reads
     as the bar being broken rather than as the bar being full */
  white-space: nowrap; flex: 0 0 auto; }

/* ============================================================
   GAME MOTION
   Transform and opacity only — those are the two things a phone
   can animate without recalculating layout, which is the whole
   difference between smooth and stuttering.
   ============================================================ */
.fx-drop  { animation: fxDrop .34s var(--ease-out) both; }
.fx-place { animation: fxPlace .3s var(--spring) both; }
.fx-deal  { animation: fxDeal .38s var(--ease-out) both; }
.fx-flip  { animation: fxFlip .42s var(--ease-in-out) both; }
.fx-slide { animation: fxSlide .3s var(--ease-out) both; }
.fx-pop   { animation: fxPop .26s var(--spring) both; }

@keyframes fxDrop  { from { transform: translateY(-140%); opacity: 0; } 70% { transform: translateY(6%); } to { transform: none; opacity: 1; } }
@keyframes fxPlace { from { transform: scale(.4) rotate(-8deg); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes fxDeal  { from { transform: translateY(40%) scale(.7); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes fxFlip  { from { transform: rotateY(90deg) scale(.85); } to { transform: none; } }
@keyframes fxSlide { from { transform: translateX(-28%); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes fxPop   { from { transform: scale(.55); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------- the table ---------- */
/* Players sit around the board instead of being listed above it. With two you
   face each other; a third takes the left rail, a fourth the right. */
.fx-table {
  display: grid; gap: 6px; align-items: center; justify-items: center;
  grid-template-areas: "tl top tr" "left board right" "bl bottom br";
  grid-template-columns: minmax(0, auto) minmax(0, 1fr) minmax(0, auto);
}
.fx-board { grid-area: board; width: 100%; min-width: 0; }
.fx-seat.at-top { grid-area: top; }
.fx-seat.at-bottom { grid-area: bottom; }
.fx-seat.at-left { grid-area: left; }
.fx-seat.at-right { grid-area: right; }
.fx-seat {
  display: flex; align-items: center; gap: 6px; padding: 4px 9px; border-radius: 999px;
  background: linear-gradient(180deg, rgba(34,28,82,.9), rgba(17,14,46,.9));
  border: 1px solid var(--rim-soft); font-size: 12px; font-weight: 700; max-width: 100%;
  transition: box-shadow var(--t-move) var(--ease-out), border-color var(--t-move) var(--ease-out), transform var(--t-move) var(--spring);
}
.fx-seat .fx-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 88px; }
.fx-seat .fx-count { color: var(--gold); font-family: var(--head); }
/* whose turn it is, said with light rather than a label */
.fx-seat.is-turn {
  border-color: var(--gold); transform: scale(1.06);
  box-shadow: 0 0 0 1px rgba(255,207,92,.4), 0 0 18px rgba(255,207,92,.45);
  animation: seatPulse 1.9s var(--ease-in-out) infinite;
}
@keyframes seatPulse { 0%, 100% { box-shadow: 0 0 0 1px rgba(255,207,92,.4), 0 0 14px rgba(255,207,92,.35); } 50% { box-shadow: 0 0 0 1px rgba(255,207,92,.6), 0 0 26px rgba(255,207,92,.65); } }
/* Three dots on the seat of a bot that is mid-thought. Two seconds of silence
   reads as a frozen game; two seconds of dots reads as someone deciding. */
.fx-seat .fx-think { display: inline-flex; align-items: center; gap: 2px; margin-left: 1px; }
.fx-seat .fx-think b {
  width: 3.5px; height: 3.5px; border-radius: 50%; background: var(--cyan); opacity: .35;
  animation: thinkDot 1.15s var(--ease-in-out) infinite;
}
.fx-seat .fx-think b:nth-child(2) { animation-delay: .16s; }
.fx-seat .fx-think b:nth-child(3) { animation-delay: .32s; }
@keyframes thinkDot { 0%, 70%, 100% { opacity: .3; transform: translateY(0); } 35% { opacity: 1; transform: translateY(-2.5px); } }
@media (prefers-reduced-motion: reduce) { .fx-seat .fx-think b { animation: none; opacity: .75; } }
.fx-seat.at-left, .fx-seat.at-right { writing-mode: horizontal-tb; font-size: 11px; padding: 4px 7px; }
.fx-seat.at-left .fx-name, .fx-seat.at-right .fx-name { max-width: 56px; }
@media (max-width: 360px) {
  .fx-seat { font-size: 11px; padding: 3px 7px; }
  .fx-seat .fx-name { max-width: 64px; }
}

@media (prefers-reduced-motion: reduce) {
  .fx-drop, .fx-place, .fx-deal, .fx-flip, .fx-slide, .fx-pop { animation: none; }
  .fx-seat.is-turn { animation: none; }
  .fx-seat { transition: none; }
}

/* Dominoes: the line is the board, so it gets the room. */
.dom-table .fx-board { padding: 2px 0; }
.dom-table .dom-line { min-height: 54px; }
.dom-laid { display: inline-block; }

/* Colour Clash at a table: the pile in the middle, hands counted at each seat. */
.cc-table-ring .cc-center { justify-content: center; }
.cc-table-ring .cc-dir { text-align: center; font-size: 11px; margin-top: 2px; letter-spacing: .06em; }
.fx-seat .uno { color: var(--red); font-style: normal; animation: unoBlink 1s steps(2) infinite; }
@keyframes unoBlink { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .fx-seat .uno { animation: none; } }

/* ---------- the prize board ---------- */
/* Five across, four down, every tile face up with both prices. */
/* The board sits inside a frame so it reads as one object — a game board —
   rather than twenty loose buttons. No overflow:hidden: the highlight scales
   tiles past the edge and clipping it would eat the glow. */
.board-frame {
  position: relative; min-width: 0; margin-top: 6px;
  padding: 9px; border-radius: 18px;
  border: 2px solid color-mix(in srgb, var(--gold) 55%, transparent);
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(255,207,92,.12), transparent 60%),
    color-mix(in srgb, var(--panel) 80%, #000);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.07),
    inset 0 2px 14px rgba(0,0,0,.45),
    0 6px 20px rgba(0,0,0,.42);
  transition: border-color var(--t-quick) var(--ease-out), box-shadow var(--t-quick) var(--ease-out);
}
/* the frame lights up for the length of a spin, so the board itself is what
   is "running" rather than one tile flickering inside a dead box */
.board-frame.spinning {
  border-color: var(--gold);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.12),
    inset 0 2px 14px rgba(0,0,0,.45),
    0 0 26px color-mix(in srgb, var(--gold) 45%, transparent);
}
.prize-board {
  display: grid; grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr)); min-width: 0;
  gap: 5px;
}
.pz-tile {
  /* A grid item defaults to min-width:auto, which means it refuses to go
     narrower than its own content — five of those across a 320px phone is how
     the board pushed the page sideways. */
  min-width: 0; overflow: hidden;
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  gap: 1px; padding: 7px 3px 6px; min-height: 92px; border-radius: 11px; cursor: pointer;
  background: var(--plate);
  border: 1.5px solid color-mix(in srgb, var(--rc, #fff) 45%, transparent);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 3px 8px rgba(0,0,0,.4);
  transition: transform var(--t-tap) var(--ease-out), box-shadow var(--t-quick) var(--ease-out),
              border-color var(--t-quick) var(--ease-out), background var(--t-quick) linear;
}
.pz-tile:not(.gone):active { transform: scale(.95); }
.pz-tile .t-emoji { font-size: 21px; line-height: 1.05; }
.pz-tile .t-name {
  font-size: 9px; line-height: 1.15; text-align: center; color: var(--text); opacity: .92;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  max-width: 100%; min-width: 0; overflow-wrap: anywhere;
}
.pz-tile .t-price { display: flex; flex-direction: column; align-items: center; margin-top: auto; line-height: 1.15; }
.pz-tile .t-price b { font-size: 10px; color: var(--yellow); font-weight: 800; }
.pz-tile .t-price i { font-size: 9px; color: var(--cyan); font-style: normal; }
.pz-tile .t-odds { position: absolute; top: 3px; right: 4px; font-size: 8px; color: var(--muted); }
.pz-tile .t-done { margin-top: auto; font-size: 14px; color: var(--lime); }
.pz-tile .t-spin { margin-top: auto; font-size: 8.5px; color: var(--muted); letter-spacing: .04em; }
.pz-tile.gone { opacity: .34; cursor: default; }
.pz-tile.r-legendary { border-color: var(--gold); }

/* the highlight as it walks the board */
.pz-tile.lit {
  transform: scale(1.08); z-index: 2;
  border-color: #fff;
  background: linear-gradient(180deg, rgba(255,255,255,.22), transparent 70%), var(--plate);
  box-shadow: 0 0 0 2px rgba(255,255,255,.55), 0 0 22px color-mix(in srgb, var(--rc, #fff) 70%, transparent);
}
/* and where it stopped */
.pz-tile.won {
  transform: scale(1.12); z-index: 3; border-color: var(--gold);
  box-shadow: 0 0 0 2px var(--gold), 0 0 32px rgba(255,207,92,.8);
  animation: tileWon 1.1s var(--ease-out) 3;
}
@keyframes tileWon { 0%, 100% { filter: none; } 45% { filter: brightness(1.7); } }

.spin-box { display: flex; flex-direction: column; align-items: stretch; gap: 7px; margin-top: 2px; }
.spin-note { text-align: center; font-size: 12px; }
.spin-buy { display: flex; gap: 7px; justify-content: center; }
.spin-buy .btn { flex: 1; }

@media (max-width: 360px) {
  .board-frame { padding: 6px; border-radius: 15px; }
  .pz-tile { min-height: 84px; padding: 6px 2px 5px; }
  .pz-tile .t-emoji { font-size: 18px; }
  .pz-tile .t-name { font-size: 8px; }
}
@media (prefers-reduced-motion: reduce) {
  .tile, .pz-tile.lit, .pz-tile.won { transition: none; transform: none; }
  .pz-tile.won { animation: none; }
  .board-frame { transition: none; }
}

/* ---------- support: reports ---------- */
.report-mine { display: flex; flex-direction: column; gap: 6px; margin-top: 2px; }
.report-row {
  display: flex; align-items: center; gap: 9px; min-width: 0;
  padding: 8px 10px; border-radius: 12px; background: var(--plate); border: 1px solid var(--rim-soft);
}
.report-row .rr-kind { font-size: 17px; flex: none; }
.report-row .grow { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.report-row b { font-size: 12.5px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.report-row small { font-size: 10.5px; }
.report-row .rr-status {
  flex: none; font-size: 10px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 999px; background: rgba(255,255,255,.07); border: 1px solid var(--rim-soft);
}
.report-row .rr-status.cyan { color: var(--cyan); border-color: color-mix(in srgb, var(--cyan) 45%, transparent); }
.report-row .rr-status.lime { color: var(--lime); border-color: color-mix(in srgb, var(--lime) 45%, transparent); }
.report-row .rr-status.muted { color: var(--muted); }

/* the picker in the report sheet: big taps, because this is reached by someone
   already annoyed and usually on a phone */
.report-kinds { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; }
.report-kinds .rk {
  min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 10px 11px; border-radius: 13px; text-align: left; cursor: pointer;
  background: var(--plate); border: 1.5px solid var(--rim-soft); color: var(--text);
  transition: border-color var(--t-quick) var(--ease-out), background var(--t-quick) linear, transform var(--t-tap) var(--ease-out);
}
.report-kinds .rk:active { transform: scale(.96); }
.report-kinds .rk.on { border-color: var(--cyan); background: linear-gradient(180deg, rgba(58,226,255,.14), transparent 75%), var(--plate); }
.report-kinds .rk-emoji { font-size: 19px; line-height: 1; }
.report-kinds .rk-name { font-size: 12.5px; font-weight: 800; line-height: 1.2; overflow-wrap: anywhere; }
.report-kinds .rk small { font-size: 10px; color: var(--muted); line-height: 1.25; overflow-wrap: anywhere; }
#report-form { display: flex; flex-direction: column; gap: 8px; }
#report-text {
  width: 100%; min-width: 0; box-sizing: border-box; resize: vertical;
  padding: 11px 12px; border-radius: 13px; font: inherit; font-size: 14px; line-height: 1.4;
  background: rgba(0,0,0,.28); border: 1px solid var(--rim-soft); color: var(--text);
}
#report-text:focus { outline: none; border-color: var(--cyan); }

/* ---------- dev menu: the reports inbox ---------- */
.dev-reports { display: flex; flex-direction: column; gap: 8px; }
.dev-report {
  min-width: 0; padding: 10px 11px; border-radius: 13px;
  background: var(--plate); border: 1px solid var(--rim-soft); border-left: 3px solid var(--rim-soft);
}
.dev-report.s-new { border-left-color: var(--yellow); }
.dev-report.s-open { border-left-color: var(--cyan); }
.dev-report.s-fixed { border-left-color: var(--lime); }
.dev-report.s-closed { opacity: .55; }
.dev-report .dr-head { display: flex; align-items: baseline; gap: 7px; min-width: 0; flex-wrap: wrap; }
.dev-report .dr-id { font-family: var(--head); font-size: 11.5px; color: var(--gold); }
.dev-report .dr-who { font-size: 12px; font-weight: 700; overflow-wrap: anywhere; }
.dev-report .dr-when { font-size: 10.5px; color: var(--muted); margin-left: auto; }
.dev-report .dr-text { font-size: 13px; line-height: 1.4; margin: 6px 0; overflow-wrap: anywhere; white-space: pre-wrap; }
.dev-report .dr-ctx { display: flex; flex-wrap: wrap; gap: 4px; }
.dev-report .dr-ctx span {
  font-size: 10px; padding: 2px 6px; border-radius: 999px;
  background: rgba(255,255,255,.06); border: 1px solid var(--rim-soft); color: var(--muted);
}
.dev-report .dr-notes { margin: 6px 0 0; display: flex; flex-direction: column; gap: 3px; }
.dev-report .dr-notes div { font-size: 11px; color: var(--muted); overflow-wrap: anywhere; }
.dev-report .dr-acts { display: flex; gap: 5px; margin-top: 8px; flex-wrap: wrap; }
.dev-report .dr-acts .btn { flex: 1 1 auto; min-width: 74px; }
.dev-report .dr-note {
  width: 100%; min-width: 0; box-sizing: border-box; margin-top: 7px;
  padding: 8px 10px; border-radius: 10px; font: inherit; font-size: 12.5px;
  background: rgba(0,0,0,.28); border: 1px solid var(--rim-soft); color: var(--text);
}
.dev-report .dr-note:focus { outline: none; border-color: var(--cyan); }
/* the filter row can be five wide; on a phone it wraps rather than shrinking
   each label to an unreadable sliver */
.segmented.wrap { flex-wrap: wrap; }
.segmented.wrap button { flex: 1 1 88px; }

/* ---------- play tab ---------- */
.play-panel { gap: 10px; }
.segmented.big button { font-size: 14px; padding: 11px 10px; font-weight: 800; }
.play-acts { display: flex; flex-direction: column; gap: 7px; }
.btn.big { font-size: 16px; padding: 14px 16px; }

/* Ranked explains itself instead of showing a picker it is going to ignore. */
.ranked-card {
  display: flex; flex-direction: column; gap: 9px; min-width: 0;
  padding: 12px; border-radius: 15px;
  border: 1.5px solid color-mix(in srgb, var(--gold) 40%, transparent);
  background:
    radial-gradient(120% 90% at 50% -20%, rgba(255,207,92,.12), transparent 60%),
    color-mix(in srgb, var(--panel) 82%, #000);
}
.ranked-card .rk-line { display: flex; align-items: flex-start; gap: 10px; min-width: 0; }
.ranked-card .rk-badge {
  flex: none; width: 30px; height: 30px; border-radius: 10px; font-size: 15px;
  display: grid; place-items: center;
  background: rgba(255,255,255,.06); border: 1px solid var(--rim-soft);
}
.ranked-card .grow { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ranked-card b { font-size: 13.5px; font-weight: 800; }
.ranked-card small { font-size: 11.5px; color: var(--muted); line-height: 1.35; overflow-wrap: anywhere; }
.rk-pool { min-width: 0; }
.rk-pool summary { font-size: 12px; color: var(--cyan); cursor: pointer; padding: 3px 0; }
.rk-pool-list { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.rk-pool-list span {
  font-size: 11px; padding: 3px 8px; border-radius: 999px; overflow-wrap: anywhere;
  background: rgba(255,255,255,.06); border: 1px solid var(--rim-soft); color: var(--text);
}
.gap-note { margin: 6px 0 0; font-size: 12px; line-height: 1.35; text-align: center; overflow-wrap: anywhere; }
.gap-note.lime { color: var(--lime); }

/* ---------- buying a board tile ---------- */
.buy-tile {
  display: flex; align-items: center; gap: 11px; min-width: 0;
  padding: 11px; border-radius: 14px; background: var(--plate); border: 1px solid var(--rim-soft);
}
.buy-tile .bt-emoji {
  flex: none; width: 52px; height: 52px; border-radius: 13px; font-size: 26px;
  display: grid; place-items: center; background: rgba(255,255,255,.05); border: 1.5px solid var(--rim-soft);
}
.buy-tile .bt-emoji.r-rare { border-color: color-mix(in srgb, var(--cyan) 55%, transparent); }
.buy-tile .bt-emoji.r-epic { border-color: color-mix(in srgb, #a36bff 60%, transparent); }
.buy-tile .bt-emoji.r-legendary { border-color: var(--gold); }
.buy-tile .grow { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.buy-tile b { font-size: 15px; font-weight: 800; overflow-wrap: anywhere; }
.buy-tile small { font-size: 11.5px; line-height: 1.3; overflow-wrap: anywhere; }
/* The sum, written out. A price on its own is a number; a price next to what
   you have left is a decision. */
.buy-maths { display: flex; flex-direction: column; gap: 4px; padding: 2px 2px 0; }
.buy-maths div { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; }
.buy-maths span { color: var(--muted); }
.buy-maths b { font-family: var(--head); font-weight: 800; }
.buy-maths .cost { color: var(--yellow); }
.buy-maths .after { border-top: 1px solid var(--rim-soft); padding-top: 5px; margin-top: 2px; }
.buy-maths .after b.bad { color: var(--pink); }

/* ---------- top bar: wallet, bell, face ---------- */
/* The wallet chips are buttons now (tap them to reach the store), so they need
   the chrome reset — and a nowrap, or the emoji and the number stack and the
   top bar doubles in height on a narrow phone. */
#top .coins {
  font: inherit; font-family: var(--head); cursor: pointer;
  white-space: nowrap; flex: none; padding: 4px 8px; font-size: 12px; gap: 4px;
  transition: transform var(--t-tap) var(--ease-out);
}
#top .coins:active { transform: scale(.94); }
.top-btn {
  position: relative; flex: none; width: 31px; height: 31px; padding: 0; margin-left: 3px;
  display: grid; place-items: center; cursor: pointer;
  border-radius: 999px; border: 1px solid var(--rim-soft);
  background: rgba(255,255,255,.06); color: var(--text); font-size: 14px;
  transition: transform var(--t-tap) var(--ease-out), border-color var(--t-quick) var(--ease-out);
}
.top-btn:active { transform: scale(.92); }
.top-btn.on { border-color: var(--cyan); }
/* the face itself is the button, so the avatar fills it */
.top-btn.pfp { overflow: hidden; padding: 0; border-width: 1.5px; border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.top-btn.pfp svg { display: block; width: 100%; height: 100%; }
.top-dot {
  position: absolute; top: -4px; right: -4px; min-width: 15px; height: 15px; padding: 0 4px;
  display: grid; place-items: center; box-sizing: border-box;
  border-radius: 999px; background: var(--pink); color: #fff;
  font-size: 9.5px; font-weight: 800; line-height: 1;
  border: 2px solid var(--bg);
}
.top-dot.dot-only { min-width: 11px; width: 11px; height: 11px; padding: 0; }

/* ---------- the avatar menu ---------- */
.menu-head { display: flex; align-items: center; gap: 11px; min-width: 0; }
.menu-head .grow { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.menu-head .mh-name { font-family: var(--head); font-size: 19px; font-weight: 800; overflow-wrap: anywhere; }
.menu-head .mh-title { font-size: 12px; color: var(--gold); overflow-wrap: anywhere; }
.menu-head .mh-meta { font-size: 12px; color: var(--muted); }
.menu-list { display: flex; flex-direction: column; gap: 6px; }
.menu-row {
  display: flex; align-items: center; gap: 11px; min-width: 0; width: 100%; cursor: pointer; text-align: left;
  padding: 11px; border-radius: 14px; color: var(--text);
  background: var(--plate); border: 1px solid var(--rim-soft);
  transition: transform var(--t-tap) var(--ease-out), border-color var(--t-quick) var(--ease-out);
}
.menu-row:active { transform: scale(.975); }
.menu-row .mr-ico {
  flex: none; width: 34px; height: 34px; border-radius: 11px; font-size: 17px;
  display: grid; place-items: center; background: rgba(255,255,255,.06); border: 1px solid var(--rim-soft);
}
.menu-row .grow { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.menu-row b { font-size: 14px; font-weight: 800; overflow-wrap: anywhere; }
.menu-row small { font-size: 11px; color: var(--muted); overflow-wrap: anywhere; }
.menu-row .mr-badge {
  flex: none; min-width: 20px; height: 20px; padding: 0 6px; box-sizing: border-box;
  display: grid; place-items: center; border-radius: 999px;
  background: var(--pink); color: #fff; font-size: 11px; font-weight: 800;
}
.menu-row .mr-go { flex: none; color: var(--muted); font-size: 19px; line-height: 1; }

/* ---------- notifications ---------- */
.notif-list { display: flex; flex-direction: column; gap: 6px; }
.notif {
  display: flex; align-items: center; gap: 9px; min-width: 0;
  padding: 9px 10px; border-radius: 13px; background: var(--plate); border: 1px solid var(--rim-soft);
}
.notif .nf-ico { flex: none; width: 26px; height: 26px; display: grid; place-items: center; font-size: 16px; }
.notif .nf-ico svg { display: block; width: 100%; height: 100%; border-radius: 999px; }
.notif .grow { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.notif b { font-size: 13px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.notif small { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.field-note { margin: 6px 0 0; font-size: 11.5px; line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
.email-row {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  padding: 9px 11px; border-radius: 12px; background: var(--plate); border: 1px solid var(--rim-soft);
}
.email-row .em-ok { flex: none; color: var(--lime); font-weight: 800; }
.email-row b { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The no-loss promise, said on the board rather than buried in terms — it is
   the reason a paid spin is a purchase and not a bet, so it belongs next to
   the button. */
.spin-promise {
  display: flex; align-items: flex-start; gap: 9px; min-width: 0;
  padding: 10px 11px; border-radius: 13px;
  background: color-mix(in srgb, var(--lime) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--lime) 32%, transparent);
}
.spin-promise .sp-tick {
  flex: none; width: 21px; height: 21px; border-radius: 999px; font-size: 12px; font-weight: 800;
  display: grid; place-items: center; background: color-mix(in srgb, var(--lime) 22%, transparent); color: var(--lime);
}
.spin-promise .grow { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.spin-promise b { font-size: 12.5px; font-weight: 800; color: var(--lime); overflow-wrap: anywhere; }
.spin-promise small { font-size: 11.5px; line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
.spend-note { text-align: center; }
/* announcements and gifts in the notifications tray */
.notif.cast { align-items: flex-start; }
.notif.cast b { white-space: normal; overflow-wrap: anywhere; }
.notif.cast .cast-text { white-space: normal; overflow: visible; line-height: 1.35; }
.notif.cast.gift { border-color: color-mix(in srgb, var(--gold) 40%, transparent); background: color-mix(in srgb, var(--gold) 7%, var(--plate)); }
.cast-loot { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; white-space: normal; overflow: visible; }
.cast-loot span {
  font-size: 10.5px; padding: 2px 7px; border-radius: 999px; color: var(--gold);
  background: rgba(255,207,92,.12); border: 1px solid rgba(255,207,92,.3);
}

/* ---------- pet shop tabs, forge, slots ---------- */
.shop-tabs {
  display: flex; gap: 5px; overflow-x: auto; padding-bottom: 3px; margin: 0 -2px;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.shop-tabs::-webkit-scrollbar { display: none; }
.shop-tab {
  flex: none; display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  padding: 7px 11px; border-radius: 999px; white-space: nowrap;
  background: var(--plate); border: 1px solid var(--rim-soft); color: var(--muted);
  font-size: 12px; font-weight: 800;
  transition: color var(--t-quick) var(--ease-out), border-color var(--t-quick) var(--ease-out), background var(--t-quick) linear;
}
.shop-tab.on { color: var(--text); border-color: var(--cyan); background: color-mix(in srgb, var(--cyan) 14%, var(--plate)); }

.forge-bag { display: flex; flex-wrap: wrap; gap: 5px; }
.forge-bag span {
  font-size: 11px; padding: 4px 9px; border-radius: 999px;
  background: var(--plate); border: 1px solid var(--rim-soft);
}
.forge-bag span b { color: var(--gold); font-family: var(--head); }
.forge-bag span.none { opacity: .45; }
.forge-list { display: flex; flex-direction: column; gap: 7px; }
.recipe {
  min-width: 0; padding: 10px 11px; border-radius: 14px;
  background: var(--plate); border: 1.5px solid var(--rim-soft);
}
.recipe.ready { border-color: color-mix(in srgb, var(--lime) 45%, transparent); }
.recipe .rc-head { display: flex; align-items: center; gap: 9px; min-width: 0; }
.recipe .rc-emoji {
  flex: none; width: 34px; height: 34px; border-radius: 11px; font-size: 18px;
  display: grid; place-items: center; background: rgba(255,255,255,.06); border: 1px solid var(--rim-soft);
}
.recipe .grow { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.recipe b { font-size: 13.5px; font-weight: 800; overflow-wrap: anywhere; }
.recipe small { font-size: 11px; color: var(--muted); overflow-wrap: anywhere; }
.recipe .rc-needs { display: flex; flex-wrap: wrap; gap: 4px; margin: 8px 0; }
.recipe .rc-needs span {
  font-size: 11px; padding: 3px 8px; border-radius: 999px;
  background: rgba(255,255,255,.05); border: 1px solid var(--rim-soft);
}
.recipe .rc-needs .ok { color: var(--lime); border-color: color-mix(in srgb, var(--lime) 35%, transparent); }
.recipe .rc-needs .short { color: var(--muted); }

/* the three worn slots on a pet's card */
.slot-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.slot {
  position: relative; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 9px 5px; border-radius: 13px; text-align: center;
  background: var(--plate); border: 1.5px dashed var(--rim-soft);
}
.slot.filled { border-style: solid; border-color: color-mix(in srgb, var(--cyan) 45%, transparent); }
.slot .sl-ico { font-size: 20px; line-height: 1; }
.slot .sl-name { font-size: 10px; color: var(--muted); overflow-wrap: anywhere; line-height: 1.2; }
.slot.filled .sl-name { color: var(--text); font-weight: 700; }
.slot .sl-off {
  position: absolute; top: -6px; right: -6px; width: 20px; height: 20px; cursor: pointer;
  display: grid; place-items: center; border-radius: 999px; font-size: 10px;
  background: var(--panel); border: 1px solid var(--rim-soft); color: var(--muted);
}
.bag-group { margin-top: 8px; }
.bag-group .bg-head { font-size: 11px; font-weight: 800; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; margin-bottom: 5px; }

/* hatching is a draw now, so it gets a reveal */
.hatch-odds { display: flex; flex-wrap: wrap; gap: 5px; }
.hatch-odds span {
  display: inline-flex; gap: 5px; align-items: baseline;
  font-size: 11px; padding: 4px 9px; border-radius: 999px; color: var(--muted);
  background: var(--plate); border: 1px solid color-mix(in srgb, var(--rc) 40%, transparent);
}
.hatch-odds b { color: var(--rc); font-size: 11px; }
.hatch-reveal {
  display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0;
  padding: 16px 12px; border-radius: 18px;
  border: 2px solid color-mix(in srgb, var(--rc) 60%, transparent);
  background: radial-gradient(120% 80% at 50% 0%, color-mix(in srgb, var(--rc) 18%, transparent), transparent 70%), var(--plate);
}
.hatch-reveal .hr-name { font-family: var(--head); font-size: 22px; font-weight: 800; overflow-wrap: anywhere; }
.hatch-reveal .hr-rarity { font-size: 13px; font-weight: 800; overflow-wrap: anywhere; }
.hatch-reveal .hr-fac { font-size: 11.5px; color: var(--muted); overflow-wrap: anywhere; }
.hatch-reveal .hr-fac.rare { color: var(--gold); }
.hatch-reveal.r-legendary { animation: tileWon 1.2s var(--ease-out) 3; }
/* what a fight paid, in words */
.haul-rows { display: flex; flex-direction: column; gap: 5px; margin: 8px 0 2px; }
.haul-row {
  display: flex; align-items: center; gap: 9px; min-width: 0; text-align: left;
  padding: 7px 10px; border-radius: 12px;
  background: rgba(255,255,255,.05); border: 1px solid var(--rim-soft);
}
.haul-row .hr-ico { flex: none; font-size: 17px; }
.haul-row .grow { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.haul-row b { font-size: 13px; font-weight: 800; overflow-wrap: anywhere; }
.haul-row small { font-size: 10.5px; color: var(--muted); line-height: 1.3; overflow-wrap: anywhere; }

/* ---------- the walkthrough ---------- */
.tour-link {
  display: flex; align-items: center; gap: 12px; width: 100%; min-width: 0; cursor: pointer; text-align: left;
  padding: 12px 14px; border-radius: var(--radius); border: 1px solid var(--line);
  background: var(--panel); color: var(--text);
  transition: transform var(--t-tap) var(--ease-out), border-color var(--t-quick) var(--ease-out);
}
.tour-link:active { transform: scale(.98); }
.tour-link .gi { font-size: 26px; flex: none; }
.tour-link .grow { display: flex; flex-direction: column; min-width: 0; }
.tour-link b { font-size: 15px; overflow-wrap: anywhere; }
.tour-link small { color: var(--muted); font-size: 12px; overflow-wrap: anywhere; }

.modal.tour { max-width: 340px; text-align: center; }
.tour .tour-dots { display: flex; justify-content: center; gap: 5px; margin-bottom: 4px; }
.tour .tour-dots span {
  width: 6px; height: 6px; border-radius: 999px; background: rgba(255,255,255,.18);
  transition: background var(--t-quick) linear, width var(--t-move) var(--spring);
}
.tour .tour-dots span.done { background: rgba(255,255,255,.4); }
.tour .tour-dots span.on { width: 18px; background: var(--accent); }
.tour .tour-icon {
  font-size: 42px; line-height: 1; margin: 6px 0 2px;
  animation: tourPop .45s var(--spring) both;
}
@keyframes tourPop { from { transform: scale(.4) rotate(-12deg); opacity: 0; } to { transform: none; opacity: 1; } }
.tour .big { font-size: 20px; }
.tour p.muted { line-height: 1.45; overflow-wrap: anywhere; }
.tour .tour-note {
  margin: 8px 0 0; padding: 9px 11px; border-radius: 12px; font-size: 12px; line-height: 1.4;
  color: var(--lime); background: color-mix(in srgb, var(--lime) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--lime) 28%, transparent); overflow-wrap: anywhere;
}
.tour .actions { margin-top: 12px; }
@media (prefers-reduced-motion: reduce) { .tour .tour-icon { animation: none; } }
.crash-hint { color: var(--yellow); border: 1px solid color-mix(in srgb, var(--yellow) 35%, transparent); background: color-mix(in srgb, var(--yellow) 8%, transparent); border-radius: 12px; padding: 9px 11px; }

/* ---------- the test account ---------- */
/* Loud on purpose. A test account you forget you are in is worse than not
   having one, so it says so on every screen until you switch back. */
.banner.sandbox {
  border-color: rgba(255,207,92,.6);
  background: repeating-linear-gradient(135deg, rgba(255,207,92,.10) 0 10px, rgba(255,207,92,.04) 10px 20px);
  color: var(--gold);
}
.banner.sandbox b { color: var(--gold); }
.top-btn.pfp.is-sandbox { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold), 0 0 12px rgba(255,207,92,.5); }
.sandbox-panel { border-color: color-mix(in srgb, var(--gold) 45%, transparent); }

/* ---------- before launch ---------- */
/* The waiting room. It has one job — say when — so the number is the largest
   thing on the page and everything else explains it. */
.pre-strip {
  display: flex; align-items: baseline; justify-content: center; gap: 10px;
  margin: 0 0 14px; padding: 10px 14px; border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--cyan) 35%, transparent);
  background: color-mix(in srgb, var(--cyan) 8%, transparent);
}
.pre-strip b {
  font-size: 28px; line-height: 1; color: var(--cyan);
  font-variant-numeric: tabular-nums;
}
.pre-strip span { font-size: 13px; color: var(--muted); }

.panel.wait { align-items: stretch; text-align: center; }
.wait-clock { padding: 12px 0 4px; }
.wait-big {
  font-size: clamp(74px, 26vw, 132px); line-height: .9; font-weight: 900;
  font-variant-numeric: tabular-nums; letter-spacing: -.04em;
  background: linear-gradient(180deg, var(--pink), var(--purple));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.wait-cap {
  margin-top: 6px; font-size: 13px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted);
}
.wait-fine {
  margin-top: 10px; font-size: 20px; font-variant-numeric: tabular-nums;
  letter-spacing: .06em; color: var(--cyan);
}
.wait-out {
  font-size: clamp(30px, 10vw, 48px); line-height: 1.02; font-weight: 900;
  letter-spacing: -.02em; color: var(--lime);
  text-shadow: 0 0 26px color-mix(in srgb, var(--lime) 45%, transparent);
}
.wait-clock.live .wait-cap { color: var(--lime); }

.wait-name {
  display: flex; align-items: center; gap: 12px; text-align: left;
  padding: 10px 12px; border-radius: 14px;
  border: 1px solid var(--line); background: rgba(255,255,255,.03);
}
.wait-name .name { font-weight: 700; font-size: 16px; overflow-wrap: anywhere; }
.wait-saved { font-size: 12px; color: var(--lime); }

ul.wait-list { margin: 0; padding-left: 18px; display: grid; gap: 7px; font-size: 14px; }
ul.wait-list li { color: var(--muted); }
ul.wait-list b { color: var(--text); }
.dev-area {
  width: 100%; border-radius: 10px; border: 1px solid var(--line);
  background: rgba(5,5,20,.6); color: var(--text); padding: 8px 10px;
  font-size: 14px; font-family: var(--body); resize: vertical; min-height: 84px;
}
.tester-list { display: grid; gap: 5px; }
.tester-row { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 10px; border: 1px solid var(--line); background: rgba(255,255,255,.03); font-size: 13px; }
.tester-row .btn.small { min-height: 30px; font-size: 12px; padding: 2px 10px; }
.tester-result { display: grid; gap: 4px; }
.tester-result .tr { font-size: 12.5px; padding: 6px 9px; border-radius: 9px; overflow-wrap: anywhere; }
.tester-result .tr.ok { color: var(--lime); background: color-mix(in srgb, var(--lime) 9%, transparent); border: 1px solid color-mix(in srgb, var(--lime) 30%, transparent); }
.tester-result .tr.meh { color: var(--muted); background: rgba(255,255,255,.03); border: 1px solid var(--line); }
.tester-result .tr.bad { color: var(--red); background: color-mix(in srgb, var(--red) 9%, transparent); border: 1px solid color-mix(in srgb, var(--red) 32%, transparent); }

/* ---------- the tag beside a name ---------- */
/* Small enough to sit inline with a name at any size, and coloured by the
   rarity of the title so a granted one does not look like a shop one. */
.ptag {
  display: inline-flex; align-items: center; gap: 3px;
  margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  font-family: var(--head); font-size: 10px; font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase; white-space: nowrap;
  vertical-align: middle; line-height: 1.7;
  border: 1px solid color-mix(in srgb, var(--muted) 45%, transparent);
  background: color-mix(in srgb, var(--muted) 12%, transparent);
  color: var(--muted);
}
.ptag.rare {
  border-color: color-mix(in srgb, var(--cyan) 55%, transparent);
  background: color-mix(in srgb, var(--cyan) 12%, transparent);
  color: var(--cyan);
}
.ptag.epic {
  border-color: color-mix(in srgb, var(--purple) 60%, transparent);
  background: color-mix(in srgb, var(--purple) 16%, transparent);
  color: #c9a6ff;
}
.ptag.legendary {
  border-color: color-mix(in srgb, var(--gold) 60%, transparent);
  background: color-mix(in srgb, var(--gold) 14%, transparent);
  color: var(--gold);
  box-shadow: 0 0 10px color-mix(in srgb, var(--gold) 22%, transparent);
}
.lb-row .ptag, .seat .ptag, .friend .ptag { font-size: 9px; padding: 1px 6px; }

/* ---------- test nights ---------- */
/* Sits above everything on Play until launch. One question — who is here and
   where are they — answered in one tap. */
.panel.testnight {
  border-color: color-mix(in srgb, var(--cyan) 42%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--cyan) 7%, transparent), transparent 60%), var(--panel);
}
.tn-head { display: flex; align-items: center; gap: 10px; }
.tn-head b { display: block; font-size: 15px; }
.tn-head small { display: block; font-size: 12px; color: var(--muted); }
.tn-badge {
  font-family: var(--head); font-weight: 800; font-size: 11px; letter-spacing: .1em;
  padding: 5px 9px; border-radius: 8px; white-space: nowrap;
  background: color-mix(in srgb, var(--cyan) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--cyan) 50%, transparent); color: var(--cyan);
}
.tn-people { display: flex; flex-wrap: wrap; gap: 6px; }
.tn-person {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px 3px 3px; border-radius: 999px; font-size: 12.5px;
  border: 1px solid var(--line); background: rgba(255,255,255,.04);
}
.tn-person.on { border-color: color-mix(in srgb, var(--green) 55%, transparent); color: var(--green); }
.tn-rooms { display: grid; gap: 6px; }
.tn-room {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 8px 10px; border-radius: 12px; color: var(--text);
  border: 1px solid color-mix(in srgb, var(--cyan) 35%, transparent);
  background: rgba(255,255,255,.03);
}
.tn-room .code { font-family: var(--head); font-weight: 800; letter-spacing: .12em; color: var(--cyan); font-size: 15px; }
.tn-room b { display: block; font-size: 13.5px; }
.tn-room small { display: block; font-size: 11.5px; color: var(--muted); overflow-wrap: anywhere; }
.tn-go { color: var(--lime); font-weight: 800; font-size: 13px; white-space: nowrap; }

/* ---------- what the online number is made of ---------- */
button.online-now {
  background: none; border: 0; padding: 4px 0; text-align: left; cursor: pointer;
  color: var(--muted); font: inherit; font-size: 13px;
}
/* The count is the button. No badge, no second colour — it looks exactly like
   the line it replaced, and tapping it says who is on. */
button.online-now b { color: var(--lime); font-size: 15px; }
button.online-now small { color: var(--muted); opacity: .8; font-size: 12px; }
.head-quiet {
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
}
.who-split { display: grid; gap: 8px; margin: 4px 0 10px; }
.ws-row {
  display: flex; align-items: flex-start; gap: 12px; padding: 10px 12px; border-radius: 13px;
  border: 1px solid color-mix(in srgb, var(--green) 35%, transparent);
  background: color-mix(in srgb, var(--green) 7%, transparent); text-align: left;
}
.ws-row.bot {
  border-color: color-mix(in srgb, var(--cyan) 35%, transparent);
  background: color-mix(in srgb, var(--cyan) 7%, transparent);
}
.ws-ico { font-size: 22px; line-height: 1.2; min-width: 28px; text-align: center; }
.ws-row b { display: block; font-size: 14px; }
.ws-row small { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }
.amb-split { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 7px; }
.amb-cell {
  border-radius: 13px; padding: 10px 8px; text-align: center;
  border: 1px solid var(--line); background: rgba(255,255,255,.03);
}
.amb-cell b { display: block; font-family: var(--head); font-weight: 900; font-size: 24px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.amb-cell span { display: block; font-size: 11px; color: var(--muted); margin-top: 2px; }
.amb-cell.real { border-color: color-mix(in srgb, var(--green) 45%, transparent); }
.amb-cell.real b { color: var(--green); }
.amb-cell.bot { border-color: color-mix(in srgb, var(--cyan) 45%, transparent); }
.amb-cell.bot b { color: var(--cyan); }
.amb-cell.tot { border-color: color-mix(in srgb, var(--gold) 45%, transparent); }
.amb-cell.tot b { color: var(--gold); }

/* ---------- the room's own bottom bar ---------- */
/* Readying up used to mean scrolling past the seats, the room settings and a
   grid of twenty games to reach one button. The button comes to the thumb
   instead. Leaving stays top-left: a destructive action does not belong under
   the thumb that is about to press Ready. */
.room-bar {
  /* Under the sheet and the overlay, over the page. A bar that covers the
     invite sheet is a bar that stops you inviting anybody. */
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 18;
  max-width: 540px; margin: 0 auto;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
  display: grid; gap: 8px;
  background: linear-gradient(180deg, rgba(7,7,26,0) 0%, rgba(7,7,26,.92) 22%, rgba(7,7,26,.98) 100%);
  border-top: 1px solid var(--line);
  backdrop-filter: blur(10px);
}
.room-bar .btn { min-height: 52px; font-size: 16px; }
.rb-line { display: flex; align-items: center; gap: 9px; font-size: 12.5px; color: var(--muted); }
.rb-code {
  font-family: var(--head); font-weight: 800; letter-spacing: .18em; font-size: 15px;
  color: var(--cyan); padding: 2px 8px; border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--cyan) 40%, transparent);
  background: color-mix(in srgb, var(--cyan) 9%, transparent);
}
.rb-line .btn.small { min-height: 30px; font-size: 12px; padding: 2px 11px; }
#main.with-bar { padding-bottom: calc(var(--bar-h, 150px) + 18px); }
/* the chat button steps up out of the bar's way rather than sitting on it */
body.has-room-bar #chat-fab { bottom: calc(var(--bar-h, 150px) + 14px + var(--safe-bottom)); }
@media (max-width: 380px) { .room-bar .btn { min-height: 48px; font-size: 15px; } }

/* A piece in transit sits above its neighbours so it travels over the board
   rather than under the next square along. */
.fx-moving { z-index: 6; position: relative; will-change: transform; }

/* ---------- a board gets the screen ---------- */
/* Every game used to draw itself at the top of the page with two-thirds of
   the display empty underneath, which made a 400px phone show a 230px board.
   The game screen is a column now: the board takes the room that is going
   spare, and the bars above and below it stay put. */
#main.playing {
  display: flex; flex-direction: column;
  min-height: calc(100dvh - 58px - var(--safe-top));
  padding-bottom: calc(18px + var(--safe-bottom));
}
#main.playing > .stack { flex: 1; display: flex; flex-direction: column; gap: 10px; }
/* the board itself is whatever the game calls its playing surface */
#main.playing .c4-board,
#main.playing .ck-board,
#main.playing .rv-board,
#main.playing .mm-board,
#main.playing .bs-grid,
#main.playing .dots-wrap,
#main.playing .ludo-wrap,
#main.playing .sk-canvas-wrap {
  margin-block: auto;
}
/* and it may use the full width it is given, not a cautious slice of it */
#main.playing .c4-board,
#main.playing .ck-board,
#main.playing .rv-board,
#main.playing .mm-board { width: min(100%, 460px); margin-inline: auto; }
/* Ludo's board is an SVG, so it takes its size from the wrapper rather than a
   width of its own. */
#main.playing .ludo-wrap { width: 100%; }
#main.playing .ludo-wrap svg { width: min(100%, 460px); height: auto; }
#main.playing .bs-grid { width: min(100%, 420px); margin-inline: auto; }

/* ---------- boards as objects ---------- */
/* A grid of coloured squares reads as a web page. The same grid with an edge
   that catches light from above, a shadow underneath and pieces that sit ON it
   reads as a board somebody put on a table. All of this is borders, gradients
   and shadows — nothing to download, nothing to go fuzzy on a big screen. */
#main.playing .ck-board,
#main.playing .rv-board,
#main.playing .mm-board,
#main.playing .c4-board {
  box-shadow:
    0 1px 0 rgba(255,255,255,.10) inset,
    0 -14px 28px rgba(0,0,0,.30) inset,
    0 14px 34px rgba(0,0,0,.45),
    0 2px 0 rgba(255,255,255,.05);
  border-radius: 16px;
}
#main.playing .ck-board,
#main.playing .rv-board { border: 3px solid #2a2550; }

/* Pieces: lit from above, with something under them. */
#main.playing .ck-p {
  box-shadow:
    0 .12em 0 rgba(0,0,0,.45),
    0 .22em .35em rgba(0,0,0,.45),
    inset 0 .10em .16em rgba(255,255,255,.35),
    inset 0 -.12em .18em rgba(0,0,0,.30);
  transition: transform .16s ease, filter .16s ease;
}
#main.playing .ck-sq.sel .ck-p { transform: translateY(-9%) scale(1.06); }
#main.playing .c4-cell.A,
#main.playing .c4-cell.B {
  box-shadow:
    0 0 14px currentColor,
    inset 0 .18em .22em rgba(255,255,255,.30),
    inset 0 -.22em .3em rgba(0,0,0,.45);
}

/* Whose turn, said by the board itself. */
#main.playing .ck-board,
#main.playing .rv-board,
#main.playing .mm-board,
#main.playing .c4-board { transition: filter .25s ease, opacity .25s ease; }
#main.playing:not(.my-turn) .ck-board,
#main.playing:not(.my-turn) .rv-board,
#main.playing:not(.my-turn) .mm-board,
#main.playing:not(.my-turn) .c4-board { filter: saturate(.78) brightness(.92); }

/* A square you can actually use says so, quietly and only on your turn. */
@keyframes playableBreath {
  0%, 100% { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--cyan) 55%, transparent); }
  50%      { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--cyan) 95%, transparent); }
}
#main.playing.my-turn .ck-sq.target { animation: playableBreath 1.9s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  #main.playing.my-turn .ck-sq.target { animation: none; }
  #main.playing .ck-p { transition: none; }
}

/* ---------- the ranked card ---------- */
/* Three rows, each a strip of games sliding past a marker. The strip is built
   so the drawn game sits at a known tile and the stop is a transition to that
   offset — the result is the server's, the spin is only the telling of it. */
.case-card { max-width: 420px; width: min(94vw, 420px); }
.case-head {
  font-family: var(--head); font-weight: 900; font-size: 20px; text-align: center;
  letter-spacing: .01em;
}
.case-sub { margin: 4px 0 14px; text-align: center; font-size: 13px; color: var(--muted); }
.case-row { display: grid; grid-template-columns: 22px minmax(0, 1fr); align-items: center; gap: 8px; margin-bottom: 10px; }
.case-leg {
  font-family: var(--head); font-weight: 900; font-size: 13px; color: var(--muted);
  text-align: center; font-variant-numeric: tabular-nums;
}
.case-window {
  position: relative; overflow: hidden; border-radius: 12px; height: 62px;
  border: 1px solid var(--line); background: rgba(5,5,20,.6);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
}
.case-strip { display: flex; height: 100%; will-change: transform; }
.case-tile {
  flex: 0 0 86px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; border-right: 1px solid rgba(255,255,255,.05);
}
.case-tile i { font-style: normal; font-size: 22px; line-height: 1; }
.case-tile b {
  font-size: 9.5px; font-weight: 700; color: var(--muted); text-align: center;
  max-width: 78px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.case-mark {
  position: absolute; inset-block: 0; left: 50%; width: 2px; transform: translateX(-50%);
  background: var(--lime); box-shadow: 0 0 10px var(--lime); pointer-events: none;
}
.case-row.landed .case-window {
  border-color: color-mix(in srgb, var(--lime) 60%, transparent);
  box-shadow: 0 0 16px color-mix(in srgb, var(--lime) 25%, transparent);
}
.case-row.landed .case-tile.win b { color: var(--text); }
.case-name {
  grid-column: 2; font-size: 12.5px; font-weight: 700; color: var(--lime); margin-top: 2px;
}
.case-card .btn { margin-top: 6px; }
@media (prefers-reduced-motion: reduce) { .case-strip { transition: none !important; } }

/* ---------- the shot clock ---------- */
/* Thirty seconds, drawn as a ring that empties. A number alone is something
   you have to read; a ring is something you notice while you are looking at
   the board, which is where you are actually looking. */
.shot { display: inline-flex; flex: 0 0 auto; line-height: 0; }
.shot svg { width: 26px; height: 26px; }
.shot circle { fill: none; stroke-width: 3; }
.shot .shot-bg { stroke: rgba(255,255,255,.12); }
.shot .shot-fg { stroke: var(--muted); stroke-linecap: round; transition: stroke .3s ease; }
.shot .shot-n {
  font-family: var(--head); font-weight: 900; font-size: 12px; fill: var(--muted);
  text-anchor: middle; dominant-baseline: central;
}
.shot.mine .shot-fg { stroke: var(--lime); }
.shot.mine .shot-n { fill: var(--lime); }
.shot.warn .shot-fg { stroke: var(--red); }
.shot.warn .shot-n { fill: var(--red); }
.shot.warn.mine { animation: shot-pulse 1s ease-in-out infinite; }
.shot.out .shot-n { fill: var(--muted); }
@keyframes shot-pulse { 50% { transform: scale(1.06); } }

/* The board itself says it too, so nobody has to be watching the top bar. */
#main.shot-warn { position: relative; }
#main.shot-warn::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; border-radius: 16px;
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--red) 45%, transparent);
  animation: shot-edge 1s ease-in-out infinite;
}
@keyframes shot-edge { 50% { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--red) 14%, transparent); } }
@media (prefers-reduced-motion: reduce) {
  .shot.warn.mine, #main.shot-warn::after { animation: none; }
}

/* ---------- the ranked room, before the card is dealt ---------- */
/* There is nothing to choose in a ranked room, so the twenty game cards are
   replaced by the one thing that is true: three games, hidden until you both
   say go. The three question marks are the promise the wheel then keeps. */
.ranked-card { border-color: color-mix(in srgb, var(--pink) 28%, transparent); }
.rc-draw { display: flex; gap: 10px; justify-content: center; margin: 4px 0 2px; }
.rc-q {
  flex: 0 0 64px; height: 64px; display: grid; place-items: center;
  border-radius: 14px; border: 1px dashed color-mix(in srgb, var(--pink) 40%, transparent);
  background: color-mix(in srgb, var(--pink) 7%, transparent);
  font-family: var(--head); font-weight: 900; font-size: 26px;
  color: color-mix(in srgb, var(--pink) 70%, var(--text));
}
.rc-q:nth-child(2) { animation-delay: .18s; }
.rc-q:nth-child(3) { animation-delay: .36s; }
.rc-q { animation: rc-breathe 2.4s ease-in-out infinite; }
@keyframes rc-breathe { 50% { transform: translateY(-3px); opacity: .72; } }
.rc-lineup { display: flex; gap: 8px; flex-wrap: wrap; }
.rc-leg {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 999px;
  border: 1px solid var(--line); background: rgba(255,255,255,.03); font-size: 12px; font-weight: 700;
}
.rc-leg.on { border-color: color-mix(in srgb, var(--lime) 55%, transparent); color: var(--lime); }
.rc-leg i { font-style: normal; font-size: 15px; }
@media (prefers-reduced-motion: reduce) { .rc-q { animation: none; } }

/* ---------- your side, for 2v2 ---------- */
.party {
  display: grid; gap: 7px; padding: 10px 12px; border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--cyan) 30%, transparent);
  background: color-mix(in srgb, var(--cyan) 6%, transparent);
}
.party-label {
  font-family: var(--head); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted);
}
.party-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.party-me, .party-mate {
  display: inline-flex; align-items: center; gap: 6px; font-size: 13.5px; font-weight: 700;
  padding: 3px 10px 3px 3px; border-radius: 999px;
  border: 1px solid var(--line); background: rgba(255,255,255,.04);
}
.party-mate.on { border-color: color-mix(in srgb, var(--green) 50%, transparent); }
.party-mate i { font-style: normal; font-size: 11px; color: var(--muted); font-weight: 600; }
.party-plus { color: var(--muted); font-weight: 800; }
.party-open {
  font-size: 13px; color: var(--muted); padding: 5px 12px; border-radius: 999px;
  border: 1px dashed var(--rule-2, var(--line));
}
.party .btn.small { min-height: 30px; font-size: 12px; padding: 2px 11px; margin-left: auto; }
