/* =====================================================================
   Time Pass — SIGNAL design system, single global stylesheet
   Loaded on every page. Sections below: shared primitives, then one
   section per page for its page-specific components (board, hand,
   canvas, etc). Game logic .js files never touch this file directly —
   they only toggle classes defined here.
   ===================================================================== */

/* ---------- SHARED: base + Signal primitives (every page) ---------- */
/* Shared base styles used on every Time Pass page — "Signal" design system */
html { scroll-behavior: smooth; }
body { -webkit-font-smoothing: antialiased; }

::selection { background: rgba(204, 255, 51, 0.35); color: #101218; }

/* Thin signal-colored scrollbar */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, #CCFF33, #2EC5FF);
  border-radius: 2px;
  border: 2px solid #101218;
}
* { scrollbar-color: #CCFF33 transparent; scrollbar-width: thin; }

.glass {
  background: rgba(255, 255, 255, 0.04);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

/* Signature accent text — single parrot-green, not a rainbow gradient.
   A faint glow gives it weight without looking like a multi-color effect. */
.text-neon-gradient {
  color: #CCFF33;
  text-shadow: 0 0 30px rgba(204, 255, 51, 0.35);
}

/* Glowing pill / badge border used on sub-pages */
.neon-border {
  border: 1px solid rgba(204, 255, 51, 0.35);
  box-shadow: 0 0 0 1px rgba(204, 255, 51, 0.08) inset, 0 8px 30px -12px rgba(204, 255, 51, 0.4);
}

/* ---- Signal system: shared angular / HUD primitives, used site-wide ---- */

/* Clipped-corner panel — the core shape language of the redesign */
.hud-clip {
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 22px 100%, 0 calc(100% - 22px));
  border-radius: 0 !important;
}
.hud-clip-sm {
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 12px 100%, 0 calc(100% - 12px));
  border-radius: 0 !important;
}

/* Live/ping indicator dot, reused for "active", "live multiplayer" etc. */
.signal-dot { position: relative; display: inline-block; }
.signal-dot::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: 999px;
  background: inherit;
  animation: ping 2.2s cubic-bezier(0,0,0.2,1) infinite;
}

/* Thin diagonal divider used to split HUD panels */
.hud-divider {
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.14), transparent);
  height: 1px;
}

/* ---- Per-page accent, set once via body[style="--accent-rgb:R,G,B"] ----
   Every generic component below reads this instead of a hardcoded color,
   so one shared rule works correctly on every page's category color
   (e.g. riptide for Strategy, blaze for Card games) with zero duplication. */
body { --accent-rgb: 204, 255, 51; /* default: volt */ }

.grid-bg {
  background-image:
    linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px);
  background-size: 40px 40px;
  mask-image: radial-gradient(ellipse 70% 55% at 50% 20%, #000 40%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse 70% 55% at 50% 20%, #000 40%, transparent 100%);
}

.glass-hover { transition: border-color .3s ease, transform .3s ease, box-shadow .3s ease; }
.glass-hover:hover {
  border-color: rgba(var(--accent-rgb), 0.35);
  box-shadow: 0 0 40px -10px rgba(var(--accent-rgb), 0.3);
  transform: translateY(-4px);
}

/* Mode select cards: clipped-corner tiles instead of soft rounded glass */
.mode-card {
  clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%);
  transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
  border-radius: 0 !important;
}
.mode-card:hover {
  transform: translateY(-3px);
  border-color: rgba(var(--accent-rgb), 0.4);
  box-shadow: 0 0 36px -10px rgba(var(--accent-rgb), 0.4);
}

.toggle-pill {
  border: 1px solid rgba(255,255,255,0.1);
  background: rgba(255,255,255,0.03);
  clip-path: polygon(8px 0, 100% 0, 100% 100%, 0 100%, 0 8px);
  transition: all .2s ease;
}
.toggle-pill.toggle-active {
  border-color: rgba(var(--accent-rgb), 0.65);
  background: rgba(var(--accent-rgb), 0.16);
  color: rgb(var(--accent-rgb));
  box-shadow: 0 0 18px -4px rgba(var(--accent-rgb), 0.6);
}

.room-code-display {
  letter-spacing: 0.3em;
  font-family: 'IBM Plex Mono', monospace;
  color: rgb(var(--accent-rgb));
  text-shadow: 0 0 18px rgba(var(--accent-rgb), 0.5);
}
.spinner {
  width: 18px; height: 18px; border-radius: 9999px;
  border: 2px solid rgba(var(--accent-rgb), 0.25);
  border-top-color: rgb(var(--accent-rgb));
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Small square corner button used in every game's fullscreen HUD
   (back / pause / exit / restart). Cut deliberately large (14px on a
   38px button) so the angular shape reads clearly even at small sizes. */
.corner-btn {
  width: 38px; height: 38px; display: flex; align-items: center; justify-content: center;
  clip-path: polygon(14px 0, 100% 0, 100% 100%, 0 100%, 0 14px);
  border: 1px solid rgba(255,255,255,0.14); background: rgba(255,255,255,0.06);
  color: #d4d4d4; flex-shrink: 0; transition: border-color .2s ease, background .2s ease, color .2s ease;
  border-radius: 0 !important;
}
.corner-btn:hover { border-color: rgba(var(--accent-rgb),0.6); color: rgb(var(--accent-rgb)); background: rgba(var(--accent-rgb),0.15); }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
}

/* ---------- HOMEPAGE ---------- */
/* ===== Time Pass homepage — "Signal" HUD/arcade theme ===== */

/* Was #0A0B0F (~5% lightness, near-pure-black) — lifted to a "light-dark"
   tone (~8%, now #101218) so the whole site reads as a deliberately dark
   theme rather than a flat black void, while staying comfortably dark
   (still ~17:1 contrast against the chalk text color). Every literal
   #0A0B0F / #05070a in this file (game-shell backgrounds, scrollbar and
   selection accents, the UNO wheel hub, etc.) was lifted the same
   proportional amount alongside this variable so the whole site moves
   together, colors-only. */
:root { --abyss: #101218; }

/* Fine HUD grid backdrop, masked to fade toward the edges */
.grid-bg-dark {
  background-image:
    linear-gradient(rgba(46,197,255,0.08) 1px, transparent 1px),
    linear-gradient(90deg, rgba(46,197,255,0.08) 1px, transparent 1px);
  background-size: 38px 38px;
  mask-image: radial-gradient(ellipse 80% 60% at 68% 15%, #000 30%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 68% 15%, #000 30%, transparent 100%);
}
.scan-noise {
  background-image: repeating-linear-gradient(0deg, rgba(255,255,255,0.025) 0px, transparent 1px, transparent 3px);
  opacity: 0.5;
}

/* ---- Floating HUD nav dock ---- */
/* The dock reads as glass, not a black slab. It used to darken to 92%
   opaque on scroll, which turned the nav into a heavy bar sitting on the
   page; the frosting now comes from the full-bleed veil behind it (below),
   so the pill itself can stay light and let the site show through. */
.nav-dock {
  border: 1px solid rgba(255,255,255,0.10);
  background: rgba(26,28,38,0.55);
  backdrop-filter: blur(16px) saturate(130%);
  -webkit-backdrop-filter: blur(16px) saturate(130%);
  transition: border-color .3s ease, box-shadow .3s ease, background-color .3s ease;
}
.site-header.is-scrolled .nav-dock {
  border-color: rgba(204,255,51,0.22);
  background: rgba(26,28,38,0.66);
  box-shadow: 0 12px 34px -18px rgba(204,255,51,0.3);
}

/* Full-bleed frosted strip behind the dock.
   `bottom: -2.25rem` lets the blur run past the header's own box, and the
   mask fades it to nothing over that overhang — without the mask the
   backdrop-filter would end in a visible horizontal seam across the page. */
.site-header-veil {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: -2.25rem;
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s ease;
  backdrop-filter: blur(22px) saturate(115%);
  -webkit-backdrop-filter: blur(22px) saturate(115%);
  background: linear-gradient(to bottom, rgba(16,18,24,0.9) 0%, rgba(16,18,24,0.7) 55%, rgba(16,18,24,0) 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
}
.site-header.is-scrolled .site-header-veil { opacity: 1; }

/* ---- Hero radar panel: layered 3D depth, mouse-reactive ---- */
#radarPanel { perspective: 1100px; }
.radar-face {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.2s ease-out;
}
.radar-layer { position: absolute; inset: 0; will-change: transform; transition: transform .15s ease-out; }
.radar-ring {
  position: absolute; border-radius: 999px; border: 1px solid rgba(46,197,255,0.22);
}
.radar-sweep {
  position: absolute; inset: 6%; border-radius: 999px; overflow: hidden;
  background: conic-gradient(from 0deg, rgba(204,255,51,0.55), transparent 24%, transparent 100%);
  animation: radarSpin 5.5s linear infinite;
  mask-image: radial-gradient(circle, #000 60%, transparent 100%);
  -webkit-mask-image: radial-gradient(circle, #000 60%, transparent 100%);
}
.radar-blip { position: absolute; border-radius: 999px; animation: blip 2.4s ease-in-out infinite; }

/* ---- CTA: angular "insert-coin" button ---- */
.btn-coin {
  clip-path: polygon(14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%, 0 14px);
  transition: transform .25s cubic-bezier(.22,.9,.32,1), box-shadow .3s ease, filter .3s ease;
}
.btn-coin:hover { transform: translate(-2px,-2px); filter: brightness(1.08); }

/* ---- Ticker strip ---- */
.ticker-track { animation: ticker 22s linear infinite; }
.ticker-wrap:hover .ticker-track { animation-play-state: paused; }

/* ---- Genre filter chips ---- */
.genre-chip { transition: all .25s ease; clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px); }
.genre-chip[data-active="true"] { color: #101218; border-color: transparent; }

/* ---- Signal tile: the redesigned game card ---- */
.signal-tile {
  position: relative;
  display: grid;
  grid-template-columns: 128px 1fr;
  background: #15171F;
  border: 1px solid rgba(255,255,255,0.07);
  clip-path: polygon(0 0, calc(100% - 26px) 0, 100% 26px, 100% 100%, 0 100%);
  transform: perspective(1000px) rotateX(var(--ry, 0deg)) rotateY(var(--rx, 0deg)) translateZ(0);
  transition: transform .3s cubic-bezier(.22,.9,.32,1), box-shadow .35s ease, border-color .35s ease;
}
.signal-tile:hover {
  border-color: rgba(255,255,255,0.16);
  box-shadow: 0 24px 50px -26px var(--tile-glow, rgba(204,255,51,0.4));
}
.signal-tile .tile-art {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  background: var(--tile-grad, linear-gradient(155deg, #CCFF33, #2EC5FF));
  overflow: hidden;
}
.signal-tile .tile-art::before {
  content: "";
  position: absolute; inset: 0;
  background-image: linear-gradient(rgba(0,0,0,0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(0,0,0,0.12) 1px, transparent 1px);
  background-size: 12px 12px;
  opacity: 0.35;
}
.signal-tile .tile-art-img {
  position: relative;
  width: 100%; height: 100%;
  object-fit: cover;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.35));
  transition: transform .35s cubic-bezier(.22,.9,.32,1);
}
.signal-tile:hover .tile-art-img { transform: scale(1.08); }
.signal-tile .tile-arrow { transition: transform .3s cubic-bezier(.22,.9,.32,1), opacity .3s ease; opacity: 0; transform: translateX(-6px); }
.signal-tile:hover .tile-arrow { opacity: 1; transform: translateX(0); }

/* One-line "what is this game" under the title. Clamped to two lines so a
   longer description can't push one tile taller than its neighbours and
   break the grid's rhythm — the copy in js/home.js is written to fit. */
.tile-desc {
  font-size: .72rem;
  line-height: 1.45;
  color: rgba(245,246,240,0.5);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Coming-soon variant (kept for future placeholder use, unused when every card has a link) */
.signal-tile.is-soon .tile-art { filter: grayscale(1) opacity(0.5); }

/* Flagship tile: set `flagship: true` on any entry in js/home.js's `games`
   array to opt a card into this. sm:col-span-2 in the grid markup makes
   the card itself full-width, but .signal-tile's own grid-template-columns
   is a fixed 128px art rail regardless of the card's outer width — without
   this, a full-width flagship card would just have a lot of empty text
   area next to a small square image instead of reading as a banner. A
   wider art rail plus a slightly stronger border is the whole treatment;
   everything else (badges, hover, tilt) stays exactly what every other
   card already does. No game currently sets the flag — the mechanism is
   kept generic and ready for whichever game you want to headline next. */
.signal-tile-flagship {
  grid-template-columns: 128px 1fr;
  border-color: rgba(204,255,51,0.25);
}
@media (min-width: 640px) {
  .signal-tile-flagship { grid-template-columns: 260px 1fr; }
}

/* ---- Live rail: active players ticker + ranking ladder ---- */
.player-chip { transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease; }
.player-chip:hover { transform: translateY(-2px); border-color: rgba(46,197,255,0.5); box-shadow: 0 10px 24px -10px rgba(46,197,255,0.4); }

/* ---------- RANKING LADDER ----------
   The old version painted a bright volt gradient straight under the row and
   set the name to text-chalk/80. On the widest rows the name sat on near-#CCFF33
   and disappeared. The fill is now a dim tint capped well below the text, the
   name is full-strength chalk, and the progress reads from the left rail
   rather than from how loud the background is. */
.rank-row {
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,0.06);
  background: rgba(255,255,255,0.025);
  transition: transform .2s ease, border-color .2s ease, background-color .2s ease;
}
.rank-row:hover {
  transform: translateX(3px);
  border-color: rgba(46,197,255,0.35);
  background: rgba(255,255,255,0.055);
}
.rank-row .rank-fill {
  position: absolute; inset: 0; right: auto;
  background: linear-gradient(90deg, rgba(46,197,255,0.16), rgba(46,197,255,0.05) 70%, transparent);
  z-index: 0;
  pointer-events: none;
}
.rank-row .rank-fill::after {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: linear-gradient(180deg, #CCFF33, #2EC5FF);
  box-shadow: 0 0 8px rgba(204,255,51,0.55);
}
.rank-row > * { position: relative; z-index: 1; }

/* Rank pip — a fixed-width badge so names all start on the same x. */
.rank-pip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.35rem; height: 1.35rem; flex: none;
  font-size: 0.7rem; font-weight: 700; font-variant-numeric: tabular-nums;
  color: rgba(233,238,245,0.45);
  border: 1px solid rgba(255,255,255,0.08);
  background: rgba(255,255,255,0.04);
  clip-path: polygon(0 0, calc(100% - 4px) 0, 100% 4px, 100% 100%, 4px 100%, 0 calc(100% - 4px));
}
.rank-row-1 .rank-pip { color: #0B0E13; background: linear-gradient(135deg, #FFE082, #E0A800); border-color: rgba(255,224,130,0.7); }
.rank-row-2 .rank-pip { color: #0B0E13; background: linear-gradient(135deg, #E8EDF5, #A8B4C4); border-color: rgba(232,237,245,0.6); }
.rank-row-3 .rank-pip { color: #0B0E13; background: linear-gradient(135deg, #F0B27A, #C67B44); border-color: rgba(240,178,122,0.6); }
.rank-row-1 { border-color: rgba(255,224,130,0.28); }
.rank-row-1 .rank-fill { background: linear-gradient(90deg, rgba(255,205,60,0.15), rgba(255,205,60,0.04) 70%, transparent); }

/* Username only — no face, no display name. See renderLeaderboard(). */
.rank-name {
  min-width: 0; flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: #E9EEF5; font-weight: 500;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.8rem; letter-spacing: -0.01em;
}
.rank-score {
  flex: none; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.72rem; font-weight: 700; color: #CCFF33;
  font-variant-numeric: tabular-nums;
}
.rank-score span { color: rgba(233,238,245,0.35); font-weight: 500; margin-left: .3rem; }

@media (prefers-reduced-motion: reduce) {
  .ticker-track { animation: none; }
  .radar-sweep, .radar-blip { animation: none !important; }
  .radar-layer { transition: none; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}

@media (max-width: 640px) {
  .signal-tile { grid-template-columns: 96px 1fr; }
}

/* ---------- CHESS ---------- */
/* ===== Chess — Signal HUD reskin ===== */
/* Accent set on <body style="--accent-rgb:46,197,255"> = riptide (Strategy) */

/* ===================== Toggle pills (variant / difficulty) ===================== */
/* .toggle-pill / .mode-card / .glass-hover / .grid-bg / .spinner / .room-code-display
   are shared — see SHARED section above. */

/* Whose-turn indicator */
.turn-dot {
  display: inline-block;
  width: 10px; height: 10px;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  transition: background-color .2s ease;
}
.turn-dot-white { background: #F5F6F0; box-shadow: 0 0 0 1.5px rgba(255,255,255,0.25); }
.turn-dot-black { background: #17181a; box-shadow: 0 0 0 1.5px rgba(255,255,255,0.35); }

/* ===================== Board ===================== */
/* Clipped-corner frame with a riptide signal glow instead of a soft
   rounded emerald glass case — matches the site's new angular language. */
.chess-board-wrap {
  position: relative;
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  padding: 14px;
  clip-path: polygon(0 0, calc(100% - 28px) 0, 100% 28px, 100% 100%, 28px 100%, 0 calc(100% - 28px));
  background: linear-gradient(160deg, rgba(255,255,255,0.06), rgba(255,255,255,0.015));
  border: 1px solid rgba(46, 197, 255, 0.25);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.04), 0 30px 70px -24px rgba(0,0,0,0.8), 0 0 70px -22px rgba(46,197,255,0.3);
  transition: transform .5s cubic-bezier(.22,1,.36,1);
}
.chess-board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);
  aspect-ratio: 1;
  overflow: hidden;
  border: 3px solid rgba(0,0,0,0.55);
  box-shadow: 0 14px 40px -16px rgba(0,0,0,0.75), inset 0 0 0 1px rgba(255,255,255,0.05);
}

.chess-sq {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  user-select: none;
}
.sq-light {
  background: linear-gradient(155deg, #fefff1 0%, #fefff1 100%);
}
.sq-dark {
  background: linear-gradient(155deg, #bfbfbf 0%, #bfbfbf 100%);
}
.sq-light:hover, .sq-dark:hover { filter: brightness(1.08); }

.sq-lastmove { box-shadow: inset 0 0 0 9999px rgba(204, 255, 51, 0.35); }
.sq-selected { box-shadow: inset 0 0 0 9999px rgba(204, 255, 51, 0.55); }

.sq-move-target::after {
  content: '';
  position: absolute;
  width: 30%; height: 30%;
  border-radius: 9999px;
  background: rgba(55, 55, 58, 0.55);
}
.sq-capture-target::after {
  content: '';
  position: absolute;
  inset: 6%;
  border-radius: 9999px;
  box-shadow: inset 0 0 0 4px rgba(55, 55, 58, 0.55);
}

.sq-check { background-color: rgba(255, 77, 46, 0.88) !important; animation: checkPulse 1s ease-in-out infinite; }
@keyframes checkPulse {
  0%, 100% { background-color: rgba(255, 77, 46, 0.75); }
  50% { background-color: rgba(255, 77, 46, 0.95); }
}

.sq-illegal { animation: illegalFlash 0.5s ease-out; }
@keyframes illegalFlash {
  0%   { background-color: rgba(255, 77, 46, 0.9); box-shadow: inset 0 0 0 3px rgba(255, 77, 46, 0.95); }
  70%  { background-color: rgba(255, 77, 46, 0.5); box-shadow: inset 0 0 0 3px rgba(255, 77, 46, 0.6); }
  100% { background-color: transparent; box-shadow: none; }
}

.chess-piece-img {
  width: 84%;
  height: 84%;
  object-fit: contain;
  display: block;
  transition: transform .15s ease;
  pointer-events: none;
}
.chess-sq:hover .chess-piece-img { transform: translateY(-3px) scale(1.1); }
.chess-sq:active .chess-piece-img { transform: scale(0.92); }

.coord {
  position: absolute;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 9px;
  font-weight: 700;
  opacity: 0.7;
  pointer-events: none;
}
.sq-light .coord { color: rgba(15, 45, 32, 0.7); }
.sq-dark .coord { color: rgba(210, 245, 225, 0.6); }
.coord-rank { top: 3px; left: 4px; }
.coord-file { bottom: 2px; right: 4px; }

/* Captured piece trays */
.captured-piece {
  display: inline-block;
  width: 18px;
  margin-right: -3px;
}
.captured-piece .chess-piece-img { width: 100%; height: 100%; }

/* Move list */
.move-list {
  display: flex;
  align-items: center;
  gap: 6px;
  overflow-x: auto;
  overflow-y: hidden;
  white-space: nowrap;
  height: 30px;
  flex: 1;
  scrollbar-width: thin;
}
.move-list::-webkit-scrollbar { height: 5px; }
.move-list::-webkit-scrollbar-thumb { background: rgba(46,197,255,0.3); border-radius: 9999px; }
.move-chip {
  flex-shrink: 0;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 12.5px;
  color: #d4d4d4;
  background: rgba(255,255,255,0.04);
  clip-path: polygon(6px 0, 100% 0, 100% 100%, 0 100%, 0 6px);
  padding: 3px 10px;
}
.move-num { color: #6b7280; margin-right: 4px; }

/* Promotion picker */
.promo-modal {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  gap: 14px;
  background: rgba(5, 6, 9, 0.85);
  backdrop-filter: blur(6px);
}
.promo-choice {
  width: 68px; height: 68px;
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 12px 100%, 0 calc(100% - 12px));
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  transition: transform .15s ease, border-color .15s ease;
}
.promo-choice:hover { transform: translateY(-3px); border-color: rgba(46,197,255,0.5); }
.promo-choice .chess-piece-img { width: 44px; height: 44px; }

.game-over-banner {
  text-align: center;
  font-weight: 700;
  font-family: 'Rajdhani', sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #9FE5FF;
  text-shadow: 0 0 16px rgba(46,197,255,0.45);
}

/* ===================== Fullscreen game mode ===================== */
body.game-fullscreen > div[aria-hidden="true"] { display: none; }
body.game-fullscreen #siteHeader { display: none; }
body.game-fullscreen #chessHero { display: none; }
body.game-fullscreen footer { display: none; }
body.game-fullscreen #gameFullscreenBack { display: inline-flex; }

body.game-fullscreen main {
  max-width: none;
  padding: 12px;
  padding-top: 68px;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
}
body.game-fullscreen #gameArea {
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
}
body.game-fullscreen #gameStack {
  max-width: min(92vw, 82vh, 480px);
  margin: 0 auto;
}
@media (min-width: 640px) {
  body.game-fullscreen main { padding: 24px; padding-top: 84px; }
  body.game-fullscreen #gameStack { max-width: min(60vw, 70vh, 480px); }
}

/* ===================== Win / lose / draw feedback ===================== */
@keyframes resultWinPulse {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.035); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.06), 0 30px 70px -24px rgba(0,0,0,0.8), 0 0 100px -8px rgba(204,255,51,0.85); }
  100% { transform: scale(1); }
}
.chess-board-wrap.result-win { animation: resultWinPulse 1.1s cubic-bezier(.22,1,.36,1); }

@keyframes resultLoseShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(3px); }
}
@keyframes resultLoseFlash {
  0%   { box-shadow: inset 0 0 0 1px rgba(255,255,255,0.04), 0 30px 70px -24px rgba(0,0,0,0.8), 0 0 90px -10px rgba(255,77,46,0.7); }
  100% { box-shadow: inset 0 0 0 1px rgba(255,255,255,0.04), 0 30px 70px -24px rgba(0,0,0,0.8), 0 0 70px -22px rgba(46,197,255,0.3); }
}
.chess-board-wrap.result-lose { animation: resultLoseShake 0.45s ease-in-out, resultLoseFlash 1.1s ease-out; }

@keyframes resultDrawPulse {
  0%   { box-shadow: inset 0 0 0 1px rgba(255,255,255,0.04), 0 30px 70px -24px rgba(0,0,0,0.8), 0 0 90px -10px rgba(180,180,180,0.5); }
  100% { box-shadow: inset 0 0 0 1px rgba(255,255,255,0.04), 0 30px 70px -24px rgba(0,0,0,0.8), 0 0 70px -22px rgba(46,197,255,0.3); }
}
.chess-board-wrap.result-draw { animation: resultDrawPulse 1s ease-out; }

.game-over-banner.banner-win { color: #9FE5FF; text-shadow: 0 0 20px rgba(46,197,255,0.6); }
.game-over-banner.banner-lose { color: #FF7A54; text-shadow: 0 0 16px rgba(255,77,46,0.4); }
.game-over-banner.banner-draw { color: #cbd5e1; text-shadow: none; }

/* ---------- UNO ---------- */
/* ===== UNO: Device Duel — Signal HUD ===== */
/* Accent set on <body style="--accent-rgb:255,77,46"> = blaze (Card game) */

/* ---------------------------------------------------------------------------
   ONE SIZE EXPRESSION, NOT SIX BREAKPOINTS

   Everything on this table used to be sized by a ladder of media queries —
   640, 819, 820, 480, 360, and a max-height tier for landscape phones — each
   one re-stating the card, pile, mini and padding sizes, each one able to
   disagree with the others. The table itself was a forced square built out of
   container queries, and it fought the flex layout hard enough that three
   separate comments in the old file were apologies for measured, wrong output.

   It is one custom property now. --uno-card-w reads BOTH axes, so a landscape
   phone (short, wide) gets small cards from the vh term and a narrow portrait
   phone gets them from the vw term, with the clamp holding both ends. Every
   other measurement on the table derives from it. There is nothing left to
   keep in sync.
   --------------------------------------------------------------------------- */
:root {
  /* Zoomed in from 13.5vw/9.6vh. The reference table is legible because the
     cards are big enough to read a suit off across the room; ours were sized
     to fit rather than to be seen. */
  --uno-card-w: clamp(68px, min(19vw, 13vh), 128px);
  /* 1.5, not 1.4: the art in assets/uno-cards/ is 360x540. Matching the box
     to the file exactly is what stops object-fit: cover shaving the top and
     bottom off every card. */
  --uno-card-h: calc(var(--uno-card-w) * 1.5);
  --uno-mini-w: calc(var(--uno-card-w) * 0.40);
  --uno-mini-h: calc(var(--uno-mini-w) * 1.4);
  --uno-radius: calc(var(--uno-card-w) * 0.12);

  /* The direction arrow. Inline so it costs no request and inherits its
     colour from the element's background through a mask. */
  --uno-arrow-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M3.6 20.4c1.5-7.6 6.4-12.5 14-14l-3.4-3.4L16.3 1 23 7.7 16.3 14.4l-2.1-2.1 3.4-3.4c-6.3 1.4-10.2 5.3-11.6 11.6z'/%3E%3C/svg%3E");

  --uno-red:    #F4483C; --uno-red-dark:    #8E1810;
  --uno-blue:   #2F7FF5; --uno-blue-dark:   #143A80;
  --uno-green:  #23BE63; --uno-green-dark:  #0D5228;
  --uno-yellow: #F0B429; --uno-yellow-dark: #7A5504;
}

.status-dot { animation: pulseGlow 1.6s ease-in-out infinite; }

/* ===================== Fullscreen game stage ===================== */
html.uno-playing, body.uno-playing { height: 100%; overflow: hidden; }
body.uno-playing #siteHeader,
body.uno-playing #unoHero,
body.uno-playing #unoInfoSections,
body.uno-playing footer { display: none !important; }
body.uno-playing #unoMain { max-width: none; padding: 0; margin: 0; }
/* The site-wide sound dock sits bottom-left, which is exactly where the first
   card of your hand is once the stage takes over the screen. The stage has its
   own mute button in the top bar, so the dock has nothing left to do here. */
body.uno-playing .tp-sound-dock { display: none !important; }
#gameArea:not(.hidden) { display: block; }

.uno-stage {
  position: fixed; inset: 0; z-index: 40;
  display: grid;
  /* minmax(0, 1fr), not the implicit `auto`. An auto-sized track grows to the
     min-content width of its widest item, and the un-wrapped hand row is wider
     than the phone — so the whole stage was being stretched ~18px past the
     viewport and the right-hand seat lost twice as much to the bezel as the
     left one did. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr auto;
  height: 100vh; height: 100dvh;
  background:
    radial-gradient(ellipse 70% 50% at 50% 0%, rgba(255,77,46,0.10), transparent 62%),
    #0C0E14;
  padding: max(8px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right))
           max(8px, env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left));
  gap: 6px;
}

.uno-stage-topbar { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.uno-stage-status { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: center; }
.uno-topbar-actions { flex-shrink: 0; display: flex; align-items: center; gap: 8px; }
.uno-round-btn {
  flex-shrink: 0; width: 38px; height: 38px;
  clip-path: polygon(9px 0, 100% 0, 100% 100%, 0 100%, 0 9px);
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.12);
  color: #d4d4d8; cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease, color .2s ease, transform .15s ease;
}
.uno-round-btn:hover { background: rgba(var(--accent-rgb),0.16); border-color: rgba(var(--accent-rgb),0.45); color: rgb(var(--accent-rgb)); }
.uno-round-btn:active { transform: scale(0.92); }

/* ===================== Arena =====================
   One round table seen from above, with the opponents' hands parked outside
   it. The table is a real element now (it used to be a painted ellipse behind
   a grid) because four name plates and four direction arrows have to be
   positioned against its rim, and you cannot anchor anything to a background.

   Everything derives from --uno-table-d, which reads both axes so a short
   landscape phone and a narrow portrait one each get a table that fits. */
.uno-arena {
  position: relative;
  min-height: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: clamp(10px, 2.4vh, 22px);
  padding: 2px 0;
}

.uno-table {
  --uno-table-d: clamp(228px, min(78vw, 50vh), 560px);
  position: relative;
  width: var(--uno-table-d); height: var(--uno-table-d);
  flex: none;
  display: flex; align-items: center; justify-content: center;
}

/* The felt. A lit disc, not a hole — the one part of the screen everything
   happens on should not also be the darkest part of it. */
.uno-felt {
  position: absolute; inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 34%, rgba(255,255,255,0.13), rgba(255,255,255,0.055) 52%, rgba(255,255,255,0.018) 82%, rgba(255,255,255,0) 100%),
    radial-gradient(circle at 50% 34%, rgba(var(--accent-rgb),0.22), rgba(var(--accent-rgb),0) 70%);
  border: 1px solid rgba(255,255,255,0.09);
  box-shadow: 0 24px 60px -30px rgba(0,0,0,0.9);
  pointer-events: none;
}
/* A second, inset rim — the reference table has a lip, and it is what stops
   the felt reading as a flat circle of colour. */
.uno-ring {
  position: absolute; inset: 7%;
  border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,0.07);
  background: radial-gradient(circle at 50% 38%, rgba(255,255,255,0.035), rgba(0,0,0,0.12));
  pointer-events: none;
}

/* ---- direction of play ----
   Four arrows on the diagonals, each pushed out to the rim and spun to point
   along the circle. A Reverse card rotates every one of them by 180 degrees,
   which is exactly what a Reverse card does to the table. */
.uno-arrows { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.uno-arrow {
  --sz: clamp(20px, 5.5vw, 34px);
  position: absolute; left: 50%; top: 50%;
  width: var(--sz); height: var(--sz);
  margin: calc(var(--sz) / -2) 0 0 calc(var(--sz) / -2);
  /* --uno-flow is set by updateColorChip() to whichever suit is in play, so
     the arrows are both the direction indicator and the colour indicator. */
  background: var(--uno-flow, #CCFF33);
  -webkit-mask: var(--uno-arrow-mask) center / contain no-repeat;
          mask: var(--uno-arrow-mask) center / contain no-repeat;
  transform: rotate(var(--a)) translateY(calc(var(--uno-table-d) * -0.44)) rotate(var(--spin));
  transition: transform .45s cubic-bezier(.34,1.4,.5,1), background-color .35s ease;
  filter: drop-shadow(0 0 9px var(--uno-flow, #CCFF33)) opacity(0.92);
}
/* After rotate(--a) the element's own +x axis IS the clockwise tangent of
   the circle, so an arrow drawn pointing right needs no extra spin to follow
   the rim. This one is drawn pointing up-and-right at 45 degrees, hence the
   45deg correction — and 180 more when play reverses.

   Play order is seat, seat+1, seat+2, seat+3 = bottom, left, top, right,
   which is clockwise on the table. */
.uno-arrow.a1 { --a: -135deg; }
.uno-arrow.a2 { --a:  -45deg; }
.uno-arrow.a3 { --a:   45deg; }
.uno-arrow.a4 { --a:  135deg; }
.uno-arrow { --spin: 45deg; }
/* Reversing only flips them. The colour stays the suit's — direction and
   colour are two different facts and they get two different channels. */
.uno-arena.reversed .uno-arrow { --spin: 225deg; }

/* ---- name plates on the rim ----
   The plate sits ON the edge of the felt. When it is that player's turn a
   tab grows out behind it — the reference's single clearest signal for
   "this one is playing right now". */
.uno-plate {
  position: absolute; z-index: 4;
  display: flex; align-items: center; justify-content: center;
  padding: 3px 12px;
  font-family: 'Rajdhani', 'Sora', sans-serif;
  font-size: clamp(0.68rem, 2vw, 0.92rem); font-weight: 700;
  letter-spacing: 0.04em;
  color: rgba(233,238,245,0.62);
  white-space: nowrap; pointer-events: none;
  transition: color .3s ease, text-shadow .3s ease;
}
.uno-plate.hidden { display: none; }
.uno-plate > span { position: relative; z-index: 2; }
/* The tab. Squashed flat until the seat is active, so it grows out of the rim. */
.uno-plate::before {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: calc(100% + 16px); height: calc(100% + 8px);
  transform: translate(-50%, -50%) scaleY(0.3);
  border-radius: 10px;
  background: rgba(var(--accent-rgb), 0.16);
  border: 1px solid rgba(var(--accent-rgb), 0);
  opacity: 0; z-index: 1;
  transition: opacity .3s ease, transform .3s cubic-bezier(.3,1.3,.5,1), border-color .3s ease;
}
.uno-plate.active { color: #fff; text-shadow: 0 0 16px rgba(var(--accent-rgb),0.8); }
.uno-plate.active::before {
  opacity: 1; transform: translate(-50%, -50%) scaleY(1);
  border-color: rgba(var(--accent-rgb),0.55);
  box-shadow: 0 0 22px -4px rgba(var(--accent-rgb),0.75);
}
.uno-plate.uno-plate-uno { color: #F7CF63; }
.uno-plate.uno-plate-uno::before {
  opacity: 1; transform: translate(-50%, -50%) scaleY(1);
  background: rgba(240,180,41,0.16); border-color: rgba(240,180,41,0.7);
}

/* Inset from the rim rather than centred on it. Straddling the edge looks
   right on a desktop, where there is room either side of the felt; on a phone
   the side stacks are pressed against the bezel and the rotated plates landed
   on top of them. 5% in clears both and still reads as "on the table". */
.uno-plate-top   { top: 5%;    left: 50%;  transform: translate(-50%, -50%); }
.uno-plate-you   { bottom: 5%; left: 50%;  transform: translate(-50%, 50%); color: rgb(var(--accent-rgb)); }
.uno-plate-left  { left: 5%;   top: 50%;   transform: translate(-50%, -50%) rotate(-90deg); }
.uno-plate-right { right: 5%;  top: 50%;   transform: translate(50%, -50%) rotate(90deg); }

.uno-center-row { position: relative; z-index: 3; display: flex; align-items: center; justify-content: center; }
.uno-center {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(8px, 2.6vw, 26px);
  position: relative; z-index: 3;
}

/* ===================== Seats =====================
   The hands, outside the felt. The top one fans across the width; the two
   side seats are vertical stacks against the edge of the arena. */
.uno-seat {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  z-index: 2; pointer-events: none;
}
.uno-seat.hidden { display: none; }
.uno-seat-left, .uno-seat-right {
  position: absolute; top: 50%; transform: translateY(-50%);
}
.uno-seat-left  { left: 0; }
.uno-seat-right { right: 0; }
.uno-seat-left .uno-seat-cards, .uno-seat-right .uno-seat-cards { flex-direction: column; }

.uno-seat-count {
  font-family: 'IBM Plex Mono', monospace;
  font-size: clamp(0.55rem, 1.5vw, 0.68rem); font-weight: 600;
  color: rgba(233,238,245,0.55);
  background: rgba(10,11,15,0.8);
  border: 1px solid rgba(255,255,255,0.10);
  padding: 1px 7px; border-radius: 9999px;
  transition: color .3s ease, border-color .3s ease;
}
.uno-seat.active .uno-seat-count {
  color: rgb(var(--accent-rgb)); border-color: rgba(var(--accent-rgb),0.55);
}
.uno-seat.uno-seat-uno .uno-seat-count { color: #F7CF63; border-color: rgba(240,180,41,0.7); }
.uno-seat.active .uno-seat-cards { animation: seatActivePulse 1.1s ease-in-out infinite; }
@keyframes seatActivePulse {
  0%, 100% { filter: drop-shadow(0 0 0 rgba(var(--accent-rgb),0)); }
  50% { filter: drop-shadow(0 0 10px rgba(var(--accent-rgb),0.85)); }
}
.uno-seat-cards { display: flex; }

.uno-mini {
  width: var(--uno-mini-w); height: var(--uno-mini-h);
  border-radius: calc(var(--uno-mini-w) * 0.14);
  background: linear-gradient(140deg, #23262F, #0A0B0F);
  border: 1px solid rgba(255,255,255,0.16);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 10px -4px rgba(0,0,0,0.7);
  margin-left: calc(var(--uno-mini-w) * -0.42);
  position: relative; overflow: hidden; flex: none;
}
.uno-mini:first-child { margin-left: 0; }
/* The fallback glyph only exists for a missing card-back.png. */
.uno-mini .uno-fallback-icon { display: none; width: 45%; height: 45%; color: rgba(var(--accent-rgb),0.55); }
.uno-mini.art-missing .uno-fallback-icon { display: block; }
/* Side stacks overlap vertically instead of horizontally. */
.uno-seat-left .uno-mini, .uno-seat-right .uno-mini {
  margin-left: 0; margin-top: calc(var(--uno-mini-h) * -0.55);
}
.uno-seat-left .uno-mini:first-child, .uno-seat-right .uno-mini:first-child { margin-top: 0; }

/* ===================== Piles ===================== */
.uno-draw-pile {
  width: var(--uno-card-w); height: var(--uno-card-h);
  border-radius: var(--uno-radius);
  background: linear-gradient(140deg, #23262F, #08090D);
  border: 2px solid rgba(255,255,255,0.20);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; position: relative; overflow: hidden; padding: 0;
  transition: transform .15s ease, border-color .2s ease, box-shadow .2s ease;
  /* Two offset ghosts behind the top card so the pile reads as a stack. */
  box-shadow: 3px 4px 0 -1px rgba(255,255,255,0.05),
              6px 8px 0 -1px rgba(255,255,255,0.025),
              0 8px 20px -8px rgba(0,0,0,0.7);
}
.uno-draw-pile:hover:not(.disabled) {
  transform: translateY(-3px);
  border-color: rgba(var(--accent-rgb),0.55);
  box-shadow: 3px 4px 0 -1px rgba(255,255,255,0.05),
              6px 8px 0 -1px rgba(255,255,255,0.025),
              0 0 26px -6px rgba(var(--accent-rgb),0.55);
}
.uno-draw-pile:active:not(.disabled) { transform: translateY(0) scale(0.97); }
.uno-draw-pile.disabled { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
/* Only glows when drawing is actually the move available to you. */
.uno-draw-pile.beckon { animation: unoBeckon 1.6s ease-in-out infinite; }
@keyframes unoBeckon {
  0%, 100% { box-shadow: 3px 4px 0 -1px rgba(255,255,255,0.05), 0 0 0 0 rgba(var(--accent-rgb),0.5); }
  50%      { box-shadow: 3px 4px 0 -1px rgba(255,255,255,0.05), 0 0 0 9px rgba(var(--accent-rgb),0); }
}
/* The down-arrow is a fallback for a missing card-back.png, same rule as
   everywhere else: if the art loaded, the art is the card. */
.uno-pile-mark {
  display: none; position: relative; z-index: 2;
  width: 36%; height: 36%; color: rgba(var(--accent-rgb),0.7);
  align-items: center; justify-content: center;
}
.uno-draw-pile.art-missing .uno-pile-mark { display: flex; }
.uno-pile-mark svg { width: 100%; height: 100%; }
.uno-draw-count {
  position: absolute; bottom: 4px; right: 4px; z-index: 3;
  font-family: 'IBM Plex Mono', monospace;
  font-size: clamp(0.52rem, 1.4vw, 0.64rem); font-weight: 600; color: #E9EEF5;
  background: rgba(0,0,0,0.72); padding: 1px 6px; border-radius: 9999px;
}

.uno-discard-wrap { position: relative; z-index: 0; width: var(--uno-card-w); height: var(--uno-card-h); }
.uno-discard-wrap .uno-card { position: absolute; inset: 0; z-index: 2; }
/* Two cards peeking out underneath so the pile looks thrown onto. */
.uno-discard-wrap::before,
.uno-discard-wrap::after {
  content: ''; position: absolute; inset: 0;
  border-radius: var(--uno-radius);
  background: linear-gradient(160deg, #24272F, #0A0B0F);
  border: 2px solid rgba(255,255,255,0.10);
}
.uno-discard-wrap::before { z-index: 0; transform: rotate(-11deg) translate(-4px, 3px); }
.uno-discard-wrap::after  { z-index: 1; transform: rotate(7deg) translate(3px, -2px); }
.uno-art-img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }

/* Newly played card lands on the discard */
.discard-pop { animation: discardPop .38s cubic-bezier(.22,.9,.32,1); }
@keyframes discardPop {
  0%   { transform: scale(0.55) rotate(-14deg); opacity: 0.35; filter: brightness(1.7); }
  60%  { transform: scale(1.09) rotate(3deg); }
  100% { transform: scale(1) rotate(0); opacity: 1; filter: brightness(1); }
}

/* ===================== Card =====================
   THE ART IS THE CARD.

   assets/uno-cards/ holds all 55 hand-drawn faces, so the vector card that
   used to be drawn underneath — white oval, corner numbers, centre value —
   is switched off. It printed the number a second time, in a different
   typeface, on top of artwork that already had one.

   It is not deleted, only hidden: if an image ever fails to load, its
   onerror handler tags the card `art-missing` and the drawn face comes
   straight back. See artImgTag() in js/uno.js. */
.uno-card {
  width: var(--uno-card-w); height: var(--uno-card-h);
  border-radius: var(--uno-radius); position: relative;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 20px -8px rgba(0,0,0,0.75);
  border: 2px solid rgba(255,255,255,0.22);
  overflow: hidden; flex-shrink: 0;
  transition: transform .18s cubic-bezier(.22,.9,.32,1), box-shadow .18s ease, border-color .18s ease, filter .18s ease;
  background: #0D0F14;
}
/* Everything drawn: off unless the art is missing. */
.uno-card .uno-card-corner,
.uno-card .uno-card-inner,
.uno-card .uno-card-quad { display: none; }
.uno-card.art-missing .uno-card-corner,
.uno-card.art-missing .uno-card-inner { display: flex; }
.uno-card.art-missing .uno-card-quad { display: grid; }

/* ---- the drawn fallback face, from here down ---- */
.uno-card.art-missing::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 128%; height: 62%;
  transform: translate(-50%, -50%) rotate(-24deg);
  border-radius: 50%;
  background: rgba(255,255,255,0.90);
  z-index: 0;
}
.uno-card.art-missing.wild::after { background: rgba(255,255,255,0.14); }
.uno-card.art-missing.red    { background: linear-gradient(160deg, var(--uno-red), var(--uno-red-dark)); }
.uno-card.art-missing.blue   { background: linear-gradient(160deg, var(--uno-blue), var(--uno-blue-dark)); }
.uno-card.art-missing.green  { background: linear-gradient(160deg, var(--uno-green), var(--uno-green-dark)); }
.uno-card.art-missing.yellow { background: linear-gradient(160deg, var(--uno-yellow), var(--uno-yellow-dark)); }
.uno-card.art-missing.wild   { background: linear-gradient(160deg, #33363F, #08090D); }

.uno-card-inner {
  position: relative; z-index: 2;
  flex-direction: column; align-items: center;
  gap: calc(var(--uno-card-w) * 0.04);
}
.uno-card.red    .uno-card-inner { color: var(--uno-red-dark); }
.uno-card.blue   .uno-card-inner { color: var(--uno-blue-dark); }
.uno-card.green  .uno-card-inner { color: var(--uno-green-dark); }
.uno-card.yellow .uno-card-inner { color: var(--uno-yellow-dark); }
.uno-card.wild   .uno-card-inner { color: #fff; }

.uno-card-icon { width: calc(var(--uno-card-w) * 0.36); height: calc(var(--uno-card-w) * 0.36); }
.uno-card-icon svg { width: 100%; height: 100%; }
.uno-card-value {
  font-family: 'Rajdhani', 'Sora', sans-serif;
  font-size: calc(var(--uno-card-w) * 0.56); font-weight: 700; line-height: 1;
  letter-spacing: -0.02em;
}
.uno-card-tag {
  font-size: calc(var(--uno-card-w) * 0.11);
  text-transform: uppercase; letter-spacing: 0.06em; font-weight: 800;
}
.uno-card-corner {
  position: absolute; top: 5%; left: 6%; z-index: 2;
  flex-direction: column; align-items: center;
  color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,0.55);
}
.uno-card-corner svg { width: calc(var(--uno-card-w) * 0.15); height: calc(var(--uno-card-w) * 0.15); }
.uno-card-corner span {
  font-family: 'Rajdhani', sans-serif; font-weight: 700;
  font-size: calc(var(--uno-card-w) * 0.20); line-height: 1;
}
.uno-card-corner.br { top: auto; left: auto; bottom: 5%; right: 6%; transform: rotate(180deg); }

.uno-card .uno-card-quad {
  position: absolute; inset: 12%; border-radius: 50%; overflow: hidden; z-index: 1;
  grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
  transform: rotate(-24deg); opacity: 0.85;
}
.uno-card .qr { background: var(--uno-red); }
.uno-card .qb { background: var(--uno-blue); }
.uno-card .qg { background: var(--uno-green); }
.uno-card .qy { background: var(--uno-yellow); }
.uno-card.wild4 .uno-card-inner { color: #fff; text-shadow: 0 2px 6px rgba(0,0,0,0.7); }


/* ===================== Hand ===================== */
.uno-bottom-bar { display: flex; flex-direction: column; gap: 4px; padding-bottom: 2px; }
/* No min-height: the "You" tag that used to live here moved onto the table's
   bottom plate, so this row is empty except when the Pass button appears. */
.uno-action-row { display: flex; align-items: center; justify-content: center; gap: 10px; }

.uno-hand {
  display: flex; justify-content: center; flex-wrap: nowrap; gap: 0;
  padding: calc(var(--uno-card-h) * 0.14) 10px 2px;
  overflow-x: auto; overflow-y: visible; -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.uno-hand::-webkit-scrollbar { display: none; }
.uno-hand .uno-card { margin-left: calc(var(--uno-card-w) * -0.34); cursor: pointer; }
.uno-hand .uno-card:first-child { margin-left: 0; }
.uno-hand .uno-card:hover:not(.unplayable),
.uno-hand .uno-card:focus-visible:not(.unplayable) {
  transform: translateY(calc(var(--uno-card-h) * -0.13)) scale(1.04);
  z-index: 5; box-shadow: 0 18px 30px -10px rgba(0,0,0,0.85);
}
.uno-hand .uno-card.unplayable {
  /* Desaturating hard turned every off-colour card the same beige, which
     made a hand unreadable at a glance. Dim it instead — the colour is the
     information, so the colour has to survive. */
  filter: brightness(0.5) saturate(0.75); opacity: 0.85; cursor: not-allowed;
}
.uno-hand .uno-card.playable { border-color: rgba(204,255,51,0.7); box-shadow: 0 0 0 1px rgba(204,255,51,0.3), 0 8px 20px -8px rgba(0,0,0,0.75); }
/* Cards deal in one at a time when a hand is rendered fresh. */
.uno-hand.dealing .uno-card { animation: unoDealIn .34s cubic-bezier(.22,.9,.32,1) both; }
@keyframes unoDealIn {
  0%   { transform: translateY(46px) scale(0.86) rotate(6deg); opacity: 0; }
  100% { transform: translateY(0) scale(1) rotate(0); opacity: 1; }
}
/* The card that just arrived from the draw pile. */
.uno-hand .uno-card.just-drawn { animation: unoJustDrawn .5s cubic-bezier(.22,.9,.32,1); }
@keyframes unoJustDrawn {
  0%   { transform: translateY(-30px) scale(1.14); filter: brightness(1.8); }
  100% { transform: translateY(0) scale(1); filter: brightness(1); }
}

/* Whole bottom bar glows lime when it is genuinely your turn */
.uno-bottom-bar.your-turn .uno-hand { box-shadow: 0 -14px 30px -18px rgba(204,255,51,0.55); }

/* ===================== Card flight =====================
   A clone of the card, absolutely positioned over the arena, animated from
   where the card was to where it is going. The real elements never move, so
   nothing about the layout depends on the animation finishing. */
.uno-flight-layer { position: absolute; inset: 0; z-index: 30; pointer-events: none; overflow: visible; }
.uno-flight {
  position: absolute; margin: 0;
  transition: transform .34s cubic-bezier(.3,.85,.35,1), opacity .34s ease;
  will-change: transform, opacity;
}

/* ===================== Wild colour picker ===================== */
.uno-wheel {
  position: relative; width: clamp(170px, 52vw, 208px); aspect-ratio: 1; margin: 0 auto;
  border-radius: 50%; overflow: hidden;
  display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
  box-shadow: 0 0 0 3px rgba(255,255,255,0.08), 0 20px 50px -20px rgba(0,0,0,0.85);
}
.uno-wheel-q { border: none; cursor: pointer; transition: filter .2s ease; }
.uno-wheel-q:hover, .uno-wheel-q:focus-visible { filter: brightness(1.25); }
.uno-wheel-q:active { filter: brightness(0.9); }
.uno-wheel-q.blue   { background: linear-gradient(135deg, var(--uno-blue), var(--uno-blue-dark)); }
.uno-wheel-q.green  { background: linear-gradient(135deg, var(--uno-green), var(--uno-green-dark)); }
.uno-wheel-q.yellow { background: linear-gradient(135deg, var(--uno-yellow), var(--uno-yellow-dark)); }
.uno-wheel-q.red    { background: linear-gradient(135deg, var(--uno-red), var(--uno-red-dark)); }
.uno-wheel-center {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 28%; aspect-ratio: 1; border-radius: 50%; background: #101218;
  border: 2px solid rgba(255,255,255,0.15);
  display: flex; align-items: center; justify-content: center;
  font-family: 'Rajdhani', sans-serif; font-weight: 800; font-size: 1.4rem; color: #CCFF33;
  pointer-events: none; box-shadow: 0 0 18px rgba(204,255,51,0.55);
}
.uno-color-btn { width: 64px; height: 64px; border-radius: 50%; border: 3px solid rgba(255,255,255,0.2); cursor: pointer; transition: transform .15s ease, border-color .15s ease; }
.uno-color-btn:hover { transform: scale(1.08); border-color: rgba(255,255,255,0.6); }
.uno-color-btn.red { background: var(--uno-red); }
.uno-color-btn.blue { background: var(--uno-blue); }
.uno-color-btn.green { background: var(--uno-green); }
.uno-color-btn.yellow { background: var(--uno-yellow); }

/* ===================== Bits and pieces ===================== */
.uno-pass-gate {
  position: fixed; inset: 0; z-index: 45;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  background: rgba(5,6,9,0.94); backdrop-filter: blur(8px); text-align: center; padding: 24px;
}

.uno-call-btn { animation: unoPulse 1s ease-in-out infinite; }
.uno-call-floating { position: fixed; left: 50%; bottom: max(96px, calc(96px + env(safe-area-inset-bottom))); transform: translateX(-50%); z-index: 46; }
@keyframes unoPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(251, 191, 36, 0.5); } 50% { box-shadow: 0 0 0 10px rgba(251, 191, 36, 0); } }

/* Bottom, not top. In the fullscreen stage the site header is gone, so a
   toast pinned 84px from the top landed squarely on the opposite player's
   seat — covering the card count exactly when a message about that player
   was being shown. */
.uno-toast {
  position: fixed; bottom: calc(var(--uno-card-h) + 58px); left: 50%;
  transform: translateX(-50%); z-index: 60;
  background: rgba(20,20,20,0.95); border: 1px solid rgba(255,255,255,0.15);
  color: #fff; font-size: 0.85rem; font-weight: 600;
  padding: 10px 18px; clip-path: polygon(8px 0,100% 0,100% 100%,0 100%,0 8px);
  box-shadow: 0 10px 30px -8px rgba(0,0,0,0.6);
  animation: unoToastIn .2s ease, unoToastOut .3s ease 1.6s forwards;
}
@keyframes unoToastIn { 0% { opacity: 0; transform: translate(-50%, 8px); } 100% { opacity: 1; transform: translate(-50%, 0); } }
@keyframes unoToastOut { 0% { opacity: 1; } 100% { opacity: 0; visibility: hidden; } }

.uno-player-count-btn { transition: border-color .3s ease, box-shadow .3s ease, transform .2s ease; clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%); }
.uno-player-count-btn:hover { transform: translateY(-3px); }
.uno-player-count-btn.selected {
  border-color: rgb(var(--accent-rgb)) !important;
  box-shadow: 0 0 30px -8px rgba(var(--accent-rgb),0.5);
  color: rgb(var(--accent-rgb));
}

/* ---------------------------------------------------------------------
   Desktop: nothing gets cut off.

   On a phone the side stacks bleeding past the edge of the screen is the
   look — it is what the reference does, and there is no room to do
   anything else. On a desktop there is plenty of room, so a card sliced in
   half by the viewport is just a bug wearing a style. Here the side seats
   are pulled fully inside, the hand wraps instead of scrolling, and the
   cards barely overlap so every one is whole.
   --------------------------------------------------------------------- */
@media (min-width: 900px) {
  .uno-hand { flex-wrap: wrap; row-gap: 10px; overflow: visible; }
  .uno-hand .uno-card { margin-left: calc(var(--uno-card-w) * -0.06); }
  .uno-arena { padding: 2px clamp(12px, 4vw, 56px); }
  .uno-seat-left  { left: clamp(4px, 2vw, 28px); }
  .uno-seat-right { right: clamp(4px, 2vw, 28px); }
  .uno-seat-left .uno-mini, .uno-seat-right .uno-mini { margin-top: calc(var(--uno-mini-h) * -0.42); }
}

/* Phones: let the side stacks run off the edge, like the reference. It reads
   as a hand held just out of frame rather than as a clipped element. */
@media (max-width: 560px) {
  .uno-seat-left  { left: calc(var(--uno-mini-w) * -0.34); }
  .uno-seat-right { right: calc(var(--uno-mini-w) * -0.34); }
}

@media (prefers-reduced-motion: reduce) {
  .uno-ring, .uno-draw-pile.beckon, .uno-seat.active .uno-seat-cards,
  .status-dot, .uno-call-btn { animation: none !important; }
  .uno-hand.dealing .uno-card, .uno-hand .uno-card.just-drawn { animation: none !important; }
  .uno-flight { transition: none; }
}

/* ---------- BALL RUNNER ---------- */
/* ===== Ball Runner — Signal HUD reskin ===== */
/* Accent set on <body style="--accent-rgb:255,77,46"> = blaze (Arcade) */
/* .glass-hover / .grid-bg / .mode-card / .room-code-display / .spinner are shared */

/* ===================== Fullscreen game mode ===================== */
#gameArea.game-live {
  position: fixed !important; inset: 0 !important;
  top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important;
  width: 100vw !important; height: 100dvh !important; margin: 0 !important;
  max-width: none !important; z-index: 2000 !important;
  display: flex !important; flex-direction: column !important;
  background: #0a0e14;
}
html.game-locked, html.game-locked body { overflow: hidden !important; height: 100%; overscroll-behavior: none; }

.game-topbar { flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: max(12px, env(safe-area-inset-top)) 14px 10px 14px; }
/* .corner-btn is shared — see SHARED section */

/* touch-action: none, and it is not optional.
   Without it a swipe across the track is a scroll gesture as far as the
   browser is concerned: it takes the pointer stream away mid-drag and fires
   pointercancel, so steering, swiping and even tapping to jump all died on a
   phone while working perfectly with a mouse. The game owns every gesture
   inside this box. */
.track-canvas-holder {
  position: relative; flex: 1 1 auto; min-height: 0; width: 100%;
  overflow: hidden; background: #0a0e14;
  touch-action: none; -webkit-user-select: none; user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.track-canvas-holder canvas { display: block; width: 100%; height: 100%; touch-action: none; }

.game-controls-bar {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center; gap: 18px;
  padding: 14px 14px max(14px, env(safe-area-inset-bottom)) 14px;
  background: linear-gradient(0deg, rgba(5,7,10,0.9), rgba(5,7,10,0));
}
.game-room-info { flex-shrink: 0; text-align: center; font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: #737373; padding-bottom: 8px; }

.run-overlay { position: absolute; inset: 0; z-index: 20; display: flex; align-items: center; justify-content: center; background: rgba(5, 7, 10, 0.55); backdrop-filter: blur(2px); }
.run-countdown-number {
  font-family: 'Rajdhani', sans-serif; font-size: 6rem; font-weight: 700; color: #fff;
  text-shadow: 0 0 40px rgba(var(--accent-rgb),0.8), 0 0 80px rgba(var(--accent-rgb),0.5);
}
@keyframes countPulse { 0% { transform: scale(0.6); opacity: 0; } 35% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
.count-pulse { animation: countPulse .45s ease-out; }

.run-result-card { max-width: 320px; text-align: center; }

.hud-pill { font-family: 'IBM Plex Mono', monospace; }
.opp-status-dot { display: inline-block; width: 8px; height: 8px; border-radius: 9999px; background: rgb(var(--accent-rgb)); box-shadow: 0 0 8px 1px rgba(var(--accent-rgb),0.7); }
.opp-status-dot.out { background: #f87171; box-shadow: 0 0 8px 1px rgba(248,113,113,0.6); }

.ctrl-btn {
  width: 56px; height: 56px; display: flex; align-items: center; justify-content: center;
  clip-path: polygon(12px 0, 100% 0, 100% 100%, 0 100%, 0 12px);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.04);
  color: #d4d4d4; transition: border-color .2s ease, background .2s ease, transform .1s ease;
  /* none, not manipulation: the steer buttons are HELD, and `manipulation`
     still lets the browser claim a hold-and-drag as a pan. */
  touch-action: none; user-select: none; -webkit-tap-highlight-color: transparent;
}
.ctrl-btn:active { transform: scale(0.92); background: rgba(var(--accent-rgb),0.16); border-color: rgba(var(--accent-rgb),0.5); }
.ctrl-btn-jump { border-color: rgba(var(--accent-rgb),0.35); background: rgba(var(--accent-rgb),0.12); color: rgb(var(--accent-rgb)); }
.ctrl-btn-slide { border-color: rgba(190,120,255,0.35); background: rgba(190,120,255,0.10); color: #C89BFF; }

/* --- HUD (rewritten runner) --- */
.br-hud { display: flex; align-items: center; gap: 8px; }
.br-stat {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 4px 10px;
  clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 6px));
  border: 1px solid rgba(255,255,255,0.10); background: rgba(255,255,255,0.04);
}
.br-stat-k { font-size: 0.52rem; text-transform: uppercase; letter-spacing: 0.14em; color: rgba(233,238,245,0.38); }
.br-stat-v {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.9rem; font-weight: 700; color: #E9EEF5; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.br-stat-v-dist { color: rgb(var(--accent-rgb)); }

.br-combo {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 40px; padding: 6px 8px;
  clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 6px));
  border: 1px solid rgba(255,255,255,0.10); background: rgba(255,255,255,0.04);
  font-family: 'Rajdhani', sans-serif; font-size: 1rem; font-weight: 700;
  color: rgba(233,238,245,0.55);
}
.br-combo.is-hot {
  color: #0B0E13; border-color: rgba(204,255,51,0.8);
  background: linear-gradient(90deg,#CCFF33,#A8E62B);
  box-shadow: 0 0 16px rgba(204,255,51,0.45);
}
@keyframes brPop { 0% { transform: scale(1); } 40% { transform: scale(1.28); } 100% { transform: scale(1); } }
.br-combo.pop { animation: brPop .28s ease-out; }

.br-shield {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 6px));
  border: 1px solid rgba(46,197,255,0.5); background: rgba(46,197,255,0.14); color: #2EC5FF;
  box-shadow: 0 0 14px rgba(46,197,255,0.35);
}

/* --- Race strip --- */
.br-racebar { flex-shrink: 0; padding: 0 18px 8px; }
.br-racebar-track {
  position: relative; height: 4px; width: 100%;
  background: rgba(255,255,255,0.07); border-radius: 9999px;
}
.br-racebar-mid { position: absolute; left: 50%; top: -3px; bottom: -3px; width: 1px; background: rgba(255,255,255,0.18); }
.br-racebar-dot {
  position: absolute; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px;
  border-radius: 9999px; transition: left .22s linear;
}
.br-racebar-me   { background: rgb(var(--accent-rgb)); box-shadow: 0 0 10px 2px rgba(var(--accent-rgb),0.7); z-index: 2; }
.br-racebar-them { background: #2EC5FF; box-shadow: 0 0 10px 2px rgba(46,197,255,0.6); }
.br-opp {
  margin-top: 8px; display: flex; align-items: center; justify-content: center; gap: 7px;
  font-family: 'IBM Plex Mono', monospace; font-size: 0.66rem;
  text-transform: uppercase; letter-spacing: 0.08em; color: rgba(233,238,245,0.5);
}

/* --- Result grid --- */
.br-res-grid { margin-top: 1.1rem; display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.br-res-cell {
  padding: 8px 6px;
  clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 6px));
  border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
}
.br-res-v {
  margin: 0; font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 1.05rem; font-weight: 700; color: rgb(var(--accent-rgb));
  font-variant-numeric: tabular-nums;
}
.br-res-k { margin: 2px 0 0; font-size: 0.55rem; text-transform: uppercase; letter-spacing: 0.14em; color: rgba(233,238,245,0.4); }

@media (max-width: 420px) {
  .br-stat { padding: 3px 7px; }
  .br-stat-v { font-size: 0.8rem; }
  .br-hud { gap: 5px; }
}

/* ---------- NEON TIC-TAC-TOE ---------- */
/* ===== Neon Tic-Tac-Toe — Signal HUD reskin ===== */
/* Accent set on <body style="--accent-rgb:46,197,255"> = riptide (Strategy) */
/* .glass-hover / .grid-bg / .mode-card / .room-code-display / .spinner are shared */

.ttt-board-wrap { position: relative; width: 100%; max-width: 420px; margin: 0 auto; }
.ttt-board {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; aspect-ratio: 1;
}
.ttt-cell {
  position: relative;
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 12px 100%, 0 calc(100% - 12px));
  border: 1px solid rgba(255,255,255,0.08);
  background: rgba(255,255,255,0.02);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: border-color .3s ease, box-shadow .3s ease, background-color .3s ease, transform .2s ease;
}
.ttt-cell:hover:not(.filled) { border-color: rgba(46, 197, 255, 0.4); box-shadow: 0 0 26px -8px rgba(46, 197, 255, 0.45); }
.ttt-cell:active:not(.filled) { transform: scale(0.96); }
.ttt-cell.filled { cursor: default; }
.ttt-cell svg { width: 62%; height: 62%; overflow: visible; }

.mark-x line { stroke: #2EC5FF; stroke-width: 9; stroke-linecap: round; filter: drop-shadow(0 0 7px rgba(46,197,255,0.85)); }
.mark-o circle { stroke: #CCFF33; stroke-width: 9; fill: none; filter: drop-shadow(0 0 7px rgba(204,255,51,0.85)); }

.mark-draw { animation: markDraw .4s ease forwards; }
@keyframes markDraw { 0% { stroke-dashoffset: var(--len); opacity: 0.3; } 100% { stroke-dashoffset: 0; opacity: 1; } }

.pulse-select { animation: vanishPulse 1.1s ease-in-out infinite; }
@keyframes vanishPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

.ttt-cell.own-selectable:not(.selected-mark) { box-shadow: 0 0 0 1px rgba(46,197,255,0.28) inset; }
.ttt-cell.own-selectable:not(.selected-mark):hover {
  border-color: rgba(46, 197, 255, 0.5);
  box-shadow: 0 0 0 1px rgba(46,197,255,0.28) inset, 0 0 26px -8px rgba(46, 197, 255, 0.5);
}
.ttt-cell.selected-mark { border-color: rgba(46, 197, 255, 0.95) !important; box-shadow: 0 0 30px -4px rgba(46, 197, 255, 0.85) !important; }
.ttt-cell.move-target:not(.filled) { border-color: rgba(204, 255, 51, 0.4); background: rgba(204, 255, 51, 0.06); }
.ttt-cell.move-target:not(.filled):hover { border-color: rgba(204, 255, 51, 0.7); box-shadow: 0 0 26px -8px rgba(204, 255, 51, 0.5); }

.beam-line {
  stroke: url(#beamGrad); stroke-width: 7; stroke-linecap: round;
  filter: drop-shadow(0 0 12px rgba(46,197,255,0.9));
  animation: beamDraw .5s ease forwards, beamPulse 1.4s ease-in-out infinite .5s;
}
@keyframes beamDraw { 0% { stroke-dashoffset: var(--blen); } 100% { stroke-dashoffset: 0; } }
@keyframes beamPulse { 0%, 100% { opacity: 0.75; } 50% { opacity: 1; } }

.status-dot { animation: pulseGlow 1.6s ease-in-out infinite; }

/* ---------- DUEL OF DOTS ---------- */
/* ===== Duel of Dots — Signal HUD reskin ===== */
/* Accent set on <body style="--accent-rgb:46,197,255"> = riptide (Strategy) */
/* .grid-bg / .mode-card / .room-code-display / .spinner are shared */

.back-btn {
  display: inline-flex; align-items: center; gap: 8px; margin-bottom: 24px;
  clip-path: polygon(8px 0,100% 0,100% 100%,0 100%,0 8px);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.05);
  padding: 8px 16px; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
  color: #d4d4d4; transition: border-color .3s ease, color .3s ease;
}
.back-btn:hover { border-color: rgba(var(--accent-rgb),0.5); color: rgb(var(--accent-rgb)); }

.setup-label { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.16em; color: #a3a3a3; }
.stepper { margin-top: 10px; display: flex; align-items: center; gap: 18px; }
.stepper-btn {
  width: 40px; height: 40px; clip-path: polygon(9px 0,100% 0,100% 100%,0 100%,0 9px);
  border: 1px solid rgba(255,255,255,0.12); background: rgba(255,255,255,0.04);
  color: #e5e5e5; font-size: 1.25rem; line-height: 1;
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.stepper-btn:hover { border-color: rgba(var(--accent-rgb),0.5); color: rgb(var(--accent-rgb)); background: rgba(var(--accent-rgb),0.1); }
.stepper-btn:disabled { opacity: 0.35; pointer-events: none; }
.stepper-value { min-width: 34px; text-align: center; font-family: 'IBM Plex Mono', monospace; font-family: 'Rajdhani', sans-serif; font-size: 1.6rem; font-weight: 700; color: #fff; }
.setup-hint { margin-top: 6px; font-size: 0.75rem; color: #737373; }

.pill-row { margin-top: 10px; display: flex; gap: 10px; }
.pill-btn {
  flex: 1; padding: 10px 0; clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.03);
  color: #d4d4d4; font-weight: 600; transition: border-color .2s ease, background .2s ease, color .2s ease;
}
.pill-btn.pill-active {
  border-color: rgba(var(--accent-rgb),0.65); background: rgba(var(--accent-rgb),0.16);
  color: rgb(var(--accent-rgb)); box-shadow: 0 0 18px -4px rgba(var(--accent-rgb),0.6);
}

.start-btn {
  margin-top: 26px; width: 100%; padding: 12px 0;
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%);
  border: 1px solid rgba(var(--accent-rgb),0.3); background: rgba(var(--accent-rgb),0.1);
  color: rgb(var(--accent-rgb)); font-weight: 700; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.1em;
  transition: border-color .2s ease, background .2s ease;
}
.start-btn:hover { border-color: rgba(var(--accent-rgb),0.6); background: rgba(var(--accent-rgb),0.2); }
.start-btn:disabled { opacity: 0.35; pointer-events: none; }

.choice-btn {
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.05);
  padding: 16px; font-size: 0.85rem; font-weight: 600; color: #e5e5e5;
  transition: border-color .3s ease, color .3s ease;
}
.choice-btn:hover { border-color: rgba(var(--accent-rgb),0.5); color: rgb(var(--accent-rgb)); }

.join-input {
  flex: 1; clip-path: polygon(6px 0,100% 0,100% 100%,0 100%,0 6px);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.05);
  padding: 10px 12px; font-family: 'IBM Plex Mono', monospace; text-transform: uppercase; letter-spacing: 0.05em;
  font-size: 0.875rem; color: #e5e5e5; outline: none;
}
.join-input:focus { border-color: rgba(var(--accent-rgb),0.5); }
.join-btn {
  clip-path: polygon(6px 0,100% 0,100% 100%,0 100%,0 6px);
  border: 1px solid rgba(var(--accent-rgb),0.3); background: rgba(var(--accent-rgb),0.1);
  padding: 10px 16px; font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: rgb(var(--accent-rgb)); transition: border-color .3s ease, background .3s ease;
}
.join-btn:hover { border-color: rgba(var(--accent-rgb),0.6); background: rgba(var(--accent-rgb),0.2); }

.copy-code-btn {
  margin-top: 12px; clip-path: polygon(8px 0,100% 0,100% 100%,0 100%,0 8px);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.05);
  padding: 6px 14px; font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: #d4d4d4; transition: border-color .3s ease, color .3s ease;
}
.copy-code-btn:hover { border-color: rgba(var(--accent-rgb),0.5); color: rgb(var(--accent-rgb)); }

.lobby-list { margin-top: 18px; display: flex; flex-direction: column; gap: 8px; text-align: left; }
.lobby-row {
  display: flex; align-items: center; gap: 10px;
  clip-path: polygon(6px 0,100% 0,100% 100%,0 100%,0 6px);
  border: 1px solid rgba(255,255,255,0.07); background: rgba(255,255,255,0.02);
  padding: 8px 12px; font-size: 0.8rem; color: #d4d4d4;
}
.lobby-swatch { width: 10px; height: 10px; border-radius: 9999px; flex-shrink: 0; }

/* ===================== Fullscreen game mode ===================== */
#gameArea.game-live {
  position: fixed !important; inset: 0 !important;
  width: 100vw !important; height: 100dvh !important; margin: 0 !important;
  max-width: none !important; z-index: 2000 !important;
  display: flex !important; flex-direction: column !important;
  background: #0a0e14;
}
html.game-locked, html.game-locked body { overflow: hidden !important; height: 100%; overscroll-behavior: none; }

.game-topbar { flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: max(12px, env(safe-area-inset-top)) 14px 8px 14px; }
/* .corner-btn is shared — see SHARED section */
.corner-btn-spacer { width: 38px; flex-shrink: 0; }

.turn-pill {
  display: inline-flex; align-items: center; gap: 9px;
  clip-path: polygon(9px 0,100% 0,100% 100%,0 100%,0 9px);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.05);
  padding: 8px 16px; font-size: 0.8rem; font-weight: 600; color: #e5e5e5; transition: border-color .3s ease;
  border-radius: 0 !important;
}
.turn-dot-swatch { width: 10px; height: 10px; border-radius: 9999px; box-shadow: 0 0 10px 1px currentColor; }

.board-area { flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: center; padding: 4px 14px; }
.board-frame {
  aspect-ratio: 1 / 1; height: 100%; max-width: 100%; max-height: 100%;
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 22px 100%, 0 calc(100% - 22px));
  padding: 10px;
  background: linear-gradient(160deg, rgba(255,255,255,0.06), rgba(255,255,255,0.015));
  border: 1px solid rgba(var(--accent-rgb),0.4);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.04), 0 20px 50px -20px rgba(0,0,0,0.8), 0 0 60px -20px rgba(var(--accent-rgb),0.35);
  border-radius: 0 !important;
}
.board-holder { width: 100%; height: 100%; overflow: hidden; background: #0a0e14; border: 3px solid rgba(0,0,0,0.5); }
.board-holder svg { display: block; width: 100%; height: 100%; touch-action: manipulation; }

.dg-dot { fill: #4b5563; }
.dg-line-hit { fill: none; stroke: transparent; stroke-width: 18; cursor: pointer; }
.dg-line-hit:hover { stroke: rgba(255,255,255,0.06); }
.dg-line-drawn { fill: none; stroke-linecap: round; stroke-width: 6; pointer-events: none; }
.dg-line-last { stroke-width: 9; }
.dg-box-ball { pointer-events: none; filter: drop-shadow(0 0 5px currentColor); }

.score-panel { flex-shrink: 0; display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; padding: 10px 14px max(12px, env(safe-area-inset-bottom)) 14px; background: linear-gradient(0deg, rgba(5,7,10,0.9), rgba(5,7,10,0)); }
.score-row {
  display: flex; align-items: center; gap: 8px;
  clip-path: polygon(8px 0,100% 0,100% 100%,0 100%,0 8px);
  border: 1px solid rgba(255,255,255,0.12); background: rgba(255,255,255,0.04);
  padding: 6px 14px; font-size: 0.78rem; transition: border-color .3s ease, background .3s ease;
  border-radius: 0 !important;
}
.score-row.score-active { border-color: currentColor; background: rgba(255,255,255,0.06); box-shadow: 0 0 16px -8px currentColor; }
.score-name { display: flex; align-items: center; gap: 7px; color: #e5e5e5; }
.score-swatch { width: 9px; height: 9px; border-radius: 9999px; flex-shrink: 0; }
.score-value { font-family: 'IBM Plex Mono', monospace; font-weight: 700; font-size: 0.88rem; color: #fff; }

/* ===================== End overlay ===================== */
.end-overlay { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; background: rgba(5, 7, 10, 0.65); backdrop-filter: blur(4px); padding: 20px; }
.end-card { max-width: 340px; width: 100%; text-align: center; padding: 30px 26px; }
.end-scores { margin-top: 16px; display: flex; flex-direction: column; gap: 6px; }
.end-score-row {
  display: flex; align-items: center; justify-content: space-between;
  clip-path: polygon(6px 0,100% 0,100% 100%,0 100%,0 6px);
  background: rgba(255,255,255,0.03); padding: 7px 12px; font-size: 0.82rem;
}
.rematch-btn {
  clip-path: polygon(8px 0,100% 0,100% 100%,0 100%,0 8px);
  border: 1px solid rgba(var(--accent-rgb),0.3); background: rgba(var(--accent-rgb),0.1);
  padding: 10px 20px; font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: rgb(var(--accent-rgb)); transition: border-color .3s ease, background .3s ease;
}
.rematch-btn:hover { border-color: rgba(var(--accent-rgb),0.6); background: rgba(var(--accent-rgb),0.2); }
.changemode-btn {
  clip-path: polygon(8px 0,100% 0,100% 100%,0 100%,0 8px);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.05);
  padding: 10px 20px; font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: #d4d4d4; transition: border-color .3s ease, color .3s ease;
}
.changemode-btn:hover { border-color: rgba(var(--accent-rgb),0.5); color: rgb(var(--accent-rgb)); }

@keyframes boxPop { 0% { transform: scale(0.4); opacity: 0; } 60% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
.dg-box-pop { animation: boxPop .35s ease-out; transform-box: fill-box; transform-origin: center; }

@keyframes winPulse { 0%, 100% { text-shadow: 0 0 20px rgba(var(--accent-rgb),0.5); } 50% { text-shadow: 0 0 36px rgba(var(--accent-rgb),0.9); } }
.end-title-win { animation: winPulse 1.4s ease-in-out infinite; color: rgb(var(--accent-rgb)); }

/* ---------- AUTH POPUP (login / create profile / edit profile) ---------- */
/* player-auth.js injects its own <style> tag with .pa-* rules and is a
   protected logic file we never edit directly. These overrides use one
   extra level of specificity (body .pa-x) so they win the cascade
   regardless of DOM order, restyling the popup to match Signal without
   touching player-auth.js itself. Uses volt as the universal brand accent
   (not a per-category color, since this popup appears on every page). */
body .pa-overlay { font-family: 'Sora', ui-sans-serif, system-ui, sans-serif; }
body .pa-card {
  border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 22px 100%, 0 calc(100% - 22px));
  border: 1px solid rgba(255,255,255,0.1);
  background: rgba(21,23,31,0.95);
  box-shadow: 0 20px 60px -12px rgba(0,0,0,0.7), 0 0 50px -14px rgba(204,255,51,0.18);
}
body .pa-title { font-family: 'Rajdhani', sans-serif; font-size: 1.4rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.01em; color: #F5F6F0; }
body .pa-sub { color: rgba(245,246,240,0.55); }
body .pa-input {
  border-radius: 0;
  clip-path: polygon(8px 0, 100% 0, 100% 100%, 0 100%, 0 8px);
  border: 1px solid rgba(255,255,255,0.1);
  background: rgba(255,255,255,0.04);
  color: #F5F6F0;
}
body .pa-input:focus { border-color: rgba(204,255,51,0.55); }
body .pa-btn {
  border-radius: 0;
  clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
  border: 1px solid #CCFF33;
  background: #CCFF33;
  color: #101218;
  font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.8rem;
}
body .pa-btn:hover { border-color: #DFFF7A; background: #DFFF7A; box-shadow: 0 0 26px -6px rgba(204,255,51,0.6); }
body .pa-link { color: rgba(245,246,240,0.4); }
body .pa-link:hover { color: #CCFF33; }
body .pa-key-box {
  border-radius: 0;
  clip-path: polygon(8px 0, 100% 0, 100% 100%, 0 100%, 0 8px);
  border: 1px solid rgba(204,255,51,0.3);
  background: rgba(204,255,51,0.06);
}
body .pa-key { font-family: 'IBM Plex Mono', monospace; color: #CCFF33; }
body .pa-warn, body .pa-error { color: #FF7A54; }
body .pa-copybtn {
  border-radius: 0;
  clip-path: polygon(6px 0, 100% 0, 100% 100%, 0 100%, 0 6px);
  border: 1px solid rgba(255,255,255,0.14);
  background: rgba(255,255,255,0.05);
  color: rgba(245,246,240,0.75);
}
/* player-auth.js sets these two spots to old green via inline styles at
   runtime (serialized as rgb(...)) or directly in its markup template
   (literal hex) — both matched and overridden here without editing the
   protected file. */
body .pa-hint[style*="rgb(110, 231, 183)"] { color: #CCFF33 !important; }
body [style*="color:#a7f3d0"] { color: #9FE5FF !important; }
/* Sign in/up tabs and the account-menu admin link were never covered by
   this override sweep before — both still rendered raw emerald. */
body .pa-tab[data-active="true"] { border-color: transparent; background: #CCFF33; color: #101218; }
body .pa-success { color: #CCFF33; }
body .pa-nav-signed-in::after { background: #CCFF33; box-shadow: 0 0 0 2px rgba(16,18,24,0.9), 0 0 8px rgba(204,255,51,0.8); }
body .pa-dropdown-admin { color: #CCFF33; font-weight: 700; border-top: 1px solid rgba(204,255,51,0.18); }
body .pa-dropdown-item.pa-dropdown-admin:hover { color: #CCFF33; background: rgba(204,255,51,0.1); }

/* ---------- NOIR CASEFILE ---------- */
/* ===== Noir Casefile — Signal HUD reskin ===== */
/* Accent set on <body style="--accent-rgb:204,255,51"> = volt (Puzzle) */
/* .glass-hover / .grid-bg / .mode-card / .room-code-display / .spinner are shared */

.grain {
  background-image: repeating-linear-gradient(0deg, rgba(255,255,255,0.015) 0px, rgba(255,255,255,0.015) 1px, transparent 1px, transparent 3px);
  mix-blend-mode: overlay;
}
.case-number { font-variant-numeric: tabular-nums; letter-spacing: 0.08em; }
.redact { background: repeating-linear-gradient(45deg, rgba(255,255,255,0.06), rgba(255,255,255,0.06) 4px, transparent 4px, transparent 8px); }
.evidence-card { transition: all .35s ease; }
.evidence-locked { cursor: pointer; }
.evidence-locked:hover { border-color: rgba(var(--accent-rgb),0.3); }
.clip-hidden { max-height: 0; opacity: 0; overflow: hidden; transition: max-height .5s ease, opacity .4s ease; }
.clip-shown { max-height: 240px; opacity: 1; }

.custom-select-trigger { transition: border-color .3s ease, box-shadow .3s ease, background-color .3s ease; }
.custom-select-trigger:hover, .custom-select.open .custom-select-trigger { border-color: rgba(var(--accent-rgb),0.45); box-shadow: 0 0 24px -8px rgba(var(--accent-rgb),0.4); }
.custom-select-panel {
  position: absolute; left: 0; right: 0; top: calc(100% + 8px); z-index: 30;
  max-height: 260px; overflow-y: auto;
  background: rgba(15, 15, 15, 0.92); backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px);
  border: 1px solid rgba(var(--accent-rgb),0.25);
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);
  box-shadow: 0 12px 40px -12px rgba(0,0,0,0.6), 0 0 30px -10px rgba(var(--accent-rgb),0.2);
  padding: 6px; display: none;
}
.custom-select.open .custom-select-panel { display: block; }
.custom-select-option { padding: 0.6rem 0.7rem; font-size: 0.875rem; color: #d4d4d4; cursor: pointer; transition: background-color .2s ease, color .2s ease; display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.custom-select-option:hover { background: rgba(var(--accent-rgb),0.12); color: rgb(var(--accent-rgb)); }
.custom-select-option.selected { background: rgba(var(--accent-rgb),0.14); color: rgb(var(--accent-rgb)); }
.custom-select-chevron { transition: transform .3s ease; }
.custom-select.open .custom-select-chevron { transform: rotate(180deg); }

.scene-wrap { position: relative; width: 100%; aspect-ratio: 900 / 380; overflow: hidden; border: 1px solid rgba(255,255,255,0.08); box-shadow: inset 0 0 60px rgba(0,0,0,0.5); }
.scene-wrap svg { width: 100%; height: 100%; display: block; }
.hotspot {
  position: absolute; transform: translate(-50%, -50%); width: 38px; height: 38px;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  display: flex; align-items: center; justify-content: center;
  background: rgba(10,10,10,0.55); border: 1.5px solid rgba(var(--accent-rgb),0.6); color: rgb(var(--accent-rgb));
  cursor: pointer; backdrop-filter: blur(3px);
  transition: transform .25s ease, background-color .25s ease, border-color .25s ease;
  animation: hotspotPulse 2.6s ease-in-out infinite;
}
.hotspot:hover { transform: translate(-50%, -50%) scale(1.12); background: rgba(var(--accent-rgb),0.18); }
.hotspot.found { border-color: rgba(var(--accent-rgb),0.9); background: rgba(var(--accent-rgb),0.22); animation: none; }
.hotspot.active { border-color: rgb(var(--accent-rgb)); box-shadow: 0 0 0 4px rgba(var(--accent-rgb),0.18); }
@keyframes hotspotPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb),0.35); } 50% { box-shadow: 0 0 0 8px rgba(var(--accent-rgb),0); } }
.hotspot-label { font-family: 'IBM Plex Mono', monospace; font-size: 0.65rem; font-weight: 600; }

.suspect-card { flex: 0 0 auto; width: 148px; cursor: pointer; }
.suspect-avatar {
  width: 84px; height: 84px; border-radius: 9999px;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 35% 30%, rgba(var(--accent-rgb),0.16), rgba(255,255,255,0.02));
  border: 1px solid rgba(255,255,255,0.1);
  transition: border-color .3s ease, box-shadow .3s ease;
}
.suspect-card:hover .suspect-avatar, .suspect-card.active .suspect-avatar { border-color: rgba(var(--accent-rgb),0.5); box-shadow: 0 0 24px -6px rgba(var(--accent-rgb),0.5); }
.suspect-bubble { max-height: 0; opacity: 0; overflow: hidden; transition: max-height .4s ease, opacity .35s ease, margin-top .4s ease; }
.suspect-bubble.open { max-height: 160px; opacity: 1; margin-top: 0.5rem; }

/* noir.js's evidence-scene and suspect-avatar SVGs hardcode old green as
   raw stroke/fill attributes. CSS's stroke/fill properties override SVG
   presentation attributes, so exact-value attribute selectors fix these
   without touching the protected file. */
#sceneWrap [stroke="#34d399"] { stroke: #CCFF33 !important; }
#sceneWrap [fill="#34d399"] { fill: #CCFF33 !important; }
#sceneWrap [fill="rgba(52,211,153,0.05)"] { fill: rgba(204,255,51,0.06) !important; }
#sceneGlow stop:first-child { stop-color: rgba(204,255,51,0.22) !important; }
#suspectsLineup [stroke="#6ee7b7"] { stroke: #E8FFA6 !important; }
#suspectsLineup [fill="#34d399"] { fill: #CCFF33 !important; }
#suspectsLineup [stroke="#34d399"] { stroke: #CCFF33 !important; }
.custom-select-chevron[stroke="#34d399"] { stroke: #CCFF33 !important; }

/* ---- noir.js markup override ----
   noir.js (a protected logic file) generates cards, badges, the verdict
   box, evidence caption, suspect bubbles and the custom-select trigger
   itself, hardcoding old rounded-* shapes and emerald/red Tailwind
   classes. We can't edit that file, so these target its exact output by
   id/attribute — using [class*="..."] instead of escaped class selectors
   so Tailwind's "/" in e.g. emerald-400/30 doesn't need escaping. Scoped
   to noir's own containers so nothing else on the site is affected. */
#casesGrid > article,
#cluesCaption,
#verdictBox,
.suspect-bubble,
.custom-select-trigger {
  border-radius: 0 !important;
}
#casesGrid > article { clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%); }
#cluesCaption, .suspect-bubble, .custom-select-trigger { clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%); }
#verdictBox { clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%); }

#casesGrid button[data-open] {
  border-radius: 0 !important;
  clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
  border-color: rgba(204,255,51,0.35) !important;
  background-color: rgba(204,255,51,0.12) !important;
  color: #CCFF33 !important;
}
#casesGrid button[data-open]:hover {
  border-color: rgba(204,255,51,0.65) !important;
  background-color: rgba(204,255,51,0.22) !important;
  box-shadow: 0 0 26px -6px rgba(204,255,51,0.55) !important;
}
#casesGrid span[class*="rounded-full"] { border-radius: 0 !important; clip-path: polygon(6px 0, 100% 0, 100% 100%, 0 100%, 0 6px); }

#view-grid [class*="text-emerald-300"],
#view-case [class*="text-emerald-300"],
#view-case [class*="text-emerald-200"] { color: #CCFF33 !important; }

#verdictBox[class*="border-emerald-400"] { border-color: rgba(204,255,51,0.5) !important; }
#verdictBox[class*="bg-emerald-400"] { background-color: rgba(204,255,51,0.12) !important; }
#verdictBox[class*="text-emerald-200"] { color: #CCFF33 !important; }
#verdictBox[class*="border-red-400"] { border-color: rgba(255,122,84,0.5) !important; }
#verdictBox[class*="bg-red-400"] { background-color: rgba(255,122,84,0.1) !important; }
#verdictBox[class*="text-red-300"] { color: #FF7A54 !important; }

/* ---------- KNOW ME? ---------- */
/* ===== Know Me? — Signal HUD reskin ===== */
/* Accent set on <body style="--accent-rgb:159,229,255"> = riptide-300 (Party) */
/* .glass-hover / .grid-bg / .spinner / .room-code-display are shared */

.screen-enter { animation: screenIn .35s ease both; }
@keyframes screenIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

.qopt {
  display: flex; flex-direction: column; align-items: center; gap: 0.5rem;
  padding: 1.1rem 0.75rem;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
  border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
  color: #d4d4d4; text-align: center; font-size: 0.85rem; cursor: pointer;
  transition: border-color .25s ease, box-shadow .25s ease, transform .15s ease, background .25s ease;
}
.qopt:hover { border-color: rgba(var(--accent-rgb),0.35); transform: translateY(-2px); }
.qopt.qopt-selected { border-color: rgba(var(--accent-rgb),0.7); background: rgba(var(--accent-rgb),0.12); box-shadow: 0 0 30px -8px rgba(var(--accent-rgb),0.5); color: #fff; }
.qopt-icon { display: flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; border-radius: 0.75rem; background: rgba(255,255,255,0.05); color: rgb(var(--accent-rgb)); flex-shrink: 0; overflow: hidden; }
.qopt-icon svg { width: 20px; height: 20px; flex-shrink: 0; }
.qopt-icon-image { padding: 0; background: rgba(255,255,255,0.05); position: relative; }
.qopt-icon-image img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: inherit; }
.qopt-icon-fallback { display: none; align-items: center; justify-content: center; width: 100%; height: 100%; color: rgb(var(--accent-rgb)); }
.qopt-icon-fallback svg { width: 20px; height: 20px; }

.icon-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 0.5rem; max-height: 220px; overflow-y: auto; padding: 0.25rem; }
.icon-swatch {
  display: flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem; border-radius: 0.6rem;
  border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
  color: #a3a3a3; cursor: pointer; transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.icon-swatch:hover, .icon-swatch.icon-swatch-active { border-color: rgba(var(--accent-rgb),0.6); color: rgb(var(--accent-rgb)); background: rgba(var(--accent-rgb),0.12); }
.icon-swatch svg { width: 16px; height: 16px; }

.wkm-progress-track { height: 6px; border-radius: 999px; background: rgba(255,255,255,0.08); overflow: hidden; }
.wkm-progress-fill { height: 100%; background: linear-gradient(90deg, #2EC5FF, #9FE5FF); border-radius: 999px; transition: width .35s ease; }

.qopt-review { cursor: default; text-align: center; position: relative; }
.qopt-review:hover { transform: none; }
.qopt-review-correct { border-color: rgba(var(--accent-rgb),0.6); background: rgba(var(--accent-rgb),0.1); box-shadow: 0 0 24px -10px rgba(var(--accent-rgb),0.5); }
.qopt-review-wrong { border-color: rgba(255,122,84,0.55); background: rgba(255,122,84,0.08); }
.qopt-review-tag { display: inline-flex; align-items: center; gap: 0.2rem; font-size: 0.6rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 0.15rem 0.45rem; border-radius: 999px; margin-top: 0.15rem; }
.qopt-review-tag svg { width: 9px; height: 9px; }
.qopt-review-tag-correct { background: rgba(var(--accent-rgb),0.18); color: rgb(var(--accent-rgb)); }
.qopt-review-tag-wrong { background: rgba(255,122,84,0.18); color: #FF7A54; }

.qopt-review-compact { padding: 0.55rem 0.4rem; gap: 0.3rem; font-size: 0.68rem; }
.qopt-review-compact .qopt-icon { width: 1.6rem; height: 1.6rem; border-radius: 0.5rem; }
.qopt-review-compact .qopt-icon svg { width: 13px; height: 13px; }
.qopt-review-compact .qopt-review-tag { font-size: 0.52rem; padding: 0.1rem 0.35rem; gap: 0.15rem; }
.qopt-review-compact .qopt-review-tag svg { width: 7px; height: 7px; }

.kq-result-row { border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.05); clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%); overflow: hidden; }
.kq-result-row-toggle { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; width: 100%; padding: 0.5rem 0.75rem; font-size: 0.875rem; background: transparent; border: none; cursor: pointer; color: inherit; transition: background .2s ease; }
.kq-result-row-toggle:hover { background: rgba(255,255,255,0.04); }
.kq-result-chevron { display: flex; color: #737373; transition: transform .2s ease; }
.kq-result-chevron svg { width: 14px; height: 14px; }
.kq-result-row-open .kq-result-chevron { transform: rotate(180deg); }
.kq-result-breakdown { padding: 0 0.75rem 0.75rem; }

.quiz-question-card { border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03); clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%); }

.kq-section-label { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase; color: #737373; margin-bottom: 0.9rem; padding-left: 0.15rem; }
.kq-card {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.75rem 1rem;
  border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
  clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%);
  padding: 1rem 1.15rem; transition: border-color .25s ease, background .25s ease, transform .2s ease;
}
.kq-card:hover { border-color: rgba(var(--accent-rgb),0.3); background: rgba(255,255,255,0.045); transform: translateY(-2px); }
.kq-card-title { color: #fff; font-weight: 600; font-size: 0.95rem; }
.kq-card-meta { color: #737373; font-size: 0.78rem; margin-top: 0.2rem; }
.kq-card-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; flex-shrink: 0; }
.kq-mini-btn {
  display: inline-flex; align-items: center; gap: 0.3rem;
  clip-path: polygon(6px 0,100% 0,100% 100%,0 100%,0 6px);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.04);
  color: #d4d4d4; font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  line-height: 1; padding: 0.4rem 0.7rem; white-space: nowrap; transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.kq-mini-btn svg { width: 12px; height: 12px; flex-shrink: 0; }
.kq-mini-btn:hover { border-color: rgba(var(--accent-rgb),0.5); color: rgb(var(--accent-rgb)); background: rgba(var(--accent-rgb),0.1); }
.kq-mini-btn-primary { border-color: rgba(var(--accent-rgb),0.3); background: rgba(var(--accent-rgb),0.1); color: rgb(var(--accent-rgb)); }
.kq-mini-btn-primary:hover { border-color: rgba(var(--accent-rgb),0.6); background: rgba(var(--accent-rgb),0.18); }
.kq-empty { border: 1px dashed rgba(255,255,255,0.1); clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%); padding: 1.75rem 1.25rem; text-align: center; color: #737373; font-size: 0.85rem; }

.kq-bank-grid { display: grid; grid-template-columns: 1fr; gap: 0.6rem; }
@media (min-width: 640px) { .kq-bank-grid { grid-template-columns: 1fr 1fr; } }
.kq-bank-card {
  display: flex; align-items: center; gap: 0.75rem; text-align: left;
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%);
  border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
  padding: 0.85rem 1rem; color: #d4d4d4; font-size: 0.88rem; cursor: pointer;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
.kq-bank-card:hover { border-color: rgba(var(--accent-rgb),0.35); transform: translateY(-1px); }
.kq-bank-card.kq-bank-card-active { border-color: rgba(var(--accent-rgb),0.6); background: rgba(var(--accent-rgb),0.1); color: #fff; }
.kq-checkbox { display: flex; align-items: center; justify-content: center; width: 1.35rem; height: 1.35rem; border-radius: 0.4rem; border: 1.5px solid rgba(255,255,255,0.2); flex-shrink: 0; transition: border-color .2s ease, background .2s ease; }
.kq-checkbox svg { width: 12px; height: 12px; opacity: 0; transform: scale(.6); transition: opacity .15s ease, transform .15s ease; }
.kq-bank-card-active .kq-checkbox { border-color: rgb(var(--accent-rgb)); background: rgb(var(--accent-rgb)); }
.kq-bank-card-active .kq-checkbox svg { opacity: 1; transform: scale(1); color: #0a0a0a; }

.kq-qcard-collapsed { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; }
.kq-qcard-text { color: #fff; font-weight: 600; font-size: 0.95rem; line-height: 1.4; }
.kq-chip-row { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.65rem; }
.kq-chip {
  display: inline-flex; align-items: center; gap: 0.3rem; border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
  color: #a3a3a3; font-size: 0.72rem; padding: 0.25rem 0.65rem 0.25rem 0.4rem; cursor: pointer;
  transition: border-color .2s ease, background .2s ease, color .2s ease, transform .15s ease;
}
.kq-chip:hover { border-color: rgba(var(--accent-rgb),0.35); color: #d4d4d4; transform: translateY(-1px); }
.kq-chip-icon { display: flex; align-items: center; justify-content: center; width: 1.1rem; height: 1.1rem; flex-shrink: 0; overflow: hidden; border-radius: 999px; }
.kq-chip-icon svg { width: 11px; height: 11px; flex-shrink: 0; }
.kq-chip-icon-image img { width: 100%; height: 100%; object-fit: cover; display: block; }
.kq-chip-correct { border-color: rgba(var(--accent-rgb),0.45); background: rgba(var(--accent-rgb),0.12); color: rgb(var(--accent-rgb)); }
.kq-chip-correct:hover { color: rgb(var(--accent-rgb)); }
.kq-icon-btn {
  display: flex; align-items: center; justify-content: center; width: 2rem; height: 2rem;
  clip-path: polygon(5px 0,100% 0,100% 100%,0 100%,0 5px);
  border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.03);
  color: #a3a3a3; flex-shrink: 0; cursor: pointer; transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.kq-icon-btn:hover { border-color: rgba(var(--accent-rgb),0.5); color: rgb(var(--accent-rgb)); background: rgba(var(--accent-rgb),0.1); }
.correct-radio, .share-to-bank-checkbox { accent-color: rgb(var(--accent-rgb)); }
.kq-icon-btn-danger:hover { border-color: rgba(255,77,46,0.5); color: #FF4D2E; background: rgba(255,77,46,0.1); }
.kq-icon-btn svg { width: 14px; height: 14px; }
.kq-qcard-btns { display: flex; gap: 0.4rem; flex-shrink: 0; }

/* ---------- SURPRISE ---------- */
/* ===== Surprise — Signal HUD reskin ===== */
/* Accent set on <body style="--accent-rgb:159,229,255"> = riptide-300 (Party) */
/* .glass-hover / .grid-bg / .spinner(@keyframes spin) are shared */

.countdown-number {
  font-family: 'Rajdhani', sans-serif;
  font-size: 7.5rem; font-weight: 700; line-height: 1; color: #fff;
  text-shadow: 0 0 40px rgba(var(--accent-rgb),0.8), 0 0 80px rgba(var(--accent-rgb),0.5);
}
@keyframes countPulse { 0% { transform: scale(0.7); opacity: 0; } 30% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
.count-pulse { animation: countPulse 0.5s ease-out; }

@keyframes shakeJitter {
  0%, 100% { transform: translate(0, 0); }
  20% { transform: translate(-2px, 1px); }
  40% { transform: translate(2px, -1px); }
  60% { transform: translate(-1px, -2px); }
  80% { transform: translate(1px, 2px); }
}
.shake-jitter { animation: shakeJitter 0.12s linear infinite; }

#fakeFreezeOverlay {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(10, 10, 10, 0.35);
  backdrop-filter: saturate(0.6) brightness(0.85); -webkit-backdrop-filter: saturate(0.6) brightness(0.85);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; pointer-events: none; transition: opacity 0.15s ease;
}
#fakeFreezeOverlay.active { opacity: 1; pointer-events: all; }
.fake-spinner { width: 34px; height: 34px; border-radius: 999px; border: 3px solid rgba(255,255,255,0.15); border-top-color: rgba(255,255,255,0.75); animation: spin 0.8s linear infinite; }

/* ---------- LIE DETECTOR ---------- */
/* ===== Lie Detector — Signal HUD reskin ===== */
/* Accent set on <body style="--accent-rgb:46,197,255"> = riptide (Logic/Strategy) */
/* .glass-hover / .grid-bg are shared. Polygraph gauge colors stay as authored
   in liedetector.js (green/yellow/red stress gradient is semantic, not chrome). */

.wave-line { stroke: #2EC5FF !important; stroke-dasharray: 10 7; animation: waveMove 1s linear infinite; }
/* Gauge gradient stops: liedetector.js hardcodes the low-stress end as old
   green (#34d399) via inline SVG <stop> — CSS's stop-color property
   overrides that presentation attribute without touching the file. */
#gaugeGradhub stop:first-child, #gaugeGradlive stop:first-child { stop-color: #2EC5FF !important; }
#gaugeGradhub stop:last-child, #gaugeGradlive stop:last-child { stop-color: #FF4D2E !important; }
/* Gauge gradient stops: liedetector.js hardcodes the low-stress end as old
   green (#34d399) via inline SVG <stop> — CSS's stop-color property
   overrides that presentation attribute without touching the file. */
/* Confetti pieces: liedetector.js randomly assigns one of several inline
   background colors, several of which are old green. Browsers serialize
   JS-set style.background as rgb(...), so we match on that to override
   each shade without touching the protected file. */
.confetti-piece[style*="rgb(52, 211, 153)"] { background: #2EC5FF !important; }
.confetti-piece[style*="rgb(110, 231, 183)"] { background: #9FE5FF !important; }
.confetti-piece[style*="rgb(45, 212, 191)"] { background: #CCFF33 !important; }
.confetti-piece[style*="rgb(167, 243, 208)"] { background: #DFFF7A !important; }
@keyframes waveMove { to { stroke-dashoffset: -170; } }

.needle { transform-origin: 150px 150px; transition: transform 0.55s cubic-bezier(.34,1.56,.64,1); }
.needle.idle { animation: needleIdle 2.4s ease-in-out infinite; }
@keyframes needleIdle { 0%, 100% { transform: rotate(-6deg); } 50% { transform: rotate(6deg); } }
.needle.scanning { animation: needleScan .12s linear infinite; }
@keyframes needleScan { 0% { transform: rotate(-45deg); } 25% { transform: rotate(35deg); } 50% { transform: rotate(-30deg); } 75% { transform: rotate(42deg); } 100% { transform: rotate(-45deg); } }
.needle.spike { animation: needleSpike .6s cubic-bezier(.36,.07,.19,.97) 2; }
@keyframes needleSpike { 0% { transform: rotate(0deg); } 20% { transform: rotate(-58deg); } 40% { transform: rotate(55deg); } 60% { transform: rotate(-48deg); } 80% { transform: rotate(40deg); } 100% { transform: rotate(0deg); } }
.needle.calm { animation: needleCalm 1.2s ease-out forwards; }
@keyframes needleCalm { 0% { transform: rotate(-6deg); } 100% { transform: rotate(0deg); } }
.blip { animation: blipPulse 1.4s ease-in-out infinite; }
@keyframes blipPulse { 0%, 100% { opacity: 0.4; r: 3; } 50% { opacity: 1; r: 5; } }

.glitch-text { position: relative; animation: glitchShift .35s steps(2) 3; }
@keyframes glitchShift {
  0% { transform: translate(0); }
  25% { transform: translate(-2px, 1px); text-shadow: 2px 0 rgba(255,122,84,0.6), -2px 0 rgba(46,197,255,0.6); }
  50% { transform: translate(2px, -1px); }
  75% { transform: translate(-1px, 2px); text-shadow: -2px 0 rgba(255,122,84,0.6), 2px 0 rgba(46,197,255,0.6); }
  100% { transform: translate(0); text-shadow: none; }
}
.shake-hard { animation: shakeHard .5s ease; }
@keyframes shakeHard {
  0%, 100% { transform: translateX(0); }
  10% { transform: translateX(-9px) rotate(-0.6deg); } 20% { transform: translateX(9px) rotate(0.6deg); }
  30% { transform: translateX(-7px); } 40% { transform: translateX(7px); }
  50% { transform: translateX(-5px); } 60% { transform: translateX(5px); }
  70% { transform: translateX(-3px); } 80% { transform: translateX(3px); } 90% { transform: translateX(-1px); }
}

.suspect-card { position: relative; overflow: hidden; }
.scan-sweep::before {
  content: ''; position: absolute; left: 0; right: 0; top: -20%; height: 40%;
  background: linear-gradient(to bottom, rgba(var(--accent-rgb),0) 0%, rgba(var(--accent-rgb),0.22) 50%, rgba(var(--accent-rgb),0) 100%);
  animation: scanSweep .8s ease-in-out 1; pointer-events: none;
}
@keyframes scanSweep { 0% { top: -40%; } 100% { top: 110%; } }
.stress-bar-fill { transition: width 0.8s cubic-bezier(.22,1,.36,1); }

.confetti-piece { position: absolute; width: 7px; height: 7px; left: 50%; top: 50%; border-radius: 2px; animation: confettiBurst .9s ease-out forwards; }
@keyframes confettiBurst { to { transform: translate(var(--tx), var(--ty)) rotate(var(--r)); opacity: 0; } }

.stamp { animation: stampIn .45s cubic-bezier(.34,1.56,.64,1); }
@keyframes stampIn { 0% { transform: scale(2.2) rotate(-14deg); opacity: 0; } 60% { transform: scale(0.92) rotate(-8deg); opacity: 1; } 100% { transform: scale(1) rotate(-8deg); opacity: 1; } }

.selected-ring { box-shadow: 0 0 0 2px rgba(var(--accent-rgb),0.7), 0 0 30px -6px rgba(var(--accent-rgb),0.6); border-color: rgba(var(--accent-rgb),0.6) !important; }
.liar-ring { box-shadow: 0 0 0 2px rgba(255,77,46,0.7), 0 0 30px -6px rgba(255,77,46,0.55); border-color: rgba(255,77,46,0.55) !important; }
.truth-ring { box-shadow: 0 0 0 2px rgba(var(--accent-rgb),0.8), 0 0 34px -6px rgba(var(--accent-rgb),0.7); }

/* ---------- PORTFOLIO ---------- */
/* ===== Portfolio — Signal HUD reskin ===== */
/* Accent set on <body style="--accent-rgb:204,255,51"> = volt (brand default) */
/* .glass-hover / .grid-bg are shared */

.avatar-fallback {
  display: none; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #1c2a0f, #101218);
  color: #CCFF33; font-family: 'Rajdhani', sans-serif; font-weight: 700;
}

/* ---- whoknowsme.js markup override ----
   Same protected-file situation as noir.js: whoknowsme.js generates the
   bank rows, rank list rows, and "add option" buttons itself and
   hardcodes rounded-lg + emerald Tailwind classes. Scoped to Know Me's
   own containers (including the JS-built results modal, which has a
   stable id even though it's appended dynamically) so nothing else on
   the site is affected. Accent here is riptide-300, matching the page. */
#myQuizzesList [class*="rounded-lg"],
#resultsRankList [class*="rounded-lg"],
#kqModalRankList [class*="rounded-lg"],
#bankSelectGrid [class*="rounded-lg"] {
  border-radius: 0 !important;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
}
#myQuizzesList [class*="text-emerald-300"],
#resultsRankList [class*="text-emerald-300"],
#kqModalRankList [class*="text-emerald-300"],
#bankSelectGrid [class*="text-emerald-300"],
#builderQuestionList [class*="text-emerald-300"] { color: #9FE5FF !important; }
#myQuizzesList [class*="text-emerald-200"],
#resultsRankList [class*="text-emerald-200"],
#kqModalRankList [class*="text-emerald-200"] { color: #d7f5ff !important; }
#myQuizzesList [class*="border-emerald-400"],
#resultsRankList [class*="border-emerald-400"],
#kqModalRankList [class*="border-emerald-400"] { border-color: rgba(159,229,255,0.5) !important; }
#myQuizzesList [class*="bg-emerald-400"],
#resultsRankList [class*="bg-emerald-400"],
#kqModalRankList [class*="bg-emerald-400"] { background-color: rgba(159,229,255,0.1) !important; }
#bankSelectGrid [class*="hover:border-emerald-400"]:hover,
#bankSelectGrid .bank-row:hover { border-color: rgba(159,229,255,0.5) !important; }
#builderQuestionList .add-opt-btn:hover { color: #d7f5ff !important; }

/* ---- liedetector.js markup override ----
   Same protected-file situation: liedetector.js generates the round
   cards, verdict box, suspect cards, and truth/lie stamps itself and
   hardcodes rounded-2xl/xl/full + emerald/red Tailwind classes. Scoped
   to lie-detector's own containers. Accent here is riptide, matching
   the page's --accent-rgb. */
#roundsGrid > article,
#roundContainer [class*="rounded-2xl"],
#deviceBanner [class*="rounded-2xl"],
#liveDeviceWrap [class*="rounded-2xl"],
#statementsList [class*="rounded-xl"] {
  border-radius: 0 !important;
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%);
}
#roundsGrid button[data-open],
#roundContainer #verdictBox,
#roundContainer .stamp,
#roundContainer [class*="rounded-lg"] {
  border-radius: 0 !important;
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);
}
#roundsGrid button[data-open] {
  border-color: rgba(46,197,255,0.35) !important;
  background-color: rgba(46,197,255,0.12) !important;
  color: #9FE5FF !important;
}
#roundsGrid button[data-open]:hover {
  border-color: rgba(46,197,255,0.65) !important;
  background-color: rgba(46,197,255,0.22) !important;
}
#roundsGrid span[class*="rounded-full"] { border-radius: 0 !important; clip-path: polygon(6px 0, 100% 0, 100% 100%, 0 100%, 0 6px); }
#deviceBanner [class*="bg-emerald-400"],
#liveDeviceWrap [class*="bg-emerald-400"] { background-color: #2EC5FF !important; }
#deviceBanner [class*="bg-teal-400"],
#liveDeviceWrap [class*="bg-teal-400"] { background-color: #CCFF33 !important; }
#heroSection [class*="text-emerald-300"],
#roundsGrid [class*="text-emerald-300"],
#statementsList [class*="text-emerald-300"] { color: #9FE5FF !important; }
#roundContainer .stamp[class*="border-emerald-400"] { border-color: rgba(46,197,255,0.55) !important; }
#roundContainer .stamp[class*="bg-emerald-400"] { background-color: rgba(46,197,255,0.18) !important; }
#roundContainer .stamp[class*="text-emerald-200"] { color: #9FE5FF !important; }
#roundContainer [class*="border-emerald-400"] { border-color: rgba(46,197,255,0.5) !important; }
#roundContainer [class*="bg-emerald-400"] { background-color: rgba(46,197,255,0.12) !important; }
#roundContainer [class*="text-emerald-200"] { color: #9FE5FF !important; }
#roundContainer [class*="border-red-400"] { border-color: rgba(255,122,84,0.5) !important; }
#roundContainer [class*="bg-red-400"] { background-color: rgba(255,122,84,0.1) !important; }

/* Same "Begin Round" button liedetector.js generates per round card as
   noir.js generates per case card — this one was missing its override
   (noir's #casesGrid button[data-open] got fixed, this twin didn't), so it
   was still rendering raw emerald border/bg/text and an emerald hover glow
   (shadow-[...rgba(16,185,129,0.5)]). Riptide, matching the rest of this
   page's remapped elements. */
#roundsGrid button[data-open] {
  border-radius: 0 !important;
  clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
  border-color: rgba(46,197,255,0.35) !important;
  background-color: rgba(46,197,255,0.12) !important;
  color: #9FE5FF !important;
}
#roundsGrid button[data-open]:hover {
  border-color: rgba(46,197,255,0.65) !important;
  background-color: rgba(46,197,255,0.22) !important;
  box-shadow: 0 0 26px -6px rgba(46,197,255,0.55) !important;
}
#roundContainer [class*="text-red-300"] { color: #FF7A54 !important; }

/* ---------- Homepage game cards: like button + trending badge ---------- */
/* .tile-art already has position:relative, so these anchor to the card's
   cover-art area. */
.tile-like-btn {
  position: absolute;
  top: .55rem;
  right: .55rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 9999px;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(10,11,15,0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: rgba(245,246,240,0.75);
  transition: transform .2s ease, color .2s ease, border-color .2s ease, background .2s ease;
  cursor: pointer;
}
.tile-like-btn:hover { border-color: rgba(255,122,84,0.6); color: #FF7A54; transform: scale(1.08); }
.tile-like-btn[data-liked="true"] { color: #FF4D2E; border-color: rgba(255,77,46,0.55); background: rgba(255,77,46,0.18); }
.tile-like-btn svg { pointer-events: none; }

.tile-trending-badge {
  position: absolute;
  top: .55rem;
  left: .55rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 9999px;
  background: rgba(204,255,51,0.18);
  border: 1px solid rgba(204,255,51,0.45);
  font-size: .8rem;
  line-height: 1;
}

/* ---- Sound toggle dock ---------------------------------------------------
   Bottom-left, small, and quiet. It has to be reachable on every page (the
   one thing worse than unexpected music is unexpected music you can't stop)
   without competing with anything. Bottom-LEFT specifically: bottom-right is
   where the chat drawer opens. */
.tp-sound-dock {
  position: fixed;
  left: 1rem;
  bottom: 1rem;
  z-index: 80;
  display: flex;
  gap: .35rem;
}

.tp-sound-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 6px));
  border: 1px solid rgba(255,255,255,0.1);
  background: rgba(16,18,24,0.78);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: rgba(245,246,240,0.4);
  cursor: pointer;
  transition: color .25s ease, border-color .25s ease, background .25s ease;
}

.tp-sound-btn:hover { color: rgba(245,246,240,0.85); border-color: rgba(255,255,255,0.28); }

/* On = volt, off = dim. The state has to be readable at 32px without a label. */
.tp-sound-btn[aria-pressed="true"] {
  color: #CCFF33;
  border-color: rgba(204,255,51,0.45);
  background: rgba(204,255,51,0.1);
}

@media (max-width: 480px) {
  .tp-sound-dock { left: .6rem; bottom: .6rem; }
  .tp-sound-btn { width: 30px; height: 30px; }
}

/* ---------- RECENT ROOMS (js/rooms.js) ----------
   Shown on every online-room setup screen. A room here is a live PeerJS id
   that has been probed and answered, never just a remembered string — a row
   that cannot be rejoined removes itself rather than sitting there lying. */
.tpr-wrap { margin-top: 1.25rem; }
.tpr-wrap.hidden { display: none; }
.tpr-title {
  margin: 0 0 .5rem;
  font-size: 0.62rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.18em;
  color: rgba(233,238,245,0.42);
}
.tpr-list { display: flex; flex-direction: column; gap: .4rem; }
.tpr-row {
  display: flex; align-items: center; gap: .7rem; width: 100%;
  padding: .55rem .75rem;
  clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 6px));
  border: 1px solid rgba(255,255,255,0.09);
  background: rgba(255,255,255,0.03);
  color: rgba(233,238,245,0.55);
  text-align: left; cursor: default;
  transition: border-color .2s ease, background-color .2s ease, color .2s ease;
}
.tpr-row.is-open { cursor: pointer; color: #E9EEF5; }
.tpr-row.is-open:hover {
  border-color: rgba(var(--accent-rgb), 0.5);
  background: rgba(var(--accent-rgb), 0.08);
}
.tpr-code {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.82rem; font-weight: 600; letter-spacing: 0.08em;
}
.tpr-meta { font-size: 0.66rem; color: rgba(233,238,245,0.35); }
.tpr-state {
  margin-left: auto; flex: none;
  font-size: 0.62rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  color: rgba(233,238,245,0.35);
}
.tpr-row.is-open .tpr-state { color: rgb(var(--accent-rgb)); }
