/* ==========================================================================
   ZANA - design system
   Original visual language: indigo-black ground, violet/cyan accent, gold coin.
   ========================================================================== */

:root {
  /* surfaces */
  --bg:        #080a12;
  --bg-2:      #0e1120;
  --surface:   #141830;
  --surface-2: #1b2040;
  --surface-3: #232a52;
  --line:      #262c4f;
  --line-soft: #1d2340;

  /* type */
  --text:      #e8eaf6;
  --text-dim:  #9aa2c9;
  --text-mute: #6b739c;

  /* brand */
  --violet:    #7c5cff;
  --violet-lo: #5b3ee8;
  --cyan:      #22d3ee;
  --gold:      #ffb020;
  --gold-lo:   #e08c00;
  --win:       #3ddc97;
  --lose:      #ff5d7a;
  --warn:      #ffb020;

  --grad: linear-gradient(120deg, var(--violet) 0%, #6d7bff 45%, var(--cyan) 100%);
  --grad-gold: linear-gradient(120deg, #ffd166 0%, var(--gold) 50%, #ff8f3f 100%);

  --r-sm: 8px;
  --r:    13px;
  --r-lg: 20px;

  --rail: 76px;
  --nav:  248px;
  --top:  62px;
  --chat: 296px;

  --shadow: 0 10px 34px rgba(0, 0, 0, .48);
  --glow: 0 0 0 1px rgba(124, 92, 255, .34), 0 8px 30px rgba(124, 92, 255, .2);
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

/* soft aurora behind everything */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(1100px 620px at 12% -12%, rgba(124, 92, 255, .17), transparent 62%),
    radial-gradient(900px 540px at 96% 4%, rgba(34, 211, 238, .11), transparent 60%),
    radial-gradient(700px 500px at 50% 108%, rgba(255, 176, 32, .06), transparent 62%);
}

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; border: none; background: none; }
a { color: inherit; text-decoration: none; }
::selection { background: rgba(124, 92, 255, .4); }

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 20px; }
::-webkit-scrollbar-thumb:hover { background: #2f3768; }

.hidden { display: none !important; }

/* ==========================================================================
   Shell
   ========================================================================== */

#app {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: var(--nav) 1fr;
  grid-template-rows: var(--top) 1fr;
  grid-template-areas: 'nav top' 'nav main';

  /* Filling the screen on a phone, in three escalating steps.
   *
   * `100vh` is frozen at whatever the browser chrome made it on load, so a
   * toolbar sliding away leaves a dead band at the bottom that `body {
   * overflow: hidden }` gives no way to scroll to. `100dvh` is meant to fix
   * that, and mostly does - but browsers do not agree on what the viewport is:
   * measured on a phone-sized Chrome, `100dvh` resolved to 915px while the
   * same browser reported `innerHeight` of 1166, leaving 251px of the same
   * dead band.
   *
   * So the last word goes to `--app-h`, which app.js keeps pinned to the
   * height the browser itself reports. The two units below are what stands
   * until that runs, and what stands if it cannot. */
  height: 100vh;
  height: 100dvh;
  height: var(--app-h, 100dvh);
}
#app.nav-collapsed { grid-template-columns: var(--rail); }
#app.chat-open { grid-template-columns: var(--nav) 1fr var(--chat); grid-template-areas: 'nav top chat' 'nav main chat'; }
#app.nav-collapsed.chat-open { grid-template-columns: var(--rail) 1fr var(--chat); }

/* ---- top bar ---- */
.topbar {
  grid-area: top;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 18px;
  background: rgba(14, 17, 32, .82);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
  z-index: 40;
}
.topbar .spacer { flex: 1; }

.icon-btn {
  display: grid;
  place-items: center;
  width: 36px; height: 36px;
  border-radius: 10px;
  color: var(--text-dim);
  transition: background .15s, color .15s;
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); }
.icon-btn.on { background: var(--surface-2); color: var(--violet); }

/* balance pill */
.wallet-pill {
  display: flex;
  align-items: stretch;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 11px;
  overflow: hidden;
}
.wallet-pill .amount {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 14px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  letter-spacing: .2px;
}
.wallet-pill .amount.bump { animation: bump .5s ease; }
@keyframes bump { 0% { transform: scale(1); } 32% { transform: scale(1.13); color: var(--gold); } 100% { transform: scale(1); } }

.coin {
  display: inline-grid;
  place-items: center;
  width: 17px; height: 17px;
  border-radius: 50%;
  background: var(--grad-gold);
  color: #3a2600;
  font-size: 10px;
  font-weight: 900;
  flex: none;
  box-shadow: inset 0 -1px 2px rgba(0,0,0,.3);
}
.coin.sm { width: 13px; height: 13px; font-size: 8px; }

/* ---- side nav ---- */
.sidenav {
  grid-area: nav;
  background: var(--bg-2);
  border-right: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  z-index: 50;
}
.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  height: var(--top);
  padding: 0 18px;
  flex: none;
  border-bottom: 1px solid var(--line-soft);
}
.brand-mark {
  width: 30px; height: 30px;
  border-radius: 9px;
  background: var(--grad);
  display: grid;
  place-items: center;
  font-weight: 900;
  font-size: 15px;
  color: #0a0b14;
  flex: none;
  box-shadow: 0 4px 16px rgba(124, 92, 255, .45);
}
.brand-name { font-weight: 800; font-size: 17px; letter-spacing: -.3px; }
.brand-name span { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }

.nav-scroll { flex: 1; overflow-y: auto; padding: 12px 10px 20px; }
.nav-group + .nav-group { margin-top: 18px; }
.nav-label {
  padding: 0 10px 7px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-mute);
}
.nav-item {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 10px;
  border-radius: 10px;
  color: var(--text-dim);
  font-weight: 550;
  font-size: 13.5px;
  transition: background .13s, color .13s;
}
/* the sign-out row is a button, so it needs what a button does not inherit */
.nav-action {
  background: none;
  border: 0;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.nav-action:hover { color: var(--lose); }
.nav-action:hover .nav-ico { color: var(--lose); }
.nav-item:hover { background: var(--surface); color: var(--text); }
.nav-item.active { background: var(--surface-2); color: var(--text); }
.nav-item.active .nav-ico { color: var(--violet); }
.nav-ico { width: 19px; flex: none; display: grid; place-items: center; color: var(--text-mute); }
.nav-item .tag {
  margin-left: auto;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 20px;
  background: rgba(124, 92, 255, .18);
  color: #b7a6ff;
}

#app.nav-collapsed .brand-name,
#app.nav-collapsed .nav-label,
#app.nav-collapsed .nav-item span,
#app.nav-collapsed .nav-item .tag { display: none; }
#app.nav-collapsed .nav-item { justify-content: center; padding: 11px 0; }
#app.nav-collapsed .brand { justify-content: center; padding: 0; }

/* ---- main ---- */
.main {
  grid-area: main;
  overflow-y: auto;
  overflow-x: hidden;
  scroll-behavior: smooth;
}
.page { max-width: 1240px; margin: 0 auto; padding: 24px 24px 72px; }
.page.wide { max-width: 1500px; }

/* ---- chat ---- */
.chatbar {
  grid-area: chat;
  background: var(--bg-2);
  border-left: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#app:not(.chat-open) .chatbar { display: none; }
.chat-head {
  height: var(--top);
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 15px;
  border-bottom: 1px solid var(--line-soft);
  flex: none;
  font-weight: 650;
}
.chat-online {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-dim);
  font-weight: 500;
}
.dot-live { width: 7px; height: 7px; border-radius: 50%; background: var(--win); box-shadow: 0 0 8px var(--win); }
.chat-log { flex: 1; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 11px; }
.chat-msg { font-size: 13px; line-height: 1.45; word-break: break-word; }
.chat-msg .who { font-weight: 700; color: var(--violet); margin-right: 6px; }
.chat-msg .who.self { color: var(--cyan); }
.chat-msg .body { color: var(--text-dim); }
.chat-form { padding: 12px; border-top: 1px solid var(--line-soft); flex: none; display: flex; gap: 8px; }
.chat-form input { flex: 1; min-width: 0; }

/* ==========================================================================
   Controls
   ========================================================================== */

.input, input[type=text], input[type=password], input[type=number], input[type=email], select, textarea {
  width: 100%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 12px;
  color: var(--text);
  outline: none;
  transition: border-color .14s, box-shadow .14s;
  font-variant-numeric: tabular-nums;
}
.input:focus, input:focus, select:focus, textarea:focus {
  border-color: var(--violet);
  box-shadow: 0 0 0 3px rgba(124, 92, 255, .16);
}
input::placeholder { color: var(--text-mute); }
input[type=number] { -moz-appearance: textfield; }
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%239aa2c9' d='M6 8.2 1.8 4h8.4z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; padding-right: 32px; }

.field { display: block; margin-bottom: 12px; }
.field > label {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11.5px;
  font-weight: 650;
  color: var(--text-dim);
  margin-bottom: 6px;
}
.field .hint { color: var(--text-mute); font-weight: 500; }
/* Sits in the right-hand side of the password field's own label row, which is
   already a flex with space-between - so it needs no layout of its own, only to
   stop shouting at the field it belongs to. */
.field .forgot-link { font-size: 11.5px; font-weight: 650; text-decoration: none; }
.field .forgot-link:hover { text-decoration: underline; }

.input-group { position: relative; display: flex; }
.input-group input { border-radius: 10px 0 0 10px; }
.input-group .adorn {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: none;
  border-radius: 0 10px 10px 0;
}
.input-group .adorn button {
  padding: 3px 8px;
  border-radius: 6px;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-dim);
  background: var(--surface-2);
  transition: background .13s, color .13s;
}
.input-group .adorn button:hover { background: var(--surface-3); color: var(--text); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 18px;
  border-radius: 11px;
  font-weight: 700;
  font-size: 14px;
  background: var(--surface-2);
  color: var(--text);
  transition: filter .14s, transform .08s, background .14s, opacity .14s;
  white-space: nowrap;
}
.btn:hover { filter: brightness(1.14); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: not-allowed; filter: none; transform: none; }
.btn.primary { background: var(--grad); color: #0a0b14; box-shadow: 0 6px 20px rgba(124, 92, 255, .3); }
.btn.gold { background: var(--grad-gold); color: #2b1c00; }
.btn.win { background: linear-gradient(120deg, #4ade80, #22c58a); color: #062a18; }
.btn.danger { background: linear-gradient(120deg, #ff6b81, #f0435f); color: #2c0009; }
.btn.ghost { background: transparent; border: 1px solid var(--line); color: var(--text-dim); }
.btn.ghost:hover { border-color: var(--violet); color: var(--text); }
.btn.block { width: 100%; }
.btn.lg { padding: 14px 22px; font-size: 15px; }
.btn.sm { padding: 7px 12px; font-size: 12.5px; border-radius: 9px; }

.seg {
  display: flex;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 3px;
  gap: 3px;
}
.seg button {
  flex: 1;
  padding: 7px 10px;
  border-radius: 7px;
  font-size: 12.5px;
  font-weight: 650;
  color: var(--text-dim);
  transition: background .14s, color .14s;
  white-space: nowrap;
}
.seg button:hover { color: var(--text); }
.seg button.on { background: var(--surface-3); color: var(--text); }
.seg.accent button.on { background: var(--grad); color: #0a0b14; }

.switch { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; }
.switch input { display: none; }
.switch .track {
  width: 38px; height: 21px;
  border-radius: 20px;
  background: var(--surface-3);
  position: relative;
  transition: background .16s;
  flex: none;
}
.switch .track::after {
  content: '';
  position: absolute;
  top: 3px; left: 3px;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: var(--text-dim);
  transition: transform .16s, background .16s;
}
.switch input:checked + .track { background: rgba(124, 92, 255, .35); }
.switch input:checked + .track::after { transform: translateX(17px); background: var(--violet); }

/* ==========================================================================
   Cards, panels, tables
   ========================================================================== */

.card {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  padding: 20px;
}
.card.flush { padding: 0; overflow: hidden; }

.section-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 30px 0 14px;
}
.section-head:first-child { margin-top: 0; }
.section-head h2 { margin: 0; font-size: 17px; font-weight: 750; letter-spacing: -.2px; }
.section-head .rule { flex: 1; height: 1px; background: var(--line-soft); }
.section-head .count { font-size: 12px; color: var(--text-mute); font-weight: 600; }

h1 { font-size: 26px; font-weight: 800; letter-spacing: -.6px; margin: 0 0 6px; }
.sub { color: var(--text-dim); margin: 0 0 22px; }

.table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table th {
  text-align: left;
  padding: 11px 14px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-mute);
  border-bottom: 1px solid var(--line-soft);
  white-space: nowrap;
}
.table td { padding: 10px 14px; border-bottom: 1px solid var(--line-soft); white-space: nowrap; }
.table tr:last-child td { border-bottom: none; }
.table tbody tr { transition: background .12s; }
.table tbody tr:hover { background: rgba(255, 255, 255, .022); }
.table .num { font-variant-numeric: tabular-nums; }
.table-wrap { overflow-x: auto; }

.pos { color: var(--win); font-weight: 650; }
.neg { color: var(--text-mute); }
.muted { color: var(--text-mute); }
.dim { color: var(--text-dim); }
.mono { font-family: var(--mono); font-size: 12px; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 20px;
  font-size: 11.5px;
  font-weight: 700;
  background: var(--surface-2);
  color: var(--text-dim);
}
.pill.win { background: rgba(61, 220, 151, .14); color: var(--win); }
.pill.lose { background: rgba(255, 93, 122, .13); color: var(--lose); }
.pill.gold { background: rgba(255, 176, 32, .14); color: var(--gold); }

.empty { padding: 40px 20px; text-align: center; color: var(--text-mute); }

/* ==========================================================================
   Lobby
   ========================================================================== */

.hero {
  position: relative;
  border-radius: var(--r-lg);
  padding: 34px 34px 30px;
  margin-bottom: 26px;
  overflow: hidden;
  background: linear-gradient(115deg, #1b1740 0%, #141830 46%, #10233a 100%);
  border: 1px solid var(--line);
}
.hero::after {
  content: '';
  position: absolute;
  right: -90px; top: -110px;
  width: 420px; height: 420px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(124, 92, 255, .34), transparent 66%);
}
.hero-tag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  border-radius: 20px;
  background: rgba(255, 176, 32, .13);
  color: var(--gold);
  font-size: 11.5px;
  font-weight: 750;
  letter-spacing: .04em;
  margin-bottom: 14px;
}
.hero h1 { font-size: 32px; max-width: 620px; position: relative; }
.hero p { color: var(--text-dim); max-width: 540px; margin: 0 0 20px; position: relative; }
.hero-actions { display: flex; gap: 11px; flex-wrap: wrap; position: relative; }
.hero-stats { display: flex; gap: 30px; margin-top: 26px; position: relative; flex-wrap: wrap; }
.hero-stats div { display: flex; flex-direction: column; }
.hero-stats b { font-size: 19px; font-weight: 750; font-variant-numeric: tabular-nums; }
.hero-stats span { font-size: 11.5px; color: var(--text-mute); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }

.game-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
  gap: 15px;
}
.game-card {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 15px;
  text-align: left;
  transition: transform .18s cubic-bezier(.2,.8,.3,1), box-shadow .18s, border-color .18s;
}
.game-card:hover {
  transform: translateY(-5px);
  border-color: var(--accent, var(--violet));
  box-shadow:
    0 14px 34px rgba(0, 0, 0, .5),
    0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent),
    0 10px 40px color-mix(in srgb, var(--accent) 34%, transparent);
}

/* a bright hairline across the top edge, in the game's colour */
.game-card .gc-edge {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  z-index: 3;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  opacity: .8;
  transition: opacity .2s;
}
.game-card:hover .gc-edge { opacity: 1; }
.game-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 82% at 50% 2%, var(--accent) 0%, transparent 68%),
    linear-gradient(160deg, color-mix(in srgb, var(--accent) 34%, transparent), transparent 62%);
  opacity: .52;
  transition: opacity .2s;
}
.game-card:hover::before { opacity: .82; }
.game-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(8, 10, 18, .93) 4%, rgba(8, 10, 18, .34) 42%, transparent 72%);
}
.game-art {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding-bottom: 34px;
}

/* a soft pool of the game's own colour behind the icon, so each tile in the
   grid reads as a different one at a glance */
.game-art::before {
  content: '';
  position: absolute;
  top: 34%;
  left: 50%;
  width: 108px;
  height: 108px;
  margin: -54px 0 0 -54px;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 62%, transparent) 0%, transparent 68%);
  filter: blur(9px);
  opacity: .75;
  transition: opacity .2s, transform .2s;
}
.game-card:hover .game-art::before { opacity: 1; transform: scale(1.12); }

.game-art svg {
  position: relative;
  width: 84px;
  height: 84px;
  opacity: 1;
  filter:
    saturate(1.22) brightness(1.1)
    drop-shadow(0 4px 14px rgba(0, 0, 0, .55))
    drop-shadow(0 0 16px color-mix(in srgb, var(--accent) 55%, transparent));
  transition: transform .2s cubic-bezier(.2,.8,.3,1);
}
.game-card:hover .game-art svg { transform: scale(1.07) translateY(-2px); }
/* ::after is the element's last child, so without a stacking order of its own
   the label sits underneath the darkening veil and reads as greyed out. */
.game-card .gc-name {
  position: relative;
  z-index: 2;
  font-weight: 800;
  font-size: 15px;
  letter-spacing: -.2px;
  color: #fff;
  text-shadow: 0 1px 10px rgba(0, 0, 0, .8);
}
.game-card .gc-blurb {
  position: relative;
  z-index: 2;
  font-size: 11.5px;
  color: var(--text-dim);
  text-shadow: 0 1px 8px rgba(0, 0, 0, .75);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.game-card .gc-live {
  position: absolute;
  top: 11px; left: 11px;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 20px;
  background: rgba(8, 10, 18, .72);
  backdrop-filter: blur(6px);
  font-size: 10px;
  font-weight: 750;
  color: var(--win);
  z-index: 2;
}

/* live ticker */
.ticker { overflow: hidden; border-radius: var(--r); border: 1px solid var(--line-soft); background: var(--surface); }
.ticker-row {
  display: grid;
  grid-template-columns: 1.1fr 1fr .8fr .9fr 1fr;
  gap: 10px;
  padding: 9px 15px;
  font-size: 12.5px;
  border-bottom: 1px solid var(--line-soft);
  align-items: center;
}
.ticker-row:last-child { border-bottom: none; }
.ticker-row.head { color: var(--text-mute); font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; }
.ticker-row .r { text-align: right; font-variant-numeric: tabular-nums; }
.ticker-row.new { animation: slidein .4s cubic-bezier(.2,.8,.3,1); }
@keyframes slidein { from { opacity: 0; transform: translateY(-9px); } to { opacity: 1; transform: none; } }

/* ==========================================================================
   Game screen
   ========================================================================== */

.game-shell {
  display: grid;
  grid-template-columns: 322px 1fr;
  gap: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--line-soft);
  background: var(--surface);
  min-height: 560px;
}
.game-shell.reverse { grid-template-columns: 1fr 322px; }
.game-panel { background: var(--bg-2); padding: 18px; border-right: 1px solid var(--line-soft); }
.game-shell.reverse .game-panel { border-right: none; border-left: 1px solid var(--line-soft); order: 2; }
.game-stage {
  position: relative;
  padding: 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 480px;
  background:
    radial-gradient(700px 340px at 50% 0%, rgba(124, 92, 255, .07), transparent 66%),
    var(--surface);
}
.game-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.game-head h1 { margin: 0; font-size: 21px; }
.game-head .spacer { flex: 1; }

.bet-total {
  display: flex;
  justify-content: space-between;
  padding: 11px 13px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  font-size: 13px;
  margin-bottom: 12px;
}
.bet-total b { font-variant-numeric: tabular-nums; }

.result-flash {
  position: absolute;
  top: 20px; left: 50%;
  transform: translateX(-50%);
  padding: 9px 20px;
  border-radius: 30px;
  font-weight: 800;
  font-size: 15px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  z-index: 5;
  pointer-events: none;
  opacity: 0;
}
.result-flash.show { animation: flash 1.7s ease; }
.result-flash.w { border-color: rgba(61,220,151,.5); color: var(--win); background: rgba(61,220,151,.12); }
.result-flash.l { border-color: rgba(255,93,122,.4); color: var(--lose); background: rgba(255,93,122,.1); }
@keyframes flash {
  0% { opacity: 0; transform: translate(-50%, 10px) scale(.94); }
  14% { opacity: 1; transform: translate(-50%, 0) scale(1); }
  76% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -8px); }
}

/* ---- dice ---- */
.dice-board { width: 100%; max-width: 640px; }

.dice-track {
  position: relative;
  width: 100%;
  height: 14px;
  border-radius: 20px;
  background: var(--bg);
  border: 1px solid var(--line);
  margin: 74px 0 54px;
}

/* the two halves of the bar: where you win and where you lose */
.dice-zone {
  position: absolute;
  top: 1px; bottom: 1px;
  border-radius: 20px;
  transition: left .18s ease, width .18s ease;
}
.dice-zone.lose { background: linear-gradient(90deg, #3a2036, #4a2438); }
.dice-zone.win  { background: linear-gradient(90deg, #3ddc97, #22c58a); box-shadow: 0 0 18px rgba(61,220,151,.28); }

/* faint ticks left behind by recent rolls */
.dice-mark {
  position: absolute;
  top: -5px;
  width: 2px; height: 24px;
  margin-left: -1px;
  border-radius: 2px;
  background: var(--text-mute);
  opacity: .5;
  z-index: 2;
  transition: opacity .6s;
}
.dice-mark.w { background: var(--win); }
.dice-mark.l { background: var(--lose); }

.dice-thumb {
  position: absolute;
  top: 50%;
  width: 26px; height: 36px;
  margin-left: -13px;
  border-radius: 8px;
  background: var(--grad);
  transform: translateY(-50%);
  cursor: grab;
  box-shadow: 0 4px 14px rgba(124,92,255,.55);
  transition: left .1s;
  z-index: 4;
}
.dice-thumb::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: 2px; height: 14px;
  margin: -7px 0 0 -1px;
  border-radius: 2px;
  background: rgba(10,11,20,.5);
}
.dice-thumb:active { cursor: grabbing; }

/* Under a finger those three easings read as lag, and they do not even lag
   together: the thumb settles in .1s, the zones in .18s and the number above
   them in .22s, so the bar arrives after the touch and the figure after the
   bar. A drag is direct manipulation and everything it moves tracks it exactly;
   the easing is there for a target typed into the box, which still gets it. */
.dice-track.dragging .dice-thumb,
.dice-track.dragging .dice-marker,
.dice-track.dragging .dice-zone { transition: none; }

/* the target you set, sitting above the bar */
.dice-marker {
  position: absolute;
  bottom: 30px;
  transform: translateX(-50%);
  padding: 6px 12px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  transition: left .22s cubic-bezier(.2,.8,.3,1);
  z-index: 5;
}
.dice-marker::after {
  content: '';
  position: absolute;
  bottom: -5px; left: 50%;
  width: 9px; height: 9px;
  margin-left: -4.5px;
  background: inherit;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  transform: rotate(45deg);
}

/* where the roll actually landed, sitting below the bar */
.dice-pin {
  position: absolute;
  top: 32px;
  transform: translateX(-50%);
  padding: 7px 14px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-weight: 850;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  opacity: 0;
  z-index: 6;
  transition: left .55s cubic-bezier(.16,.9,.3,1), opacity .25s, background .25s, border-color .25s;
}
.dice-pin::before {
  content: '';
  position: absolute;
  top: -5px; left: 50%;
  width: 9px; height: 9px;
  margin-left: -4.5px;
  background: inherit;
  border-left: 1px solid var(--line);
  border-top: 1px solid var(--line);
  transform: rotate(45deg);
}
.dice-pin.on { opacity: 1; }
.dice-pin.rolling { transition: none; opacity: 1; color: var(--text-dim); }
.dice-pin.w {
  background: rgba(61,220,151,.16);
  border-color: rgba(61,220,151,.6);
  color: var(--win);
  box-shadow: 0 6px 22px rgba(61,220,151,.25);
}
.dice-pin.l {
  background: rgba(255,93,122,.13);
  border-color: rgba(255,93,122,.5);
  color: var(--lose);
}
.dice-pin.land { animation: pinland .5s cubic-bezier(.2,1.5,.4,1); }
@keyframes pinland {
  0%   { transform: translateX(-50%) translateY(-8px) scale(.9); }
  55%  { transform: translateX(-50%) translateY(2px) scale(1.06); }
  100% { transform: translateX(-50%) translateY(0) scale(1); }
}

.dice-scale {
  display: flex;
  justify-content: space-between;
  width: 100%;
  color: var(--text-mute);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

/* ---- limbo ---- */
.limbo-face { text-align: center; }
.limbo-value {
  font-size: 76px;
  font-weight: 850;
  letter-spacing: -3px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  transition: color .2s;
}
.limbo-value.w { color: var(--win); text-shadow: 0 0 44px rgba(61,220,151,.4); }
.limbo-value.l { color: var(--lose); }
.limbo-sub { color: var(--text-mute); margin-top: 10px; font-weight: 600; }

/* limbo scale: same reading as dice, on a log axis */
.limbo-board { width: 100%; max-width: 620px; margin-top: 44px; }
.limbo-track {
  position: relative;
  width: 100%;
  height: 14px;
  border-radius: 20px;
  background: var(--bg);
  border: 1px solid var(--line);
  margin-bottom: 46px;
}
.limbo-fill {
  position: absolute;
  top: 1px; bottom: 1px; left: 1px;
  width: 0;
  border-radius: 20px;
  background: linear-gradient(90deg, #7c5cff, #22d3ee);
  transition: width .6s cubic-bezier(.16,.9,.3,1), background .3s;
}
.limbo-fill.w { background: linear-gradient(90deg, #3ddc97, #22c58a); box-shadow: 0 0 18px rgba(61,220,151,.3); }
.limbo-fill.l { background: linear-gradient(90deg, #7a3350, #ff5d7a); }
.limbo-target {
  position: absolute;
  top: -7px;
  width: 3px; height: 28px;
  margin-left: -1.5px;
  border-radius: 3px;
  background: var(--gold);
  box-shadow: 0 0 10px rgba(255,176,32,.6);
  z-index: 3;
  transition: left .25s cubic-bezier(.2,.8,.3,1);
}
.limbo-target-label {
  position: absolute;
  bottom: 30px;
  transform: translateX(-50%);
  padding: 5px 11px;
  border-radius: 9px;
  background: rgba(255,176,32,.14);
  border: 1px solid rgba(255,176,32,.45);
  color: var(--gold);
  font-weight: 800;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  z-index: 4;
  transition: left .25s cubic-bezier(.2,.8,.3,1);
}
.limbo-pin {
  position: absolute;
  top: 30px;
  transform: translateX(-50%);
  padding: 6px 13px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-weight: 850;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  opacity: 0;
  z-index: 5;
  transition: left .6s cubic-bezier(.16,.9,.3,1), opacity .25s;
}
.limbo-pin::before {
  content: '';
  position: absolute;
  top: -5px; left: 50%;
  width: 9px; height: 9px;
  margin-left: -4.5px;
  background: inherit;
  border-left: 1px solid var(--line);
  border-top: 1px solid var(--line);
  transform: rotate(45deg);
}
.limbo-pin.on { opacity: 1; }
.limbo-pin.w { background: rgba(61,220,151,.16); border-color: rgba(61,220,151,.6); color: var(--win); }
.limbo-pin.l { background: rgba(255,93,122,.13); border-color: rgba(255,93,122,.5); color: var(--lose); }
.limbo-scale {
  display: flex;
  justify-content: space-between;
  width: 100%;
  color: var(--text-mute);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

/* ---- mines ---- */
.mine-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; width: min(100%, 420px); }
.tile {
  aspect-ratio: 1;
  border-radius: 11px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-bottom-width: 3px;
  display: grid;
  place-items: center;
  transition: transform .12s, background .16s, border-color .16s;
}
.tile:hover:not(:disabled) { transform: translateY(-2px); background: var(--surface-3); }
.tile:active:not(:disabled) { transform: translateY(1px); border-bottom-width: 1px; }
.tile:disabled { cursor: default; }
.tile svg { width: 42%; height: 42%; opacity: 0; transform: scale(.5); transition: opacity .2s, transform .25s cubic-bezier(.2,1.4,.4,1); }
.tile.open svg { opacity: 1; transform: scale(1); }
.tile.gem { background: rgba(34, 211, 238, .13); border-color: rgba(34, 211, 238, .4); }
.tile.bomb { background: rgba(255, 93, 122, .16); border-color: rgba(255, 93, 122, .5); }
.tile.faded { opacity: .34; }

/* ---- towers ---- */
.tower { display: flex; flex-direction: column-reverse; gap: 7px; width: min(100%, 400px); }
.tower-row { display: flex; gap: 7px; align-items: center; }
.tower-row .lv { width: 46px; font-size: 11px; color: var(--text-mute); font-variant-numeric: tabular-nums; text-align: right; flex: none; }
.tower-row .cells { display: flex; gap: 7px; flex: 1; }
.tower-cell {
  flex: 1;
  height: 40px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  font-size: 15px;
  transition: background .15s, border-color .15s, transform .1s;
}
.tower-row.active .tower-cell:hover { background: var(--surface-3); transform: translateY(-2px); border-color: var(--violet); }
.tower-row.done { opacity: .5; }
.tower-row.active { box-shadow: -3px 0 0 var(--violet); border-radius: 3px; }
.tower-cell.safe { background: rgba(61,220,151,.16); border-color: rgba(61,220,151,.45); }
.tower-cell.dead { background: rgba(255,93,122,.16); border-color: rgba(255,93,122,.45); }

/* ---- plinko ---- */
.plinko-stage { position: relative; width: 100%; max-width: 560px; }
.plinko-canvas { width: 100%; display: block; }
.plinko-buckets { display: flex; gap: 3px; margin-top: 8px; }
.plinko-bucket {
  flex: 1;
  min-width: 0;
  text-align: center;
  padding: 5px 1px;
  border-radius: 6px;
  font-size: 10.5px;
  font-weight: 750;
  color: #10121e;
  font-variant-numeric: tabular-nums;
  transition: transform .16s;
}
.plinko-bucket.hit { animation: bhit .45s cubic-bezier(.2,1.6,.4,1); }
@keyframes bhit { 0% { transform: translateY(0); } 36% { transform: translateY(9px); } 100% { transform: translateY(0); } }

/* ---- keno ---- */
/* Every track is minmax(0, 1fr) rather than 1fr, and every cell may shrink.
   This is what stops the board pushing the whole page sideways on a phone:
   `1fr` is `minmax(auto, 1fr)`, and `auto` there means "no smaller than the
   content" - which, for a cell carrying both an aspect-ratio and a min-height,
   works out as the height times the ratio. Six of those plus the gaps came to
   about 400px of unshrinkable track on a 360px screen, and the page scrolled. */
.keno-grid {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 8px;
  width: min(100%, 470px);
  max-width: 100%;
}
.keno-cell {
  min-width: 0;
  aspect-ratio: 1;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-bottom-width: 3px;
  font-weight: 700;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  transition: transform .12s, background .16s, color .16s, border-color .16s;
}
.keno-cell:hover:not(:disabled) { transform: translateY(-2px); color: var(--text); }
.keno-cell.picked { background: var(--grad); color: #0a0b14; border-color: transparent; }
.keno-cell.drawn { background: var(--surface-3); color: var(--text); border-color: var(--cyan); }
.keno-cell.hit { background: linear-gradient(120deg, #3ddc97, #22c58a); color: #062a18; border-color: transparent; animation: pop .32s cubic-bezier(.2,1.5,.4,1); }
@keyframes pop { 0% { transform: scale(.72); } 100% { transform: scale(1); } }
.keno-pays { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 16px; justify-content: center; }
.keno-pay {
  padding: 5px 10px;
  border-radius: 8px;
  background: var(--surface-2);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  border: 1px solid transparent;
}
.keno-pay.on { border-color: var(--win); color: var(--win); }

/* ---- wheel ---- */
.wheel-wrap { position: relative; width: min(100%, 400px); aspect-ratio: 1; }
.wheel-svg { width: 100%; height: 100%; transition: transform 4.4s cubic-bezier(.13, .78, .16, 1); }
.wheel-pin {
  position: absolute;
  top: -4px; left: 50%;
  margin-left: -9px;
  width: 18px; height: 26px;
  background: var(--grad-gold);
  clip-path: polygon(50% 100%, 0 0, 100% 0);
  z-index: 3;
  filter: drop-shadow(0 3px 6px rgba(0,0,0,.6));
}
.wheel-center {
  position: absolute;
  inset: 32%;
  border-radius: 50%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  font-size: 25px;
  font-weight: 850;
  font-variant-numeric: tabular-nums;
}

/* ---- hilo / blackjack cards ---- */
.card-face {
  width: 78px; height: 108px;
  border-radius: 9px;
  background: linear-gradient(160deg, #fdfdff, #e4e7f2);
  color: #12141f;
  position: relative;
  flex: none;
  box-shadow: 0 6px 18px rgba(0,0,0,.45);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 30px;
}
.card-face.sm { width: 56px; height: 78px; font-size: 21px; }
.card-face .corner { position: absolute; top: 5px; left: 7px; font-size: 13px; line-height: 1; font-weight: 800; }
.card-face .corner.br { top: auto; left: auto; bottom: 5px; right: 7px; transform: rotate(180deg); }
.card-face.red { color: #d92244; }

/* "10" is twice as wide as every other rank, so tuck its corners in slightly
   and tighten the glyph rather than letting it spill off the card. */
.card-face.wide-rank .corner { letter-spacing: -.5px; font-size: 12px; }
.card-face.wide-rank .corner:not(.br) { left: 5px; }
.card-face.wide-rank .corner.br { right: 5px; }
.poker-cards .card-face.wide-rank .corner { font-size: 8.5px; }
.card-face.back {
  background: repeating-linear-gradient(45deg, #2a2f5c 0 7px, #1e2347 7px 14px);
  border: 2px solid var(--surface-3);
}
.card-face.deal { animation: deal .34s cubic-bezier(.2,.9,.3,1); }
@keyframes deal { from { opacity: 0; transform: translateY(-22px) rotate(-7deg); } to { opacity: 1; transform: none; } }

.hand { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; align-items: center; }
.hand-row { display: flex; flex-direction: column; align-items: center; gap: 9px; }
.hand-label { font-size: 11.5px; color: var(--text-mute); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.hand-total {
  padding: 3px 11px;
  border-radius: 20px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-weight: 750;
  font-variant-numeric: tabular-nums;
}
.hand-seat { padding: 10px; border-radius: 12px; border: 1px solid transparent; transition: border-color .16s, background .16s; }
.hand-seat.active { border-color: var(--violet); background: rgba(124,92,255,.07); }
.hand-seat.won { border-color: rgba(61,220,151,.5); background: rgba(61,220,151,.07); }
.hand-seat.lost { opacity: .55; }

.hilo-odds { display: flex; gap: 10px; width: min(100%, 340px); margin-top: 20px; }
.hilo-btn {
  flex: 1;
  padding: 14px;
  border-radius: 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  text-align: center;
  transition: background .15s, border-color .15s, transform .1s;
}
.hilo-btn:hover:not(:disabled) { background: var(--surface-3); border-color: var(--violet); transform: translateY(-2px); }
.hilo-btn b { display: block; font-size: 16px; }
.hilo-btn span { font-size: 11.5px; color: var(--text-mute); }
.chain { display: flex; gap: 5px; flex-wrap: wrap; justify-content: center; margin-top: 16px; max-width: 480px; }

/* ---- gems ---- */
.gem-row { display: flex; gap: 12px; justify-content: center; }
.gem-slot {
  width: 74px; height: 74px;
  border-radius: 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
}
.gem-slot svg { width: 44px; height: 44px; }
.gem-slot.match { border-color: var(--win); background: rgba(61,220,151,.1); animation: pop .3s cubic-bezier(.2,1.5,.4,1); }

/* ---- coin flip ---- */
.coin3d { width: 128px; height: 128px; perspective: 800px; }
.coin3d .inner { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 1.5s cubic-bezier(.28,.72,.3,1); }
.coin3d .side {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-weight: 900;
  font-size: 34px;
  backface-visibility: hidden;
  box-shadow: inset 0 -6px 16px rgba(0,0,0,.3);
}
.coin3d .heads { background: var(--grad-gold); color: #3a2600; }
.coin3d .tails { background: linear-gradient(120deg, #b9c3e8, #7c88b8); color: #1b1f36; transform: rotateY(180deg); }

/* ---- crash ---- */
.crash-stage { width: 100%; max-width: 680px; }
.crash-canvas { width: 100%; height: 300px; display: block; border-radius: 12px; background: var(--bg); border: 1px solid var(--line-soft); }
.crash-mult {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  font-size: 60px;
  font-weight: 850;
  letter-spacing: -2px;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  text-shadow: 0 6px 30px rgba(0,0,0,.6);
}
.crash-mult.busted { color: var(--lose); }
.crash-mult small { display: block; font-size: 14px; font-weight: 650; letter-spacing: 0; color: var(--text-dim); text-align: center; margin-top: 6px; }
.crash-hist { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.crash-chip {
  padding: 3px 9px;
  border-radius: 20px;
  font-size: 11.5px;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  background: var(--surface-2);
  color: var(--text-dim);
}
.crash-chip.hi { background: rgba(61,220,151,.15); color: var(--win); }
.crash-chip.lo { background: rgba(255,93,122,.13); color: var(--lose); }
.crash-players { max-height: 210px; overflow-y: auto; }

/* ---- hold'em ---- */
/* Seats sit on the rim of the table and are centred on it, so half of each
   block hangs outside the felt. This padding is the room they need - without it
   the top and bottom seats are clipped by the edge of the stage. */
.poker-wrap {
  width: min(100%, 640px);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 62px 0 10px;
}

.poker-table {
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 2;
  border-radius: 50% / 42%;
  background:
    radial-gradient(120% 120% at 50% 20%, #1d7a58 0%, #145741 55%, #0f4231 100%);
  border: 7px solid #2a1d15;
  box-shadow: inset 0 0 60px rgba(0,0,0,.45), 0 16px 40px rgba(0,0,0,.5);
}
.poker-felt-ring {
  position: absolute;
  inset: 9%;
  border-radius: 50% / 42%;
  border: 1px solid rgba(255,255,255,.09);
  pointer-events: none;
}

/* the middle of the table: pot then community cards.

   Above the seats on purpose. A seat is a fixed-width block and the chips it
   pushes forward hang off its bottom edge, so on a narrow screen the top-left
   and top-right seats reach the middle of the felt - and being later in the
   markup, they used to paint over the flop. A bet pill with a corner tucked
   behind a card still reads; a card with its rank covered does not. */
.poker-centre {
  position: absolute;
  z-index: 2;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 100%;
}
.poker-pot {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 14px;
  border-radius: 20px;
  background: rgba(8,10,18,.6);
  border: 1px solid rgba(255,255,255,.12);
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  font-size: 13px;
}
.poker-board { display: flex; gap: 6px; justify-content: center; min-height: 78px; align-items: center; }
.poker-board .card-face { width: 52px; height: 74px; font-size: 19px; }
.poker-board .card-slot {
  width: 52px; height: 74px;
  border-radius: 8px;
  border: 1px dashed rgba(255,255,255,.14);
}

/* seats around the rim */
.poker-seat {
  position: absolute;
  z-index: 1;
  width: 132px;
  transform: translate(-50%, -50%);
  text-align: center;
}
.poker-seat.s-top    { top: 6%;  left: 50%; }
.poker-seat.s-left   { top: 50%; left: 6%; }
.poker-seat.s-right  { top: 50%; left: 94%; }
.poker-seat.s-bottom { top: 91%; left: 50%; }

/* six-handed ring, player at the bottom, then clockwise */
.poker-seat.s6-b  { top: 92%; left: 50%; }
.poker-seat.s6-bl { top: 76%; left: 11%; }
.poker-seat.s6-tl { top: 27%; left: 8%; }
.poker-seat.s6-t  { top: 8%;  left: 50%; }
.poker-seat.s6-tr { top: 27%; left: 92%; }
.poker-seat.s6-br { top: 76%; left: 89%; }

.poker-cards { display: flex; gap: 4px; justify-content: center; margin-bottom: 5px; }
/* the top rail draws its cards under the name plate, so the gap flips sides */
.poker-seat.s6-tl .poker-cards,
.poker-seat.s6-t  .poker-cards,
.poker-seat.s6-tr .poker-cards,
.poker-seat.s-top .poker-cards { margin-bottom: 0; margin-top: 5px; }
.poker-cards .card-face { width: 40px; height: 56px; font-size: 15px; }

/* Only shrink the corner pips here. Setting top/left as well would outrank the
   .corner.br rule that pins the second corner to the bottom right, and both
   would end up stacked in the same spot. */
.poker-cards .card-face .corner { font-size: 9px; }
.poker-cards .card-face .corner:not(.br) { top: 3px; left: 4px; }
.poker-cards .card-face .corner.br { bottom: 3px; right: 4px; }

.poker-plate {
  display: inline-block;
  min-width: 106px;
  padding: 5px 9px;
  border-radius: 9px;
  background: rgba(8,10,18,.74);
  border: 1px solid var(--line);
  backdrop-filter: blur(4px);
}
.poker-plate .who { font-size: 12px; font-weight: 700; }
.poker-plate .chips { font-size: 11.5px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.poker-seat.acting .poker-plate { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(255,176,32,.28); }
.poker-seat.won .poker-plate { border-color: var(--win); background: rgba(61,220,151,.16); }
.poker-seat.folded { opacity: .42; }
.poker-seat .made {
  display: block;
  font-size: 10.5px;
  color: var(--gold);
  margin-top: 2px;
}

/* chips a seat has pushed forward this street */
.poker-bet {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 5px;
  padding: 2px 9px;
  border-radius: 20px;
  background: var(--grad-gold);
  color: #2b1c00;
  font-size: 11px;
  font-weight: 850;
  font-variant-numeric: tabular-nums;
}

/* ---- the showdown -------------------------------------------------------
   A hand used to settle and hand the table straight back, so the one moment
   worth looking at - whose cards were turned over, and which five made the
   hand - went past in a single frame. The table is now held until the player
   asks for the next hand, and these rules are what make the held table
   readable: opponents' cards turn over, the five that played light up, and
   everything else steps back.
   ------------------------------------------------------------------------ */

/* an opponent's card turning face up at the showdown */
.card-face.turned {
  animation: cardturn .5s cubic-bezier(.3,.85,.3,1) backwards;
}
@keyframes cardturn {
  0%   { transform: rotateY(88deg) scale(.9); opacity: .25; }
  60%  { transform: rotateY(0) scale(1.06); opacity: 1; }
  100% { transform: rotateY(0) scale(1); opacity: 1; }
}

/* the five cards the winning hand is actually made of, and the ones that
   played no part in it */
.poker-table.showdown .card-face.used {
  box-shadow: 0 0 0 2px var(--gold), 0 8px 22px rgba(255,176,32,.35);
  z-index: 2;
}
.poker-table.showdown .card-face.spare { opacity: .5; filter: saturate(.55); }

/* a seat that showed its hand */
.poker-seat.shown .poker-plate { border-color: var(--gold); }
.poker-seat.folded .poker-cards { opacity: .55; }
.poker-plate .mucked {
  display: block;
  font-size: 10px;
  color: var(--text-mute);
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-top: 2px;
}

/* chips pushed to a winner, in place of the bet they had out */
.poker-bet.win {
  background: linear-gradient(120deg, #6ff0b6 0%, var(--win) 100%);
  color: #05291b;
}

/* the panel that replaces Deal while the table is being read */
.poker-end {
  margin-top: 6px;
  padding: 13px 14px 14px;
  border-radius: var(--r);
  background: var(--surface);
  border: 1px solid var(--line);
}
.poker-end-title { font-size: 17px; font-weight: 850; }
.poker-end-title.w { color: var(--win); }
.poker-end-title.l { color: var(--lose); }
.poker-end-line { font-size: 12.5px; color: var(--text-dim); margin-top: 2px; }
.poker-end-rows { margin-top: 10px; display: grid; gap: 5px; }
.poker-end-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: 12.5px;
}
.poker-end-row span { color: var(--text-mute); }
.poker-end-row b { font-variant-numeric: tabular-nums; text-align: right; }

/* The bottom seat hangs below the felt - its plate, its cards and the chip it
   has in - so the log starts far enough down to clear all three, and nothing
   sits under it: the room that used to be left there was room nothing used,
   and on a phone it was what pushed the hand's buttons off the screen. */
.poker-log {
  width: 100%;
  margin-top: 64px;
  max-height: 70px;
  overflow-y: auto;
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.35;
}
.poker-log div { border-bottom: 1px solid var(--line-soft); padding: 2px 0; }
.poker-log div:last-child { color: var(--text); }

.poker-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 6px; }
.poker-raise { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: center; margin-top: 8px; }
.poker-raise input[type=range] { width: 100%; accent-color: var(--violet); }
.poker-quick { display: flex; gap: 5px; margin-top: 8px; }
.poker-quick button {
  flex: 1;
  padding: 6px 4px;
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: 11.5px;
  font-weight: 700;
}
.poker-quick button:hover { background: var(--surface-3); color: var(--text); }

@media (max-width: 860px) {
  .poker-wrap { padding: 50px 0 8px; }
  .poker-log { margin-top: 56px; }
  .game-panel.pk-live > .field:first-of-type { order: 6; margin: 10px 0 0; }
  .poker-seat { width: 100px; }
  .poker-cards .card-face { width: 30px; height: 42px; font-size: 11px; }
  .poker-cards .card-face .corner { font-size: 7.5px; }
  .poker-board .card-face, .poker-board .card-slot { width: 38px; height: 54px; font-size: 14px; }
  .poker-board .card-face .corner { font-size: 10px; }
  .poker-plate { min-width: 78px; padding: 4px 6px; }
  .poker-plate .who { font-size: 11px; }
  .poker-plate .chips { font-size: 10px; }

  /* A seat block is a fixed width, so on a narrow screen the ones on the rim
     hang off the edge. Tuck them further onto the felt rather than letting the
     table run past the viewport. */
  .poker-seat.s6-bl { left: 17%; }
  .poker-seat.s6-tl { left: 15%; }
  .poker-seat.s6-tr { left: 85%; }
  .poker-seat.s6-br { left: 83%; }
  .poker-seat.s-left  { left: 16%; }
  .poker-seat.s-right { left: 84%; }
}

@media (max-width: 560px) {
  /* A board that cannot shrink any further should scroll rather than be sliced
     down the middle. The roulette felt is the one with a hard minimum: twelve
     number columns plus the zero and the 2:1 column. */
  .game-stage { overflow-x: auto; overflow-y: hidden; }

  /* keep the board, the stake and the bet button on one screenful */
  /* The result marker is centred on its value, so at 0 or 100 half of it sits
     outside the bar. Pad the board by half a marker so the overhang lands
     inside the board instead of off the side of the screen. */
  .dice-board, .limbo-board { padding: 0 30px; }
  .dice-pin, .limbo-pin { padding: 5px 9px; font-size: 13px; }
  .dice-marker, .limbo-target-label { padding: 4px 8px; font-size: 11.5px; }
  .dice-scale, .limbo-scale { font-size: 10.5px; }

  .game-stage { min-height: 300px; padding: 14px; }
  .game-panel { padding: 12px; }

  /* Five 74px stones and their gaps come to 418px, which is wider than the
     phone they were being drawn on - the board could only be seen by dragging
     it sideways. They divide the width they are given instead. */
  .gem-row { gap: 7px; width: 100%; }
  .gem-slot { flex: 1 1 0; width: auto; height: auto; min-width: 0; max-width: 74px; aspect-ratio: 1; }
  .gem-slot svg { width: 68%; height: 68%; }
  .page.wide { padding-left: 10px; padding-right: 10px; }

  .poker-wrap { padding: 44px 0 6px; }
  .poker-log { margin-top: 42px; max-height: 62px; font-size: 11.5px; }
  .poker-seat { width: 84px; }
  /* The bots' cards are face down almost all the time, so they can shrink.
     Your own two are the ones you have to read, so they keep their rank and
     stay big enough to see. */
  .poker-cards .card-face { width: 25px; height: 35px; font-size: 9px; }
  .poker-cards:not(.mine) .card-face .corner { display: none; }

  /* ...but a hand that has been turned over has to be readable, and a bare
     suit glyph is not a card. At the showdown the shown seats get their rank
     back and a little more room to put it in. */
  .poker-table.showdown .poker-seat.shown .poker-cards .card-face {
    width: 34px; height: 48px; font-size: 13px;
  }
  .poker-table.showdown .poker-seat.shown .poker-cards .card-face .corner {
    display: block; font-size: 8.5px;
  }
  .poker-table.showdown .poker-seat.shown .poker-cards .card-face.wide-rank .corner { font-size: 7.5px; }

  .poker-cards.mine { gap: 6px; }
  .poker-cards.mine .card-face { width: 46px; height: 64px; font-size: 19px; }
  .poker-cards.mine .card-face .corner { display: block; font-size: 11px; }
  .poker-cards.mine .card-face.wide-rank .corner { font-size: 10px; }
  /* The community cards are the hand everybody is playing, so they are read as
     often as your own two and are now drawn the same way: the rank in the
     corner and one suit in the middle, at a size that can be read without
     leaning in. The second corner is the part that does not fit - a card needs
     only one of them, and dropping it is what buys the room for the rest. */
  /* 36px filled the width between the two rails exactly, which left the flop
     touching the chips the corner seats push forward - the first card sat
     under a gold pill on a narrow phone. 33px and a tighter gap buy back the
     dozen pixels that moves them apart on a 360px screen and up; below that
     the felt simply has no room, and the layer order is what keeps the card
     readable. The legibility comes from dropping the second corner rather
     than from size. */
  /* The row is only as tall as the cards in it now. The old 62px left a band
     of empty box above and below them that reached the plate of the seat below,
     and since the board sits on the upper layer that band was covering a name. */
  .poker-board { gap: 4px; min-height: 49px; }
  .poker-board .card-face, .poker-board .card-slot { width: 33px; height: 47px; font-size: 14px; }
  .poker-board .card-face .corner { display: block; font-size: 10px; top: 3px; left: 4px; }
  /* the bottom pair sit a little lower, clear of the community cards */
  .poker-seat.s6-bl, .poker-seat.s6-br { top: 79%; }
  .poker-board .card-face.wide-rank .corner { font-size: 9.5px; letter-spacing: -.5px; }
  .poker-board .card-face .corner.br { display: none; }
  .poker-plate { min-width: 66px; }
  .poker-plate .who { font-size: 10px; }
  .poker-plate .chips { font-size: 9px; }
  /* A 3:2 table is too flat for six seats on a phone: the bottom seat's plate
     climbs over the community cards, which is exactly where the showdown has
     to be readable. Give it more height and spread the ring into it. */
  .poker-table { aspect-ratio: 6 / 5; }
  .poker-centre { top: 45%; gap: 7px; }
  .poker-seat.s6-b  { top: 88%; }
  .poker-seat.s6-bl { top: 71%; left: 12%; }
  .poker-seat.s6-br { top: 71%; left: 88%; }
  .poker-seat.s6-tl { top: 26%; left: 14%; }
  .poker-seat.s6-tr { top: 26%; left: 86%; }
  .poker-seat.s6-t  { top: 15%; }
  .poker-bet { font-size: 10px; padding: 1px 7px; }
  .poker-seat:not(.s6-b) .poker-cards { margin-bottom: 3px; }
}

/* ---- roulette ---- */
.roul-felt {
  position: relative;
  display: grid;
  grid-template-columns: 44px repeat(12, 1fr) 46px;
  gap: 3px;
  width: 100%;
  max-width: 640px;
}
.rn {
  aspect-ratio: 1 / .84;
  border-radius: 5px;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  position: relative;
  transition: filter .13s, transform .1s;
}
.rn:hover { filter: brightness(1.35); transform: translateY(-1px); }
.rn.red { background: #c9304a; color: #fff; }
.rn.black { background: #22273f; color: #fff; }
.rn.green { background: #17845c; color: #fff; aspect-ratio: auto; }
/* the single zero, a full-height cell down the left edge of the felt */
.roul-zeros {
  grid-row: span 3;
  display: grid;
}
.roul-zeros .rn { height: 100%; }
.rn.out { background: var(--surface-2); color: var(--text-dim); font-size: 11px; }
.rn.hitwin { outline: 2px solid var(--gold); outline-offset: 1px; }
.rn .chip-on {
  position: absolute;
  top: -5px; right: -5px;
  min-width: 19px;
  height: 19px;
  padding: 0 4px;
  border-radius: 20px;
  background: var(--grad-gold);
  color: #2b1c00;
  font-size: 10px;
  font-weight: 850;
  display: grid;
  place-items: center;
  box-shadow: 0 2px 7px rgba(0,0,0,.5);
}
/* Split and corner markers, sitting on the lines between the numbers. They are
   faintly visible so they can be found, and light up under the cursor. */
.roul-outside { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; max-width: 640px; width: 100%; margin-top: 5px; }
.roul-outside .rn { aspect-ratio: auto; padding: 9px 4px; }
/* ---------------------------------------------------------------------------
   The wheel
   -------------------------------------------------------------------------
   Two layers over one SVG: the head, and the track the ball rides. They turn
   in opposite directions because that is how a wheel is dealt, and both are
   plain transforms so the browser composites them without touching layout -
   the felt beside them keeps taking taps all the way through a spin.
   --------------------------------------------------------------------------- */
.roul-wheelbox {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 16px;
  width: 100%;
  justify-content: center;
}
.roul-readout { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }

.roul-wheel {
  position: relative;
  width: 216px;
  height: 216px;
  flex: none;
}
.roul-head,
.roul-balltrack {
  position: absolute;
  inset: 0;
  /* the head eases to a stop; the ball rides a beat longer and drops in */
  transition-property: transform;
  transition-duration: 0ms;
}
.roul-head { transition-timing-function: cubic-bezier(.16, .72, .19, 1); }
.roul-balltrack { transition-timing-function: cubic-bezier(.2, .62, .16, 1); }
.roul-head svg {
  width: 100%;
  height: 100%;
  display: block;
  filter: drop-shadow(0 14px 30px rgba(0, 0, 0, .62));
}
/* The fixed highlight: a sheen from the top left and the wheel's own shadow
   falling away from it. Outside the rotating layers on purpose - see the note
   where it is built. */
.roul-gloss {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  z-index: 2;
  background:
    radial-gradient(circle at 30% 20%, rgba(255, 255, 255, .20), rgba(255, 255, 255, .05) 40%, transparent 62%),
    radial-gradient(circle at 72% 86%, rgba(0, 0, 0, .38), transparent 54%);
}

.roul-ball {
  position: absolute;
  left: 50%;
  top: 6.2%;
  z-index: 3;
  width: 13px;
  height: 13px;
  margin-left: -6.5px;
  border-radius: 50%;
  background: radial-gradient(circle at 33% 30%, #fff, #ccd4e2 55%, #8a94a8);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .78);
}

@media (prefers-reduced-motion: reduce) {
  .roul-head, .roul-balltrack { transition-duration: 1ms !important; }
}
.roul-result {
  width: 74px; height: 74px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 27px;
  font-weight: 850;
  border: 3px solid var(--line);
}
.roul-result.red { background: #c9304a; }
.roul-result.black { background: #22273f; }
.roul-result.green { background: #17845c; }

/* ---------------------------------------------------------------------------
   The spin window

   Where the wheel goes for the length of a spin on a screen that has no room
   to keep it. It sits above the nav so the table is covered while the ball is
   still in the air, and below the sign-in dialog and the toasts, which both
   have things to say that outrank a wheel. It closes itself; a tap only means
   the player has already seen enough.
   --------------------------------------------------------------------------- */
.roul-modal {
  position: fixed;
  inset: 0;
  z-index: 190;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(5, 7, 14, .74);
  backdrop-filter: blur(4px);
  opacity: 0;
  pointer-events: none;
  transition: opacity .24s ease;
}
.roul-modal.on { opacity: 1; pointer-events: auto; }

.roul-modal-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
  padding: 20px 24px 18px;
  border-radius: var(--r);
  background: var(--bg-2);
  border: 1px solid var(--line);
  box-shadow: 0 26px 70px rgba(0, 0, 0, .62);
  transform: scale(.9) translateY(10px);
  transition: transform .3s cubic-bezier(.2, 1.2, .35, 1);
}
.roul-modal.on .roul-modal-card { transform: none; }

.roul-modal-note {
  font-size: 11.5px;
  font-weight: 750;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--text-mute);
}

/* the wheel is display:none on exactly the screens this window exists for */
.roul-modal .roul-wheel { display: block; width: 252px; height: 252px; }
.roul-modal .roul-ball { width: 15px; height: 15px; margin-left: -7.5px; }

.roul-modal-num {
  min-width: 78px;
  padding: 6px 18px;
  border-radius: 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 30px;
  font-weight: 850;
  font-variant-numeric: tabular-nums;
  text-align: center;
  line-height: 1.2;
}
.roul-modal-num.red { background: #c9304a; border-color: #e0566d; color: #fff; }
.roul-modal-num.black { background: #22273f; border-color: #39405f; color: #fff; }
.roul-modal-num.green { background: #17845c; border-color: #2aa878; color: #fff; }
.roul-modal-num.landed { animation: roul-land .46s cubic-bezier(.2, 1.5, .4, 1); }
@keyframes roul-land {
  0%   { transform: scale(.82); }
  55%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}

@media (max-width: 380px) {
  .roul-modal { padding: 14px; }
  .roul-modal .roul-wheel { width: 214px; height: 214px; }
  .roul-modal-num { font-size: 26px; }
}

@media (prefers-reduced-motion: reduce) {
  .roul-modal, .roul-modal-card { transition-duration: 1ms; }
  .roul-modal-num.landed { animation: none; }
}

/* ==========================================================================
   Reveal polish - shared by every game
   ========================================================================== */

/* the stage breathes once when a win lands */
.game-stage.win-glow::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(60% 50% at 50% 50%, rgba(61,220,151,.16), transparent 70%);
  animation: glowpulse 1.2s ease;
}
.game-stage.lose-glow::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(60% 50% at 50% 50%, rgba(255,93,122,.11), transparent 70%);
  animation: glowpulse 1s ease;
}
@keyframes glowpulse { 0% { opacity: 0; } 22% { opacity: 1; } 100% { opacity: 0; } }

/* while a reveal is playing, the board stops accepting clicks */
.game-stage.busy { cursor: progress; }
.game-stage.busy .tile:not(.open),
.game-stage.busy .keno-cell,
.game-stage.busy .tower-cell,
.game-stage.busy .hilo-btn,
.game-stage.busy .rn { pointer-events: none; }

/* dealt cards arrive one after another rather than all at once */
.hand .card-face.deal:nth-child(1) { animation-delay: 0ms; }
.hand .card-face.deal:nth-child(2) { animation-delay: 110ms; }
.hand .card-face.deal:nth-child(3) { animation-delay: 220ms; }
.hand .card-face.deal:nth-child(4) { animation-delay: 330ms; }
.hand .card-face.deal:nth-child(5) { animation-delay: 440ms; }
.hand .card-face.deal:nth-child(n+6) { animation-delay: 520ms; }
.card-face.deal { animation-fill-mode: backwards; }

/* a card turning from face-down to face-up */
.card-face.flip { animation: cardflip .42s cubic-bezier(.3,.8,.3,1); }
@keyframes cardflip {
  0%   { transform: rotateY(90deg) scale(.94); opacity: .4; }
  100% { transform: rotateY(0) scale(1); opacity: 1; }
}

/* a small strip of recent outcomes, used under dice and limbo */
.recent-strip {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 26px;
  min-height: 24px;
}
.recent-strip .crash-chip { animation: slidein .3s cubic-bezier(.2,.8,.3,1); }

/* keno numbers pop in as they are drawn */
.keno-cell.drawing { animation: pop .3s cubic-bezier(.2,1.5,.4,1); }

/* mines tiles turn over rather than blink on */
.tile.open { animation: tileturn .3s cubic-bezier(.3,.9,.3,1); }
@keyframes tileturn {
  0%   { transform: rotateY(80deg); }
  100% { transform: rotateY(0); }
}

/* the multiplier readout ticks up as a round builds */
.live-mult {
  font-variant-numeric: tabular-nums;
  transition: color .2s;
}
.live-mult.up { animation: bump .4s ease; }

/* ==========================================================================
   Shop / wallet / fairness
   ========================================================================== */

.pack-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); gap: 15px; }
.pack {
  position: relative;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--surface);
  padding: 22px 18px 18px;
  text-align: center;
  transition: transform .16s, border-color .16s, box-shadow .16s;
}
.pack:hover { transform: translateY(-4px); border-color: var(--gold); box-shadow: 0 14px 30px rgba(0,0,0,.42); }
.pack.popular { border-color: var(--gold); }
.pack .flag {
  position: absolute;
  top: -10px; left: 50%;
  transform: translateX(-50%);
  padding: 3px 12px;
  border-radius: 20px;
  background: var(--grad-gold);
  color: #2b1c00;
  font-size: 10.5px;
  font-weight: 850;
  letter-spacing: .04em;
  white-space: nowrap;
}
.pack-coins { display: flex; align-items: center; justify-content: center; gap: 7px; font-size: 23px; font-weight: 800; font-variant-numeric: tabular-nums; margin: 12px 0 3px; }
.pack-bonus { color: var(--win); font-size: 12px; font-weight: 700; min-height: 18px; }
.pack-price { font-size: 17px; font-weight: 750; margin: 14px 0 12px; }
.pack-art { height: 56px; display: grid; place-items: center; }
.pack-art svg { height: 52px; }

.notice {
  display: flex;
  gap: 12px;
  padding: 14px 16px;
  border-radius: var(--r);
  background: rgba(255, 176, 32, .07);
  border: 1px solid rgba(255, 176, 32, .26);
  color: #f0d5a2;
  font-size: 13px;
  line-height: 1.55;
}
.notice.info { background: rgba(124, 92, 255, .07); border-color: rgba(124, 92, 255, .28); color: #c6bcff; }
.notice svg { flex: none; margin-top: 1px; }

.bonus-card {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  background: linear-gradient(115deg, #1d1a42, #141830);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 22px;
}
.bonus-clock { font-size: 27px; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -.5px; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); gap: 13px; }
.stat {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  padding: 16px;
}
.stat .k { font-size: 11px; color: var(--text-mute); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.stat .v { font-size: 21px; font-weight: 780; margin-top: 5px; font-variant-numeric: tabular-nums; }

.seedbox {
  font-family: var(--mono);
  font-size: 11.5px;
  word-break: break-all;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 10px 12px;
  color: var(--text-dim);
}

.steps { counter-reset: s; display: grid; gap: 14px; }
.step { display: flex; gap: 13px; }
.step::before {
  counter-increment: s;
  content: counter(s);
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--surface-2);
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 800;
  color: var(--violet);
  flex: none;
}
.step b { display: block; margin-bottom: 2px; }
.step p { margin: 0; color: var(--text-dim); font-size: 13px; }

/* ==========================================================================
   Modal / toast
   ========================================================================== */

.modal-back {
  position: fixed;
  inset: 0;
  background: rgba(4, 5, 10, .74);
  backdrop-filter: blur(7px);
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 20px;
  animation: fade .18s ease;
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.modal {
  width: 100%;
  max-width: 428px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 26px;
  box-shadow: var(--shadow);
  animation: rise .24s cubic-bezier(.2,.9,.3,1);
  max-height: 90vh;
  overflow-y: auto;
}
.modal.wide { max-width: 640px; }
@keyframes rise { from { opacity: 0; transform: translateY(14px) scale(.98); } to { opacity: 1; transform: none; } }
.modal h2 { margin: 0 0 4px; font-size: 21px; font-weight: 780; letter-spacing: -.3px; }
.modal .lede { color: var(--text-dim); margin: 0 0 20px; font-size: 13.5px; }
.modal-x { position: absolute; top: 14px; right: 14px; }
/* the title starts on the right in Hebrew and Arabic, so the close button goes left */
[dir=rtl] .modal-x { right: auto; left: 14px; }
.modal-head { position: relative; padding-inline-end: 40px; }   /* room for the close button */

.tabs-line { display: flex; gap: 4px; background: var(--bg-2); padding: 4px; border-radius: 11px; margin-bottom: 20px; }
.tabs-line button { flex: 1; padding: 9px; border-radius: 8px; font-weight: 700; font-size: 13.5px; color: var(--text-dim); }
.tabs-line button.on { background: var(--surface-2); color: var(--text); }

.check { display: flex; gap: 9px; align-items: flex-start; font-size: 12.5px; color: var(--text-dim); cursor: pointer; }
.check input { margin-top: 2px; accent-color: var(--violet); width: 15px; height: 15px; flex: none; }

.err {
  background: rgba(255, 93, 122, .11);
  border: 1px solid rgba(255, 93, 122, .32);
  color: #ffb3c0;
  padding: 9px 12px;
  border-radius: 9px;
  font-size: 12.5px;
  margin-bottom: 14px;
}

.toast-wrap { position: fixed; bottom: 20px; right: 20px; z-index: 300; display: flex; flex-direction: column; gap: 9px; align-items: flex-end; }
.toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: 11px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  font-size: 13px;
  font-weight: 600;
  max-width: 340px;
  animation: toastin .26s cubic-bezier(.2,.9,.3,1);
}
.toast.out { animation: toastout .22s ease forwards; }
.toast.good { border-color: rgba(61,220,151,.45); }
.toast.bad { border-color: rgba(255,93,122,.45); }
@keyframes toastin { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }
@keyframes toastout { to { opacity: 0; transform: translateX(24px); } }

.spinner {
  width: 15px; height: 15px;
  border: 2px solid rgba(255,255,255,.25);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.skeleton {
  background: linear-gradient(90deg, var(--surface) 25%, var(--surface-2) 50%, var(--surface) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s infinite;
  border-radius: var(--r);
}
@keyframes shimmer { to { background-position: -200% 0; } }

/* ==========================================================================
   Footer
   ========================================================================== */

.foot {
  border-top: 1px solid var(--line-soft);
  margin-top: 46px;
  padding: 26px 0 10px;
  color: var(--text-mute);
  font-size: 12.5px;
  line-height: 1.7;
}
.foot-links { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 14px; }
.foot-links a:hover { color: var(--text); }
.foot strong { color: var(--text-dim); }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1100px) {
  #app.chat-open { grid-template-columns: var(--nav) 1fr; grid-template-areas: 'nav top' 'nav main'; }
  #app.chat-open .chatbar {
    position: fixed;
    top: var(--top); right: 0; bottom: 0;
    width: var(--chat);
    z-index: 90;
    box-shadow: -16px 0 40px rgba(0,0,0,.5);
  }
  .game-shell { grid-template-columns: 292px 1fr; }
}

@media (max-width: 860px) {
  #app, #app.chat-open, #app.nav-collapsed { grid-template-columns: 1fr; grid-template-areas: 'top' 'main'; }
  .sidenav {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    width: var(--nav);
    transform: translateX(-100%);
    transition: transform .22s cubic-bezier(.2,.9,.3,1);
    z-index: 120;
  }
  #app.nav-open .sidenav { transform: none; box-shadow: 16px 0 44px rgba(0,0,0,.55); }
  #app.nav-collapsed .brand-name, #app.nav-collapsed .nav-label,
  #app.nav-collapsed .nav-item span, #app.nav-collapsed .nav-item .tag { display: revert; }
  #app.nav-collapsed .nav-item { justify-content: flex-start; padding: 9px 10px; }
  #app.nav-collapsed .brand { justify-content: flex-start; padding: 0 18px; }
  .scrim { position: fixed; inset: 0; background: rgba(4,5,10,.6); z-index: 110; }
  .game-shell, .game-shell.reverse { grid-template-columns: 1fr; min-height: 0; }
  .game-shell .game-panel, .game-shell.reverse .game-panel { order: 2; border: none; border-top: 1px solid var(--line-soft); }
  .game-stage { min-height: 380px; order: 1; }

  /* ---- phone control order ---------------------------------------------
     On a phone the board sits at the top and the controls run underneath it.
     Left in source order that puts the bet button below every setting, so it
     is off the bottom of the screen when you are looking at the game. Pull the
     stake and the button up directly beneath the board and let the rest of the
     settings follow.                                                        */
  .game-panel {
    display: flex;
    flex-direction: column;
    padding: 14px;
  }
  .game-panel > * { order: 5; }
  .game-panel > .field:first-of-type { order: 1; margin-bottom: 10px; }
  .game-panel > .bet-action { order: 2; margin-top: 0; }
  /* The controls for a hand already under way - hit and stand, fold and raise,
     start and stop an autobet run - take the same slot as the button that
     began it. Left in source order they sit under every readout, which is the
     far end of the panel from the table they are being played against. */
  .game-panel > .bet-actions { order: 2; margin-top: 0; }
  /* the finished hand reads before the numbers do, and Next hand is the only
     control left, so it takes the same slot the Deal button had */
  .game-panel > .poker-end { order: 2; margin-top: 0; margin-bottom: 10px; }
  .game-panel > .bet-total { order: 3; }

  /* a little more thumb for the main action */
  .bet-action { min-height: 50px; font-size: 15px; }

  /* the game head wraps instead of pushing the badges off the side */
  .game-head { flex-wrap: wrap; row-gap: 8px; margin-bottom: 10px; }
  /* The blurb is the same sentence the lobby tile already showed, and it was
     the one thing forcing the header onto a second line. The badges that say
     something a player cannot read elsewhere - the return and the fairness
     link - stay. */
  .game-head h1 + .pill { display: none; }
  .game-head h1 { font-size: 20px; }
  .game-head .pill { font-size: 10.5px; }
  /* The viewport is `viewport-fit=cover`, so the last thing on the page would
     otherwise sit under the home indicator on a phone that has one. */
  .page { padding: 16px 14px calc(60px + env(safe-area-inset-bottom)); }
  .game-panel { padding-bottom: calc(14px + env(safe-area-inset-bottom)); }
  .hero { padding: 24px 20px; }
  .hero h1 { font-size: 24px; }
  .game-grid { grid-template-columns: repeat(auto-fill, minmax(136px, 1fr)); gap: 11px; }
  .ticker-row { grid-template-columns: 1fr .8fr .9fr; }
  .ticker-row .hide-sm { display: none; }
  .limbo-value { font-size: 54px; }
  .crash-mult { font-size: 44px; }
  .topbar { padding: 0 12px; gap: 8px; }
  .roul-felt { grid-template-columns: 30px repeat(12, 1fr) 34px; gap: 2px; }
  .roul-zeros { gap: 2px; }
  .rn { font-size: 9.5px; }
}

@media (max-width: 520px) {
  .card-face { width: 58px; height: 82px; font-size: 22px; }
  .card-face.sm { width: 44px; height: 62px; font-size: 16px; }
  .keno-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .hero-stats { gap: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ==========================================================================
   Opening splash

   Lives in the shell HTML so it is painted before the module graph loads.
   The end state of every keyframe below is the logo at rest, which is what
   the reduced-motion rule above collapses to.
   ========================================================================== */

.splash {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background: var(--bg);
  transition: opacity .34s ease, transform .34s ease;
}
.splash::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(760px 460px at 50% 34%, rgba(124, 92, 255, .22), transparent 64%),
    radial-gradient(560px 380px at 50% 78%, rgba(34, 211, 238, .1), transparent 62%);
}
.splash.out { opacity: 0; transform: scale(1.05); pointer-events: none; }

.splash-stage {
  position: relative;
  width: 132px;
  height: 132px;
  display: grid;
  place-items: center;
}

/* the ring sweeps once around the mark while it settles */
.splash-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: var(--violet);
  border-right-color: var(--cyan);
  opacity: 0;
  animation: splash-ring 1.5s cubic-bezier(.32, .72, .3, 1) forwards;
}
@keyframes splash-ring {
  0%   { opacity: 0; transform: rotate(-120deg) scale(.72); }
  30%  { opacity: .95; }
  100% { opacity: 0; transform: rotate(300deg) scale(1.28); }
}

.splash-mark {
  position: relative;
  width: 78px;
  height: 78px;
  border-radius: 22px;
  background: var(--grad);
  display: grid;
  place-items: center;
  font-weight: 900;
  font-size: 40px;
  color: #0a0b14;
  box-shadow: 0 14px 44px rgba(124, 92, 255, .5);
  animation: splash-mark .78s cubic-bezier(.2, .9, .28, 1.3) both;
}
@keyframes splash-mark {
  0%   { opacity: 0; transform: scale(.44) rotate(-16deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}

.splash-word {
  position: relative;
  margin-top: 14px;
  font-size: 34px;
  font-weight: 900;
  letter-spacing: 5px;
  padding-left: 5px;
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: splash-rise .6s .3s cubic-bezier(.22, .8, .3, 1) both;
}
.splash-tag {
  position: relative;
  font-size: 12.5px;
  color: var(--text-mute);
  letter-spacing: .4px;
  animation: splash-rise .6s .46s cubic-bezier(.22, .8, .3, 1) both;
}
@keyframes splash-rise {
  0%   { opacity: 0; transform: translateY(12px); }
  100% { opacity: 1; transform: translateY(0); }
}

/* ==========================================================================
   Entry gate

   Opaque and full screen rather than a modal: the app behind a modal is
   exactly what must not be rendered yet.
   ========================================================================== */

.gate {
  position: fixed;
  inset: 0;
  z-index: 150;
  overflow-y: auto;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 18px;
  transition: opacity .26s ease;
}
.gate::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(900px 520px at 50% -8%, rgba(124, 92, 255, .18), transparent 62%),
    radial-gradient(700px 460px at 50% 104%, rgba(34, 211, 238, .08), transparent 60%);
}
.gate.out { opacity: 0; pointer-events: none; }

.gate-panel {
  position: relative;
  width: 100%;
  max-width: 428px;
  margin: auto;
  animation: splash-rise .5s cubic-bezier(.22, .8, .3, 1) both;
}

.gate-brand { text-align: center; margin-bottom: 22px; }
.brand-mark.lg {
  width: 56px; height: 56px;
  margin: 0 auto 14px;
  border-radius: 17px;
  font-size: 28px;
}
.gate-title { font-size: 28px; font-weight: 900; letter-spacing: 3px; padding-left: 3px; }
.gate-title span {
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.gate-tag { font-size: 12.5px; color: var(--text-mute); margin-top: 4px; }

.gate-card { padding: 24px 22px; }
.gate-card h2 { margin: 0 0 5px; font-size: 20px; }
.gate-card .lede { margin: 0 0 18px; }

.gate-foot {
  text-align: center;
  font-size: 11.5px;
  line-height: 1.65;
  color: var(--text-mute);
  margin: 18px 4px 0;
}

@media (max-width: 520px) {
  .splash-word { font-size: 28px; }
  .splash-mark { width: 68px; height: 68px; font-size: 34px; border-radius: 19px; }
  .splash-stage { width: 118px; height: 118px; }
  .gate { padding: 22px 14px; }
  .gate-card { padding: 20px 17px; }
}

/* ---------------------------------------------------------------------------
   Full-bleed lobby tiles
   The artwork is a scene that fills the whole card rather than an icon floating
   in the middle of it, so the grid reads as a shelf of games. The card's own
   colour washes are dialled back here because each piece carries its own.
   --------------------------------------------------------------------------- */

.game-card.full .game-art {
  position: absolute;
  inset: 0;
  padding: 0;
  display: block;
  overflow: hidden;
}
.game-card.full .game-art::before { content: none; }

.game-card.full .game-art svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  filter: none;
  transform: scale(1.02);
  transition: transform .45s cubic-bezier(.2,.8,.3,1);
}
.game-card.full:hover .game-art svg { transform: scale(1.09); }

/* the accent washes are already inside the artwork; keep only a whisper of
   them so hover still tints the card */
.game-card.full::before { opacity: 0; }
.game-card.full:hover::before { opacity: .22; }

/* a deeper, taller veil so the name sits on solid ground at any art brightness */
.game-card.full::after {
  background: linear-gradient(to top,
    rgba(6, 8, 14, .96) 0%,
    rgba(6, 8, 14, .88) 16%,
    rgba(6, 8, 14, .42) 40%,
    rgba(6, 8, 14, .06) 62%,
    transparent 78%);
}

.game-card.full .gc-name {
  font-size: 17px;
  font-weight: 850;
  letter-spacing: -.3px;
}
.game-card.full .gc-blurb {
  font-size: 11.5px;
  color: rgba(233, 236, 245, .72);
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.32;
  max-height: 2.7em;
  margin-top: 3px;
}

@media (max-width: 640px) {
  .game-card.full .gc-name { font-size: 15px; }
  .game-card.full .gc-blurb { display: none; }
}

/* ---------------------------------------------------------------------------
   Top bar overflow on phones
   -------------------------------------------------------------------------
   #app is a grid. A grid item's min-width defaults to `auto`, which means the
   track cannot shrink below the intrinsic width of its content. The top bar's
   row of controls measured 514px, so on a 390px phone the single column
   resolved to 514px and dragged `main` — and therefore every page — out with
   it. The whole document scrolled sideways by 124px.

   Two things are needed. The guard below lets the track shrink, which is the
   actual bug. Then the bar's own contents have to fit in the space that is
   left, which is what the media query does.
   --------------------------------------------------------------------------- */

.topbar, .main { min-width: 0; }
.topbar .brand { min-width: 0; }

@media (max-width: 720px) {
  /* The wordmark is already at the top of the side nav; the Z mark carries it
     here. The selector needs the #app to outrank the `display: revert` that the
     collapsed-nav rule above applies to every .brand-name on the page. */
  #app .topbar .brand-name { display: none; }

  /* Signing out lives at the foot of the side nav, under the name of whoever
     is signed in, so the bar does not need it here as well. That was already
     what this rule claimed, but until the row existed it left a phone with no
     way to leave an account. */
  .topbar .icon-btn.signout { display: none; }

  /* The pill holds nothing but the balance now, so the balance is never cut.
     A figure a player cannot read in full is worse than a bar that is a few
     pixels tighter - and dropping the gold button gave back more room than
     the longest balance needs. */
  .wallet-pill { flex: none; }
  .wallet-pill .amount { padding: 0 11px; gap: 6px; font-size: 13px; white-space: nowrap; }

  /* everything else holds its size so the pill is what gives way */
  .topbar .icon-btn, .topbar .brand-mark { flex: none; }
}

@media (max-width: 430px) {
  /* below this the word does not earn its width; the + still reads as "add coins" */

  /* The balance itself now links to the wallet, so the separate wallet icon is
     saying the same thing twice. Dropping it buys back 44px, which is what
     keeps the number readable instead of ellipsised down to "5…". */
  .topbar .icon-btn.wallet-btn { display: none; }
}

/* The bar's own slots still shrink before anything overflows the page; the
   pill inside is what now holds its size, because the whole point of it is a
   number read at a glance. */
#walletSlot, #authSlot { min-width: 0; }

/* The toast slides in and out sideways by 24px. Pinned 20px from the right,
   that overshoot lands past the edge of a small phone and widens the page for
   the length of the animation. Give it both edges to sit between and let it
   arrive vertically instead. */
@media (max-width: 480px) {
  .toast-wrap { left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom)); align-items: stretch; }
  .toast { max-width: 100%; }
  @keyframes toastin { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
  @keyframes toastout { to { opacity: 0; transform: translateY(16px); } }
}

/* the balance is a link now — it should keep the bar's text colour, not the
   default link colour */
.wallet-pill .amount { color: inherit; }
.wallet-pill .amount:hover { background: var(--surface-2); }

/* On the narrowest phones still in use (320px) the balance was landing one or
   two characters short. Tightening the pill's own padding and type buys back
   the dozen pixels it needed, so the number reads in full rather than as "5,00…". */
@media (max-width: 365px) {
  .wallet-pill .amount { padding: 0 9px; gap: 5px; font-size: 12.5px; }
  .topbar { gap: 6px; padding: 0 10px; }
}

/* `.buy` is a grid, so splitting its label into "+" and "Coins" put each span
   on its own row. Lay them out in a single line. */

/* ---------------------------------------------------------------------------
   Three games to a row on a phone
   -------------------------------------------------------------------------
   The `minmax(136px, 1fr)` track above resolves to two columns on a 390px
   phone, which makes each tile huge and pushes the catalogue a long way down
   the page. Three across keeps more of the shelf on screen at once, which is
   the whole point of a lobby. The tiles get narrow, so the caption tightens
   with them and the blurb is already hidden at this size.
   --------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .game-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 9px; }
  .game-card { padding: 10px; }
  .game-card.full .gc-name { font-size: 12.5px; letter-spacing: -.15px; }
  .game-card .gc-live { top: 7px; left: 7px; padding: 2px 6px; font-size: 8.5px; gap: 4px; }
  /* the veil can be shorter on a small tile — there is only one line to carry */
  .game-card.full::after {
    background: linear-gradient(to top,
      rgba(6, 8, 14, .96) 0%,
      rgba(6, 8, 14, .82) 20%,
      rgba(6, 8, 14, .30) 44%,
      transparent 66%);
  }
}

/* ---------------------------------------------------------------------------
   Hero showpiece
   -------------------------------------------------------------------------
   A roulette wheel sits in the right of the hero. It has to read as part of the
   panel rather than as a picture pasted onto it, so its left edge is dissolved
   with a mask instead of being given a hard boundary, and the headline column
   is capped so the two never collide. It is decoration: no pointer events, and
   it is hidden from assistive tech at the markup level.
   --------------------------------------------------------------------------- */
.hero-art {
  position: absolute;
  top: 50%;
  right: -34px;
  width: 476px;
  height: 336px;
  margin-top: -168px;
  pointer-events: none;
  opacity: .95;
  -webkit-mask-image: linear-gradient(to left, #000 46%, rgba(0,0,0,.55) 72%, transparent 100%);
          mask-image: linear-gradient(to left, #000 46%, rgba(0,0,0,.55) 72%, transparent 100%);
}
.hero-art svg { width: 100%; height: 100%; display: block; }

/* the wheel's own glow replaces the flat violet blob that used to sit here */
.hero:has(.hero-art)::after { opacity: .35; }

.hero { min-height: 348px; }
.hero h1 { max-width: 560px; }
.hero p { max-width: 500px; }

@media (max-width: 1100px) {
  .hero-art { width: 384px; height: 271px; margin-top: -136px; right: -60px; opacity: .85; }
  .hero h1, .hero p { max-width: 420px; }
}

/* On a phone there is no column to spare beside the text, so the wheel stops
   competing for space and becomes a backdrop in the top corner instead. */
@media (max-width: 860px) {
  .hero-art {
    top: -64px;
    right: -80px;
    width: 262px;
    height: 185px;
    margin-top: 0;
    opacity: .34;
    -webkit-mask-image: radial-gradient(ellipse at 56% 46%, #000 24%, transparent 72%);
            mask-image: radial-gradient(ellipse at 56% 46%, #000 24%, transparent 72%);
  }
  .hero { min-height: 0; }
  .hero h1, .hero p { max-width: none; }
}

/* ---------------------------------------------------------------------------
   Live occupancy under each lobby tile
   -------------------------------------------------------------------------
   The count comes from the server's socket tally, so it is the real number of
   people in that room. It sits below the tile rather than on it, where it can
   never fight the artwork, and the row holds its height at all times so the
   grid does not jump as counts appear and disappear.
   --------------------------------------------------------------------------- */
.game-cell { display: flex; flex-direction: column; gap: 9px; min-width: 0; }

.gc-players {
  display: flex;
  align-items: center;
  gap: 7px;
  padding-left: 2px;
  font-size: 13px;
  color: var(--text-mute);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  min-height: 15px;
}
.gc-players b { color: var(--text); font-weight: 700; }
.gc-players i.dot-live { flex: none; }

/* Nobody in the room: the dot stops pulsing and the row recedes, but it still
   occupies its line so nothing below it moves.

   The class is `gc-empty`, not `empty`. `.empty` is the site-wide empty-state
   block - the one that centres "No purchases yet" inside a card - and it
   carries `padding: 40px 20px`. Putting it on this row gave every tile with
   nobody in it eighty pixels of padding it was never meant to have: the label
   floated in the middle of a band of nothing, the grid row grew to match, and
   the gap vanished again the moment somebody joined that game. Component
   state belongs to the component. */
.gc-players.gc-empty { color: var(--text-mute); opacity: .5; }
.gc-players.gc-empty i.dot-live { background: var(--text-mute); box-shadow: none; animation: none; }

@media (max-width: 640px) {
  .game-cell { gap: 6px; }
  /* The word used to be hidden outright here, which left a dot and a bare
     number under every tile and nothing to say what was being counted. It
     fits at this width - it only needs to be smaller. */
  .gc-players { font-size: 11px; gap: 4px; min-height: 13px; }
  .gc-players span { font-size: 10px; }
}

@media (max-width: 360px) {
  .gc-players { font-size: 10px; gap: 3px; }
  .gc-players span { font-size: 9px; }
}

/* the occupancy row adds a line under the grid, so the next section needs a
   little more air than it did when the grid ended at the tiles */
.page section + section { margin-top: 30px; }

/* ---------------------------------------------------------------------------
   Side navigation legibility
   -------------------------------------------------------------------------
   The item labels were `--text-dim` at weight 550, and the group headings and
   icons were `--text-mute`. Measured against the nav's `--bg-2` background,
   the headings and icons came out at 4.07:1 — under the 4.5:1 that WCAG AA
   asks of text this size, and visibly washed out on a phone in daylight. The
   values below lift every tier and keep the hierarchy intact: resting items
   are bright, the active item is brighter still, and the headings clear AA
   with room to spare.
   --------------------------------------------------------------------------- */
.sidenav .nav-item {
  color: #cfd4ee;          /* 12.8:1 — was 7.5:1 */
  font-weight: 600;        /* was 550: too thin to hold at 13.5px */
}
.sidenav .nav-ico {
  color: #aeb5d8;          /* 9.3:1 — was 4.1:1 */
}
.sidenav .nav-item:hover,
.sidenav .nav-item.active {
  color: #ffffff;          /* the active row stays clearly ahead of the rest */
}
.sidenav .nav-item.active .nav-ico { color: #a48bff; }
.sidenav .nav-label {
  color: #949cc6;          /* 7.0:1 — was 4.1:1 */
  font-weight: 750;
}
.sidenav .nav-item .tag {
  background: rgba(124, 92, 255, .26);
  color: #cbbcff;          /* 10.9:1 */
}

/* ---------------------------------------------------------------------------
   Game screens — the fixes that apply to all fourteen
   --------------------------------------------------------------------------- */

/* 1. Touch targets.
   The stake stepper (½ / 2× / Max) measured 26x23 on a phone. It appears on
   every game and is the most-tapped control in the app; Apple asks for 44x44
   and Google for 48x48. Across the fourteen mobile screens there were 256
   in-game controls under 44px tall. These rules raise every tier at once. */
@media (max-width: 1024px), (pointer: coarse) {
  .input-group .adorn { padding: 0 6px; gap: 6px; }
  .input-group .adorn button {
    min-width: 46px;
    min-height: 44px;
    padding: 0 10px;
    font-size: 13.5px;
    border-radius: 9px;
  }
  .seg { padding: 4px; gap: 4px; }
  .seg button { min-height: 44px; font-size: 13.5px; }
  .field input,
  .field select { min-height: 48px; font-size: 15px; }   /* 15px also stops iOS zooming on focus */
  .poker-quick button { min-height: 44px; min-width: 46px; }
  .switch .track { transform: scale(1.15); transform-origin: left center; }
}

/* 2. The rules card collapses on a phone.
   The toggle only exists below 860px; above it the original heading shows and
   the card is always open. */
.rules-toggle { display: none; }
.rules-section .card { display: block; }

@media (max-width: 860px) {
  .rules-head { display: none; }
  .rules-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    min-height: 52px;
    padding: 0 16px;
    border-radius: var(--r);
    background: var(--surface);
    border: 1px solid var(--line-soft);
    color: var(--text);
    font-size: 15px;
    font-weight: 700;
  }
  .rules-toggle .chev {
    width: 10px; height: 10px;
    border-right: 2px solid var(--text-dim);
    border-bottom: 2px solid var(--text-dim);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform .2s;
  }
  .rules-section.open .rules-toggle .chev { transform: rotate(-135deg) translate(-2px, -2px); }
  .rules-section .card { display: none; margin-top: 10px; }
  .rules-section.open .card { display: block; }
}

/* 3. The primary action must be reachable without scrolling.
   Measured on a 390x844 phone, twelve of the fourteen games put the bet button
   in the first screen. Two did not, and they are the two where it matters most.

   Rocket: the round history is twenty-four multiplier pills wrapping to four
   rows, 111px above the board. Rocket's betting window is a few seconds long,
   so a player who has to scroll to find the button misses the round outright.

   Keno: the paytable is eleven chips on two rows, and the 40-number board runs
   five columns of square cells - 584px of grid. Together they pushed the stake
   field and the play button to 1006px, off a 844px screen entirely. The player
   sees a board they can mark and no visible way to bet.

   Neither strip loses any information here: both scroll sideways instead of
   wrapping downward, and the Keno cells go from square to slightly wide, which
   keeps them well above the 44px touch minimum while returning 130px. */
@media (max-width: 860px) {
  .crash-hist,
  .keno-pays {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    justify-content: flex-start;
  }
  .crash-hist::-webkit-scrollbar,
  .keno-pays::-webkit-scrollbar { display: none; }
  .crash-hist > *,
  .keno-pays > * { flex: none; }
  .crash-hist { margin-bottom: 10px; }
  .keno-pays { margin-top: 12px; }

  .keno-cell { aspect-ratio: 1.34; font-size: 15px; }
}

/* The last few controls that were still under the touch minimum: the
   Manual/Auto tab pair (.tabs-line), the tower floor tiles, and the small
   ghost buttons some games use for a secondary action. */
@media (max-width: 1024px), (pointer: coarse) {
  .tabs-line button { min-height: 46px; font-size: 14px; }
  .tower-cell { min-height: 46px; }
  .game-shell .btn.sm { min-height: 44px; padding: 0 14px; font-size: 13.5px; }
  /* The Keno board runs eight columns on a tablet, which makes the cells wide
     and short, so a floor keeps them tappable whatever the column count. It is
     only applied where there is room for it: a min-height on a box that also
     has an aspect-ratio becomes a minimum WIDTH during intrinsic sizing, and
     on a narrow phone that is exactly what was pushing the page sideways. */
  @media (min-width: 641px) {
    .keno-cell { min-height: 46px; }
  }
  .rn { min-height: 46px; }
}

/* ---------------------------------------------------------------------------
   Roulette on a phone
   -------------------------------------------------------------------------
   The felt already scrolled sideways rather than being sliced, but its floor
   was 460px: twelve number columns plus the zero and the 2:1 column left each
   number at 30x29, and the split and corner spots layered over the grid lines
   at 14x12. Eighty-two of those. A finger cannot hit a 14px target, so the only
   bets a player could reliably place on a phone were the outside ones.

   The fix is not to redesign the felt - the layout is correct and familiar -
   but to stop compressing it. The floor goes to 684px, which is what twelve
   44px columns actually need, and the board pans instead. Everything else
   follows from the cells being the right size.
   --------------------------------------------------------------------------- */
@media (max-width: 860px) {
  .roul-felt, .roul-outside { min-width: 684px; }
  /* Everything else in the stage is narrower than the screen, so centring it
     inside a 712px scroll canvas would park it half a screen to the right.
     The result marker and history sit at the left and stay put while the board
     pans, so the last number drawn is always on screen. */
  /* The wheel is a desktop ornament, and on a phone it was an expensive one:
     132px at the very top of the page, which pushed the felt a third of the way
     down the screen and the Spin button off the bottom of it. Here the readout
     carries the result on its own - one 44px row with the last number and the
     history beside it - and the board starts directly underneath, so the whole
     table is on the first screenful. */
  .roul-wheel { display: none; }
  .roul-wheelbox { gap: 10px; align-items: center; justify-content: flex-start; margin-bottom: 8px; }
  .roul-readout { flex-direction: row; align-items: center; gap: 10px; flex: 1; min-width: 0; }
  .roul-readout .crash-hist { margin-bottom: 0; }
  .roul-result { width: 38px; height: 38px; font-size: 15px; border-width: 2px; }
  .roul-felt { grid-template-columns: 46px repeat(12, 1fr) 48px; gap: 4px; }
  .roul-zeros { gap: 4px; }

  /* square-ish cells that clear the 44px touch minimum in both directions */
  .rn { aspect-ratio: auto; min-height: 46px; font-size: 14px; }
  .rn.out { font-size: 12.5px; }
  .roul-outside .rn { min-height: 48px; }


}

/* ---------------------------------------------------------------------------
   Tower Climb — tile icons
   -------------------------------------------------------------------------
   The star and skull glyphs are `<svg viewBox="0 0 24 24">` with no width or
   height. An SVG with no intrinsic size and no CSS size falls back to the
   replaced-element default, which is far larger than a 40px tile - which is
   why the stars were spilling across the whole board and over the tile below.
   Sizing them explicitly is the fix; everything else here is the reveal.
   --------------------------------------------------------------------------- */
.tower-cell svg {
  width: 22px;
  height: 22px;
  display: block;
  filter: drop-shadow(0 2px 5px rgba(0, 0, 0, .45));
}
@media (max-width: 1024px), (pointer: coarse) {
  .tower-cell svg { width: 26px; height: 26px; }
}

/* The reveal. A safe tile springs in and settles; a bomb lands hard and
   shakes the tile it hit. The `reveal` class is added only the first time a
   tile is opened, so replaying the board does not replay the animation. */
@keyframes towerPop {
  0%   { opacity: 0; transform: scale(.2) rotate(-24deg); }
  55%  { opacity: 1; transform: scale(1.28) rotate(6deg); }
  78%  { transform: scale(.94) rotate(-2deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}
@keyframes towerHit {
  0%   { opacity: 0; transform: scale(1.9) translateY(-14px); }
  40%  { opacity: 1; transform: scale(1) translateY(0); }
  55%  { transform: translateX(-4px); }
  70%  { transform: translateX(4px); }
  85%  { transform: translateX(-2px); }
  100% { transform: translateX(0); }
}
/* a ring that expands out of the tile the player chose and fades */
@keyframes towerRing {
  from { opacity: .85; transform: scale(.55); }
  to   { opacity: 0;   transform: scale(1.5); }
}

.tower-cell.safe.reveal svg { animation: towerPop .46s cubic-bezier(.18,1.5,.4,1) both; }
.tower-cell.dead.reveal svg { animation: towerHit .52s cubic-bezier(.3,.8,.3,1) both; }

.tower-cell { position: relative; overflow: visible; }
.tower-cell.reveal.picked::after {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: 11px;
  border: 2px solid currentColor;
  color: var(--win);
  pointer-events: none;
  animation: towerRing .6s ease-out both;
}
.tower-cell.dead.reveal.picked::after { color: var(--lose); }

/* the floor the player is standing on gets a slow breath, so the eye knows
   where the next tap goes without anything having to say so */
@keyframes towerBreath {
  0%, 100% { box-shadow: -3px 0 0 var(--violet), 0 0 0 rgba(124, 92, 255, 0); }
  50%      { box-shadow: -3px 0 0 var(--violet), 0 0 16px rgba(124, 92, 255, .28); }
}
.tower-row.active { animation: towerBreath 2.4s ease-in-out infinite; }

/* ---------------------------------------------------------------------------
   Very narrow phones (320px class)
   -------------------------------------------------------------------------
   At this width the game header wraps its two pills onto a second line and the
   stage still claims its 380px floor, which together pushed the bet button off
   the bottom on several games. Compacting the header and lowering the stage
   floor brings it back without touching anything above 400px.
   --------------------------------------------------------------------------- */
@media (max-width: 400px) {
  .game-stage { min-height: 300px; padding: 16px; }
  .game-head { row-gap: 6px; }
  .game-head h1 { font-size: 19px; }
  .game-head .pill { font-size: 10px; padding: 3px 8px; }
  .page { padding-top: 12px; }
}

/* ---------------------------------------------------------------------------
   The last two boards that pushed the bet button off a 360px screen
   -------------------------------------------------------------------------
   Tower Climb stacks nine floors and Keno forty numbers, so they are the two
   tallest boards in the app. Both were within about thirty pixels of fitting;
   a tighter row gap on the tower and one more Keno column close it without
   taking either below the touch minimum.
   --------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .tower { gap: 5px; }
  .tower-row, .tower-row .cells { gap: 5px; }
  /* 44 is the touch minimum, not a target to exceed; the two pixels back on
     each of nine floors are what put the bet button on screen */
  .tower-cell { min-height: 44px; }
  .keno-grid { gap: 5px; }
}

/* Six columns instead of five turns Keno's eight rows into seven. Below 400px
   there is not enough width for six 44px cells, so those screens keep five and
   scroll - which is the honest trade at that size. */
@media (min-width: 350px) and (max-width: 640px) {
  .keno-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* ---------------------------------------------------------------------------
   Fox Road
   -------------------------------------------------------------------------
   A road seen from above, running left to right, one lane per rung of the
   ladder. The lane count is set by the difficulty - nineteen on easy, ten on
   expert - so the strip scrolls rather than squeezing: a lane keeps the same
   width at every difficulty and on every screen, and the board follows the fox
   instead of shrinking to fit the whole road at once.
   --------------------------------------------------------------------------- */

.fox-board {
  --lane: 78px;
  --road-h: 268px;
  width: 100%;
  /* the fade below sits over the road, so this is what it is positioned against */
  position: relative;
}

/* A road longer than the board is the normal case - nineteen lanes never fit -
   so the right edge fades out to say the road carries on rather than ending in
   a hard crop. Pointer events pass through it to the scroll underneath. */
.fox-board::after {
  content: '';
  position: absolute;
  top: 1px;
  bottom: 1px;
  right: 1px;
  width: 56px;
  border-radius: 0 var(--r) var(--r) 0;
  background: linear-gradient(90deg, transparent, var(--surface) 92%);
  pointer-events: none;
  z-index: 4;
}

.fox-road {
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  border-radius: var(--r);
  background:
    linear-gradient(180deg, rgba(255, 176, 105, .07), transparent 30%),
    var(--bg-2);
  border: 1px solid var(--line-soft);
  scrollbar-width: thin;
  scrollbar-color: var(--surface-3) transparent;
  /* the player can look down the road, and the board pulls itself back */
  scroll-padding-inline: 40px;
  -webkit-overflow-scrolling: touch;
}
.fox-road::-webkit-scrollbar { height: 7px; }
.fox-road::-webkit-scrollbar-track { background: transparent; }
.fox-road::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 99px; }

.fox-track {
  position: relative;
  display: flex;
  align-items: stretch;
  min-height: var(--road-h);
  padding: 16px 0;
  width: max-content;
}

/* the verge at each end: grass the fox starts on, den it is running for */
.fox-verge {
  flex: 0 0 84px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 16px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .10em;
  text-transform: uppercase;
  color: var(--text-mute);
  background: linear-gradient(180deg, rgba(61, 220, 151, .10), rgba(61, 220, 151, .03));
}
.fox-verge.start { border-radius: var(--r) 0 0 var(--r); }
.fox-verge.end {
  border-radius: 0 var(--r) var(--r) 0;
  background: linear-gradient(180deg, rgba(255, 176, 32, .16), rgba(255, 176, 32, .04));
  color: var(--gold);
}

/* ---- a lane -------------------------------------------------------------- */

.fox-lane {
  position: relative;
  flex: 0 0 var(--lane);
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 0 4px;
  transition: background .18s;
}

.fox-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 7px 4px 8px;
  border-radius: var(--r-sm);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  transition: border-color .18s, background .18s, transform .18s, box-shadow .18s;
}
.fox-mult {
  font-size: 13px;
  font-weight: 800;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.fox-odds {
  font-size: 9.5px;
  font-style: normal;
  font-weight: 600;
  color: var(--text-mute);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* the asphalt itself */
.fox-surface {
  position: relative;
  flex: 1 1 auto;
  min-height: 168px;
  border-radius: var(--r-sm);
  background: #241608;
  box-shadow: inset 0 1px 0 rgba(255, 207, 154, .10);
  overflow: hidden;
  transition: background .2s, box-shadow .2s;
}
/* the painted line between this lane and the next */
.fox-dash {
  position: absolute;
  top: 8%;
  bottom: 8%;
  right: -1px;
  width: 2px;
  background: repeating-linear-gradient(
    180deg, rgba(255, 207, 154, .34) 0 10px, transparent 10px 22px);
}
.fox-lane:last-of-type .fox-dash { display: none; }

.fox-index {
  text-align: center;
  font-size: 9.5px;
  font-style: normal;
  font-weight: 700;
  color: var(--text-mute);
  opacity: .5;
  font-variant-numeric: tabular-nums;
}

/* what is waiting in the lane - hidden until the round is over */
.fox-hazard {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  opacity: 0;
  transform: translateY(-14px) scale(.8);
  transition: opacity .22s, transform .22s;
  pointer-events: none;
}
.fox-hazard svg { width: 42px; height: 42px; }

/* ---- lane states --------------------------------------------------------- */

/* the lane the fox is about to take */
.fox-lane.next .fox-chip {
  border-color: var(--accent, #ff8c42);
  background: color-mix(in srgb, #ff8c42 16%, var(--surface));
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(255, 140, 66, .22);
}
.fox-lane.next .fox-mult { color: var(--text); }
.fox-lane.next .fox-surface {
  background: #33200c;
  box-shadow: inset 0 0 0 1px rgba(255, 140, 66, .45);
}

/* lanes already behind the fox */
.fox-lane.cleared .fox-chip {
  border-color: color-mix(in srgb, var(--win) 45%, transparent);
  background: color-mix(in srgb, var(--win) 13%, var(--surface));
}
.fox-lane.cleared .fox-mult { color: var(--win); }
.fox-lane.cleared .fox-surface { background: #14301f; }

/* the lane that ended the run */
.fox-lane.hit .fox-chip {
  border-color: var(--lose);
  background: color-mix(in srgb, var(--lose) 18%, var(--surface));
}
.fox-lane.hit .fox-mult { color: var(--lose); }
.fox-lane.hit .fox-surface { background: #3a0f1b; box-shadow: inset 0 0 0 1px rgba(255, 93, 122, .5); }

/* The car was already coming; this is it arriving. It drops in from the top of
   the lane after the fox has committed, so the round reads as being caught by
   the traffic rather than as a square turning red. */
.fox-lane.hit .fox-hazard {
  opacity: 1;
  transform: none;
  animation: fox-car-in .34s cubic-bezier(.3, .9, .4, 1.3);
}
@keyframes fox-car-in {
  0%   { opacity: 0; transform: translateY(-150%) scale(.8); }
  62%  { opacity: 1; transform: translateY(7%) scale(1.09); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

/* traffic revealed once the round is over, in lanes the fox never reached */
.fox-lane.car .fox-hazard { opacity: .5; transform: none; }
.fox-lane.spent { opacity: .5; }

/* a lane whose payout would run into the house ceiling */
.fox-lane.capped .fox-mult { color: var(--gold); }
.fox-lane.capped .fox-chip { border-style: dashed; }

/* ---- the fox ------------------------------------------------------------- */

.fox-runner {
  position: absolute;
  left: 0;
  bottom: 30px;
  width: 62px;
  height: 62px;
  margin-left: -31px;
  z-index: 3;
  pointer-events: none;
  transition: transform var(--hop, 340ms) cubic-bezier(.34, 1.2, .5, 1);
  filter: drop-shadow(0 6px 12px rgba(0, 0, 0, .55));
}
.fox-body { width: 100%; height: 100%; transform-origin: 50% 88%; }
.fox-runner svg { width: 100%; height: 100%; }

/* ---- what the fox does --------------------------------------------------- */

/* The hop. Crossing a lane was a slide along a straight line, which is the one
   thing a jump is not: it needs to leave the ground, lean into the crossing and
   land heavily. Timed off the same --hop the move is, so the arc and the
   travel always finish together. */
.fox-body.hopping { animation: fox-hop var(--hop, 340ms) cubic-bezier(.3, .7, .4, 1); }
@keyframes fox-hop {
  0%   { transform: translateY(0)    scale(1.08, .9); }
  20%  { transform: translateY(-30%) scale(.93, 1.1) rotate(-8deg); }
  55%  { transform: translateY(-44%) scale(1, 1)     rotate(-4deg); }
  84%  { transform: translateY(2%)   scale(1.12, .88); }
  100% { transform: translateY(0)    scale(1, 1); }
}

/* caught by a car: knocked off its feet, and it stays down */
.fox-runner.down .fox-body { animation: fox-tumble .62s cubic-bezier(.3, .8, .4, 1) forwards; }
@keyframes fox-tumble {
  0%   { transform: translateY(0) rotate(0); }
  28%  { transform: translateY(-34%) rotate(44deg); }
  100% { transform: translateY(16%) rotate(98deg); filter: saturate(.55) brightness(.8); }
}

/* home with the coins */
.fox-board.home .fox-runner { filter: drop-shadow(0 0 18px rgba(61, 220, 151, .6)); }
.fox-board.home .fox-body { animation: fox-cheer .9s ease-in-out; }
@keyframes fox-cheer {
  0%, 100% { transform: translateY(0) scale(1, 1); }
  22%      { transform: translateY(-36%) scale(.94, 1.09); }
  48%      { transform: translateY(0) scale(1.1, .9); }
  72%      { transform: translateY(-18%) scale(.97, 1.04); }
}

/* ---- the road, while it is being looked at -------------------------------- */

/* The lane the fox is standing in front of is the one that matters, so it is
   the one that moves: the painted line runs and a headlight passes over the
   asphalt. Identical in every lane it is ever applied to, and only one lane is
   ever next, so nothing here can hint at where the traffic actually is. */
.fox-lane.next .fox-dash { animation: fox-dash-run 1.1s linear infinite; }
@keyframes fox-dash-run {
  from { background-position-y: 0; }
  to   { background-position-y: 22px; }
}
.fox-lane.next .fox-surface::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  height: 40%;
  background: linear-gradient(180deg, transparent, rgba(255, 207, 154, .14), transparent);
  animation: fox-sweep 1.9s linear infinite;
  pointer-events: none;
}
@keyframes fox-sweep {
  from { transform: translateY(-110%); }
  to   { transform: translateY(250%); }
}

/* the whole board flinches when the fox meets a car */
@keyframes fox-smack {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-7px); }
  35% { transform: translateX(6px); }
  55% { transform: translateX(-4px); }
  78% { transform: translateX(3px); }
}
.fox-board.smack { animation: fox-smack .6s cubic-bezier(.36, .07, .19, .97); }

/* the difficulty picker is settled once the traffic has been dealt */
.seg.locked { opacity: .55; pointer-events: none; }

@media (max-width: 860px) {
  .fox-board { --lane: 64px; --road-h: 210px; }
  .fox-verge { flex-basis: 64px; font-size: 10px; }
  .fox-runner { width: 50px; height: 50px; margin-left: -25px; bottom: 26px; }
  .fox-hazard svg { width: 34px; height: 34px; }
  .fox-surface { min-height: 124px; }
}

@media (max-width: 480px) {
  .fox-board { --lane: 58px; --road-h: 190px; }
  .fox-verge { flex-basis: 52px; }
  .fox-mult { font-size: 12px; }
  .fox-odds { font-size: 9px; }
  .fox-surface { min-height: 108px; }
}

@media (prefers-reduced-motion: reduce) {
  .fox-runner { transition-duration: 1ms; }
  .fox-board.smack,
  .fox-body.hopping,
  .fox-board.home .fox-body,
  .fox-lane.hit .fox-hazard,
  .fox-lane.next .fox-dash,
  .fox-lane.next .fox-surface::after { animation: none; }
  .fox-runner.down .fox-body { animation: none; transform: rotate(98deg); }
}

/* ---------------------------------------------------------------------------
   Back Players
   -------------------------------------------------------------------------
   The operator's screens. Deliberately plainer than the games: this is a place
   to read a table and press a button that changes somebody's balance, so the
   design gets out of the way and the destructive controls are the only things
   wearing a colour.
   --------------------------------------------------------------------------- */

.admin-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line-soft);
}
.admin-toolbar select { width: auto; min-width: 150px; }

/* The three fields that make a player: side by side where there is room, and
   stacked on a phone, which is where an operator most often is when somebody
   asks them for an account. */
.admin-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 0 14px;
  margin-bottom: 4px;
}
.admin-grid .field { margin-bottom: 12px; }
.admin-toolbar .count { margin-left: auto; white-space: nowrap; }

.admin-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 240px;
  min-width: 0;
}
.admin-search i {
  position: absolute;
  left: 12px;
  display: flex;
  color: var(--text-mute);
  pointer-events: none;
}
.admin-search input { padding-left: 36px; width: 100%; }
/* the browser's own clear button sits badly on a dark field */
.admin-search input::-webkit-search-cancel-button { filter: invert(.6); }

/* the two columns on a player page: facts on the left, controls on the right */
.admin-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  margin-top: 18px;
  align-items: start;
}

.kv-list { display: flex; flex-direction: column; }
.kv {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 13px;
}
.kv:last-child { border-bottom: none; }
.kv b { text-align: right; word-break: break-word; }
.kv b.warn { color: var(--warn); }

/* an input and the button that commits it, side by side */
.admin-set { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.admin-set .btn { flex: 0 0 auto; }

/* the one button on the site that ends somebody's access */
.btn.danger {
  background: color-mix(in srgb, var(--lose) 16%, var(--surface-2));
  border-color: color-mix(in srgb, var(--lose) 55%, transparent);
  color: var(--lose);
}
.btn.danger:hover:not(:disabled) {
  background: color-mix(in srgb, var(--lose) 26%, var(--surface-2));
  border-color: var(--lose);
}

/* how much of a player's play a single game accounts for */
.share-bar {
  display: block;
  width: 56px;
  height: 5px;
  border-radius: 99px;
  background: var(--surface-3);
  overflow: hidden;
  margin-bottom: 3px;
}
.share-bar i { display: block; height: 100%; background: var(--grad); border-radius: 99px; }

.pill.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.pill.lose { color: var(--lose); border-color: color-mix(in srgb, var(--lose) 45%, transparent); }
.stat .v.warn { color: var(--warn); }
.stat .v.neg { color: var(--lose); }
/* Coins the operator put in by hand: gold, the colour coins are everywhere
   else on the site, so it reads as a top-up rather than as won or lost. */
.stat .v.gold { color: var(--gold); }
.table td.num.gold, .coin-gold { color: var(--gold); }

/* ---- the money screen ------------------------------------------------------
   Its figures run to hundreds of millions with two decimals, which the shared
   158px tiles cannot hold - they spilled out of the tile and were clipped by
   the next one. Here the grid is a fixed four across (two, then one, as the
   card narrows) and the figure sizes itself to the width of its own tile, so it
   always fits on one line. Scoped to this page; every other stat grid is as it
   was. */
.money-page .card { container: money / inline-size; }
.money-range { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 16px; }
.money-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
@container money (max-width: 760px) { .money-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container money (max-width: 380px) {
  .money-stats { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  /* one column has nothing to line up with, so the tiles can be short */
  .money-stats .stat { padding: 11px 14px; }
  .money-stats .stat .k { min-height: 0; }
  .money-stats .stat .v { margin-top: 4px; }
}
/* Six ranges do not fit across a phone. Rather than run off the card they
   stand in two full rows of three. */
.money-range .seg { min-width: 0; max-width: 100%; }
@container money (max-width: 620px) {
  .money-range .seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); width: 100%; }
  .money-range .seg button { min-width: 0; padding-left: 4px; padding-right: 4px; }
}
.money-stats .stat {
  min-width: 0;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 14px 16px;
}
.money-stats .stat .k { line-height: 1.35; min-height: 2.7em; }
.money-stats .stat .v {
  font-size: clamp(15px, 10.5cqi, 24px);
  line-height: 1.15;
  margin-top: 8px;
  white-space: nowrap;
  letter-spacing: -.3px;
}
.money-sub { margin-top: 26px; }
.money-sub .section-head { margin: 0 0 12px; }

.money-day-bar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; padding: 12px 14px; }
.money-day-nav { display: flex; gap: 6px; align-items: center; }
.money-day-nav .btn { padding: 0; width: 38px; height: 38px; display: inline-flex; align-items: center; justify-content: center; }
.money-day-nav .btn:disabled { opacity: .35; cursor: default; }
.money-day-nav .next svg { transform: scaleX(-1); }
[dir=rtl] .money-day-nav .flip svg { transform: scaleX(-1); }
[dir=rtl] .money-day-nav .flip.next svg { transform: none; }
.money-day-nav input[type=date] {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  height: 38px;
  padding: 0 10px;
  color: var(--text);
  font: inherit;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color-scheme: dark;
  outline: none;
}
.money-day-nav input[type=date]:focus { border-color: var(--violet); box-shadow: 0 0 0 3px rgba(124, 92, 255, .16); }
.money-day-bar .seg { min-width: 180px; }
.money-day-title { margin: 18px 2px 12px; font-size: 16px; font-weight: 750; }

/* 00:00 on the left whatever the reading direction - a clock face does not flip */
.money-hours { direction: ltr; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 3px; }
.money-hours .hour { display: flex; flex-direction: column; gap: 6px; min-width: 0; cursor: default; }
.money-hours .bar { height: 120px; display: flex; align-items: flex-end; border-bottom: 1px solid var(--line-soft); }
.money-hours .bar i { display: block; width: 100%; background: var(--grad); border-radius: 4px 4px 1px 1px; }
.money-hours .bar i.loss { background: var(--lose); }
.money-hours .hour:hover .bar i { filter: brightness(1.25); }
.money-hours .hour span { height: 12px; font-size: 10px; line-height: 12px; text-align: center; color: var(--text-mute); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .money-day-bar { justify-content: center; }
  .money-day-bar .seg { flex: 1 1 100%; }
  .money-hours { gap: 1px; }
}

/* ---- the banner a paused account sees ------------------------------------ */

/* Sits inside .main, above whatever page is mounted, and lines its width up
   with .page so it reads as part of the same column rather than a strip laid
   over the top. It is not a grid child of #app - putting it there would land
   it in the same grid area as .main and paint straight over the page. */
.account-notice {
  max-width: 1500px;
  margin: 18px auto -8px;
  padding: 11px 15px;
  border-radius: var(--r);
  font-size: 13px;
  line-height: 1.5;
  background: color-mix(in srgb, var(--warn) 13%, var(--bg-2));
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  color: var(--text);
}
/* .page owns the outer gutter, so the notice gets its own to match. */
.main > .account-notice { margin-left: 24px; margin-right: 24px; }
@media (max-width: 640px) { .main > .account-notice { margin-left: 14px; margin-right: 14px; } }
.account-notice b { color: var(--warn); }
.account-notice.blocked {
  background: color-mix(in srgb, var(--lose) 13%, var(--bg-2));
  border-color: color-mix(in srgb, var(--lose) 45%, transparent);
}
.account-notice.blocked b { color: var(--lose); }

@media (max-width: 900px) {
  .admin-cols { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .admin-toolbar { padding: 12px; gap: 9px; }
  .admin-toolbar .count { margin-left: 0; width: 100%; }
  .admin-toolbar select { width: 100%; }
  .account-notice { margin: 12px 0 -10px; font-size: 12.5px; }
  .admin-set .btn { flex: 1 1 auto; }
}

/* ---------------------------------------------------------------------------
   Roulette — chips, and the felt stood on its end
   -------------------------------------------------------------------------
   Two felts live in the document at once and a media query decides which one
   is on screen. They register the same bets, so a chip placed on one is a chip
   on the other; only the geometry differs.
   --------------------------------------------------------------------------- */

/* ---- the chips you pick up ------------------------------------------------ */

/* Six denominations on one line inside a 322px panel. Wrapping puts the
   biggest chip alone on a second row, which reads as five chips and a mistake. */
.chip-row { display: flex; gap: 6px; }

.chip-pick {
  --chip: var(--violet);
  position: relative;
  width: 44px;
  height: 44px;
  flex: none;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  display: grid;
  place-items: center;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  color: #0d1020;
  outline: 2.5px solid transparent;
  outline-offset: 3px;
  transition: transform .14s, outline-color .14s;
  /* the dashed edge every casino chip has, drawn rather than pictured */
  background: conic-gradient(
    #fff 0 12.5%, var(--chip) 0 25%, #fff 0 37.5%, var(--chip) 0 50%,
    #fff 0 62.5%, var(--chip) 0 75%, #fff 0 87.5%, var(--chip) 0);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .5), inset 0 -3px 8px rgba(0, 0, 0, .3);
}
.chip-pick::after {
  content: '';
  position: absolute;
  inset: 7px;
  border-radius: 50%;
  background: var(--chip);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .26);
}
.chip-pick span { position: relative; z-index: 2 }
.chip-pick[aria-pressed="true"] { outline-color: var(--gold); transform: translateY(-4px); }
.chip-pick:focus-visible { outline-color: var(--cyan); }

/* denominations, low to high, in the order a table racks them */
.chip-pick[data-v="0.1"] { --chip: #6b7594; color: #e8eaf6; }
.chip-pick[data-v="1"]   { --chip: #b9c2da; }
.chip-pick[data-v="5"]   { --chip: #c9304a; color: #fff; }
.chip-pick[data-v="25"]  { --chip: #0f8f63; color: #fff; }
.chip-pick[data-v="100"] { --chip: #1b2040; color: #e8eaf6; }
.chip-pick[data-v="500"] { --chip: #6d4df0; color: #f5f2ff; }

/* ---- a chip resting on the felt ------------------------------------------ */

/* after a spin, the board says which bets survived it */
.rn.chip-won .chip-on {
  background: var(--grad-gold);
  box-shadow: 0 0 0 4px rgba(255, 176, 32, .22);
}
.rn.chip-lost .chip-on { opacity: .3; filter: grayscale(.85); }

/* ---- odds printed on the outside bets ------------------------------------ */

.rn-odds {
  position: absolute;
  bottom: 2px;
  left: 0;
  right: 0;
  font-size: 8px;
  font-style: normal;
  font-weight: 700;
  letter-spacing: .04em;
  opacity: .5;
  font-variant-numeric: tabular-nums;
}

/* ---- the tall felt -------------------------------------------------------
   Zero across the top, twelve rows of three, the column bets along the
   bottom, and the dozens and even-money bets running down the left as two
   rotated strips. Five tracks and fourteen rows fit a 390px screen with the
   numbers still over the 44px touch minimum, so nothing scrolls sideways and
   the winning number can never land off screen.
   -------------------------------------------------------------------------- */

.roul-vfelt { display: none; }

@media (max-width: 860px), (pointer: coarse) {
  .roul-felt, .roul-outside { display: none; }

  /* Fourteen rows at 40px plus the gaps stood 591px tall, which is more than a
     phone has below the header - the bottom of the felt was always a scroll
     away. The numbers give up six pixels each and the two end rows a little
     more, which takes about ninety off the board and brings the whole table
     onto one screen. The cells stay wider than they are tall, so a number is
     still a comfortable thing to hit. */
  .roul-vfelt {
    display: grid;
    width: 100%;
    grid-template-columns: 34px 34px repeat(3, minmax(0, 1fr));
    grid-template-rows: 26px repeat(12, minmax(26px, auto)) 24px;
    gap: 2px;
  }

  /* zero spans the three number tracks */
  .roul-vfelt .v-zero { grid-column: 3 / 6; grid-row: 1; }

  /* the numbers fill rows 2-13 of the three number tracks, in reading order */
  .roul-vfelt .rn { aspect-ratio: auto; min-height: 0; font-size: 13px; }

  /* the column bets sit under the track they belong to */
  .roul-vfelt .rn.out { font-size: 11.5px; }

  /* The two strips down the left. Which row each one occupies is set in JS,
     next to the code that knows what a dozen is; this is only how they look. */
  .roul-vfelt .v-strip {
    writing-mode: vertical-rl;
    font-size: 11.5px;
    letter-spacing: .02em;
    padding: 5px 0;
  }

  /* rotated text puts the odds on the wrong edge, so they ride the top instead */
  .roul-vfelt .v-strip .rn-odds {
    writing-mode: horizontal-tb;
    bottom: auto;
    top: 3px;
    left: 0;
    right: 0;
    font-size: 7.5px;
  }

  /* a chip on a rotated strip belongs at its top corner, not its side */
  .roul-vfelt .v-strip .chip-on { top: -5px; right: -5px; }

  .roul-wheelbox { align-self: stretch; }
  .chip-row { gap: 7px; justify-content: space-between; }
  .chip-pick { width: 40px; height: 40px; }
}

/* the very narrowest phones give the strips a little less and the numbers more */
@media (max-width: 380px) {
  .roul-vfelt { grid-template-columns: 30px 30px repeat(3, minmax(0, 1fr)); gap: 2px; }
  .roul-vfelt .v-strip { font-size: 10.5px; }
  .chip-pick { width: 40px; height: 40px; font-size: 11.5px; }
}

/* ---------------------------------------------------------------------------
   Language

   Flags are drawn, not typed: the regional-indicator emoji renders as two grey
   letters on Windows, which is half the desktops this will be opened on. The
   hairline ring is what stops a white flag - Japan, and the top of several
   others - dissolving into the panel behind it.
   --------------------------------------------------------------------------- */

.flag {
  width: 22px;
  height: 14.67px;
  display: block;
  border-radius: 2.5px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .22), 0 1px 3px rgba(0, 0, 0, .45);
}

.lang-btn { padding: 0 7px; }
.lang-btn .flag { width: 24px; height: 16px; }

.lang-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.lang-row {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  min-height: 52px;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  color: var(--text-dim);
  font-family: inherit;
  text-align: start;
  cursor: pointer;
  transition: background .13s, border-color .13s, color .13s;
}
.lang-row:hover { background: var(--surface-2); color: var(--text); }
.lang-row.on { border-color: var(--violet); background: color-mix(in srgb, var(--violet) 14%, var(--surface)); color: var(--text); }

.lang-flag { flex: none; display: block; }
.lang-names { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.lang-names b { font-size: 13.5px; font-weight: 700; line-height: 1.2; }
.lang-names i {
  font-style: normal;
  font-size: 10.5px;
  color: var(--text-mute);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* the tick only exists on the row that is already chosen */
.lang-tick { margin-inline-start: auto; width: 14px; flex: none; }
.lang-row.on .lang-tick {
  height: 14px;
  background: var(--violet);
  clip-path: polygon(14% 48%, 0 62%, 38% 100%, 100% 22%, 86% 8%, 38% 72%);
}

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

/* ---------------------------------------------------------------------------
   Right to left

   Hebrew and Arabic turn the interface around. The game boards are the one
   thing that stays put: a dice bar, a roulette felt and a plinko pyramid are
   diagrams rather than prose, and mirroring them would move the zero to the
   other end of a table people already know the shape of. So the chrome flips
   and the stage does not.
   --------------------------------------------------------------------------- */

[dir="rtl"] .game-stage { direction: ltr; }

/* the drawer comes in from the side the reader starts on */
[dir="rtl"] .sidenav { border-right: 0; border-left: 1px solid var(--line-soft); }

@media (max-width: 1024px) {
  [dir="rtl"] .sidenav { left: auto; right: 0; transform: translateX(100%); }
  [dir="rtl"] #app.nav-open .sidenav { transform: none; box-shadow: -16px 0 44px rgba(0, 0, 0, .55); }
}

[dir="rtl"] .toast-wrap { right: auto; left: 20px; align-items: flex-start; }
@media (max-width: 560px) {
  [dir="rtl"] .toast-wrap { left: 12px; right: 12px; }
}

/* A number entered into a form is read left to right in every language here,
   so the caret and the digits stay that way whatever the paragraph does. */
[dir="rtl"] input[type="number"],
[dir="rtl"] input[type="email"],
[dir="rtl"] input[type="password"] { direction: ltr; text-align: start; }

/* The flags at the top of the age gate. Small, because this is a question
   about age and not a settings screen - but present, because it is the first
   thing anybody reads and there is no way past it to the picker in the bar. */
.age-langs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  margin-bottom: 18px;
}
.age-lang {
  padding: 4px;
  border-radius: 5px;
  border: 1px solid transparent;
  background: none;
  cursor: pointer;
  line-height: 0;
  opacity: .5;
  transition: opacity .13s, border-color .13s, background .13s;
}
.age-lang:hover { opacity: 1; background: var(--surface); }
.age-lang.on { opacity: 1; border-color: var(--violet); background: color-mix(in srgb, var(--violet) 16%, transparent); }

/* ---------------------------------------------------------------------------
   Roulette on a phone: getting Spin above the fold

   This is the tallest board on the site - thirteen rows of felt plus the
   header - and the button that commits the bet sits under it. Every other
   game fits; this one was asking the player to place chips, scroll, and only
   then find the control. The felt has already given up what it can without
   the numbers becoming hard to hit, so the rest comes out of the frame around
   it: the padding, the margins and the readout, for this game only.
   --------------------------------------------------------------------------- */
@media (max-width: 860px), (pointer: coarse) {
  .game-stage:has(.roul-vfelt) { padding: 9px; min-height: 0; }
  .game-panel:has(.chip-row) { padding-top: 9px; }
  .roul-wheelbox { margin-bottom: 6px; }
  .roul-vfelt .v-strip { padding: 3px 0; }
  /* the chip picker and its label are one row, not two */
  .game-panel:has(.chip-row) > .field:first-of-type { margin-bottom: 6px; }
  .chip-row { margin-top: 2px; }
}

@media (max-width: 560px) {
  /* The last of it, still roulette only: the readout shrinks a notch and the
     chip label sits tight against its row rather than on a line of its own. */
  .game-stage:has(.roul-vfelt) .roul-result { width: 34px; height: 34px; font-size: 14px; }
  .page:has(.roul-vfelt) { padding-top: 10px; }
  .page:has(.roul-vfelt) .game-head { margin-bottom: 6px; }
  .game-panel:has(.chip-row) > .field:first-of-type > label { margin-bottom: 4px; font-size: 11.5px; }
}

/* ---------------------------------------------------------------------------
   Withdrawals - the cashier, the code, and the admin's check on it
   ------------------------------------------------------------------------- */

.wd-box {
  background:
    radial-gradient(120% 140% at 100% 0%, rgba(255, 176, 32, .10), transparent 55%),
    linear-gradient(160deg, #1b1a3d, #141830);
  border-color: color-mix(in srgb, var(--gold) 28%, var(--line));
}
.wd-box-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
.wd-box-head h2 { margin: 2px 0 0; font-size: 19px; }
.wd-kicker { font-size: 11px; font-weight: 800; letter-spacing: .12em; color: var(--gold); }
.wd-balance { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; font-size: 12px; }
.wd-balance > span:last-child { display: inline-flex; align-items: center; gap: 7px; font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums; }
.wd-explain { margin: 12px 0 16px; font-size: 13px; }

.wd-form { display: flex; flex-direction: column; gap: 10px; }
.wd-form .input-group input { border-radius: 10px; font-size: 20px; font-weight: 750; padding: 13px 14px; }
.wd-quick { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.wd-quick .btn { width: 100%; }

.wd-summary {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 14px 0;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(0, 0, 0, .18);
  border: 1px solid var(--line-soft);
}
.wd-summary > div { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.wd-summary .dim { font-size: 11.5px; }
.wd-summary b { font-size: 17px; font-variant-numeric: tabular-nums; }
.wd-summary > div:first-child b { color: var(--win); }

.wd-fine { margin: 10px 0 0; font-size: 12.5px; }
.neg-text { color: var(--lose); }
.wd-notmoney { margin: 12px 0 0; font-size: 11.5px; color: var(--text-mute); border-top: 1px solid var(--line-soft); padding-top: 10px; }

.wd-stats .stat .v { font-size: clamp(16px, 2.2vw, 21px); overflow-wrap: anywhere; }
.wd-row { cursor: pointer; }
.wd-when { display: block; font-size: 11px; margin-top: 3px; }
.wd-code-sm { font-weight: 700; letter-spacing: .14em; font-size: 12.5px; }
.wd-actions { display: inline-flex; gap: 6px; }

/* The code itself. Five characters, big and spaced, so it reads off a phone
   screen and into another app without a squint. */
.wd-code {
  display: inline-block;
  font-family: var(--mono);
  font-weight: 800;
  font-size: 34px;
  letter-spacing: .32em;
  padding-left: .32em;       /* balance the trailing letter-spacing */
  direction: ltr;
  unicode-bidi: isolate;
}
.wd-ticket {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 22px 16px;
  margin-bottom: 16px;
  border-radius: 16px;
  border: 1px dashed color-mix(in srgb, var(--gold) 55%, transparent);
  background: linear-gradient(160deg, rgba(255, 176, 32, .10), rgba(124, 92, 255, .08));
  text-align: center;
}
.wd-ticket .wd-code { font-size: clamp(30px, 11vw, 44px); color: var(--text); }
.wd-ticket-amount { display: inline-flex; align-items: center; gap: 7px; font-size: 15px; }
.wd-ticket-amount b { font-size: 20px; font-variant-numeric: tabular-nums; }
.wd-ticket-amount span { color: var(--text-dim); }
.wd-issued-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.wd-issued-actions .btn { width: 100%; }

/* ---- admin: checking a code ---------------------------------------------- */
.wd-verify { display: flex; gap: 10px; flex-wrap: wrap; }
.wd-verify-input {
  flex: 1 1 220px;
  text-transform: uppercase;
  font-family: var(--mono);
  font-weight: 800;
  font-size: 20px !important;
  letter-spacing: .25em;
  direction: ltr;
}
.wd-verify-input::placeholder { letter-spacing: normal; font-weight: 500; font-size: 14px; text-transform: none; }
.wd-result { margin-bottom: 18px; border-width: 1px; border-style: solid; }
.wd-result.ok   { border-color: color-mix(in srgb, var(--win) 55%, transparent);  background: color-mix(in srgb, var(--win) 7%, var(--surface)); }
.wd-result.used { border-color: color-mix(in srgb, var(--warn) 55%, transparent); background: color-mix(in srgb, var(--warn) 7%, var(--surface)); }
.wd-result.void { border-color: color-mix(in srgb, var(--lose) 55%, transparent); background: color-mix(in srgb, var(--lose) 7%, var(--surface)); }
.wd-result-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.wd-result-head .wd-code { font-size: 26px; }
.wd-verdict { font-size: 15px; }
.wd-result.ok .wd-verdict { color: var(--win); }
.wd-result.used .wd-verdict { color: var(--warn); }
.wd-result.void .wd-verdict { color: var(--lose); }
.wd-stat-foot { font-size: 11.5px; margin-top: 4px; }
.wd-todo {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 8px;
  margin-bottom: 14px;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(0, 0, 0, .2);
  border: 1px solid var(--line-soft);
  font-size: 14px;
}
.wd-todo-val { font-size: 17px; font-variant-numeric: tabular-nums; unicode-bidi: isolate; }
.wd-todo-copy { display: inline-flex; gap: 6px; margin-inline-start: auto; }
@media (max-width: 640px) { .wd-todo-copy { margin-inline-start: 0; width: 100%; } .wd-todo-copy .btn { flex: 1; } }

@media (max-width: 640px) {
  .wd-balance { align-items: flex-start; }
  .wd-summary { grid-template-columns: 1fr; }
  .wd-issued-actions { grid-template-columns: 1fr; }
  .wd-verify .btn { flex: 1 1 100%; }
  .wd-actions { flex-direction: column; }
}

/* ---------------------------------------------------------------------------
   Rock Paper Scissors
   -------------------------------------------------------------------------
   The ladder along the top, the two hands facing off in the middle, the
   picks under them. Everything that moves is a CSS animation restarted by
   the script, so a throw is cheap and a hidden tab cannot leave one stuck. */

.game-stage.rps-stage { justify-content: flex-start; gap: 18px; padding-top: 70px; overflow: hidden; }

/* ---- the ladder ---- */
.rps-ladder {
  display: flex;
  gap: 8px;
  width: 100%;
  max-width: 720px;
  overflow-x: auto;
  padding: 6px 4px 10px;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.rps-ladder::-webkit-scrollbar { display: none; }
.rps-step {
  flex: 0 0 auto;
  min-width: 78px;
  padding: 8px 10px 9px;
  border-radius: 12px;
  background: var(--bg-2);
  border: 1px solid var(--line-soft);
  text-align: center;
  transition: background .25s, border-color .25s, transform .25s, box-shadow .25s;
}
.rps-step b { display: block; font-size: 14px; font-variant-numeric: tabular-nums; color: var(--text-dim); }
.rps-step-n { display: block; font-size: 10px; font-weight: 700; color: var(--text-mute); letter-spacing: .06em; margin-bottom: 2px; }
.rps-step.done { background: color-mix(in srgb, var(--win) 14%, var(--bg-2)); border-color: color-mix(in srgb, var(--win) 45%, transparent); }
.rps-step.done b { color: var(--win); }
.rps-step.next {
  border-color: #e879f9;
  box-shadow: 0 0 0 3px rgba(232, 121, 249, .18), 0 6px 18px rgba(232, 121, 249, .18);
  transform: translateY(-2px);
}
.rps-step.next b { color: var(--text); }
.rps-step.hit { animation: rps-hit .5s cubic-bezier(.2, 1.6, .4, 1); }
@keyframes rps-hit { 0% { transform: scale(1); } 45% { transform: scale(1.18); } 100% { transform: scale(1); } }

/* ---- the arena ---- */
.rps-arena {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 560px;
  margin-top: 6px;
}
.rps-side { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.rps-tag { font-size: 11.5px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: var(--text-mute); }

.rps-hand {
  --ring: var(--line);
  width: clamp(112px, 26vw, 164px);
  aspect-ratio: 1;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background:
    radial-gradient(circle at 35% 28%, rgba(255, 255, 255, .10), transparent 60%),
    linear-gradient(160deg, var(--surface-3), var(--bg-2));
  border: 2px solid var(--ring);
  box-shadow: inset 0 -10px 24px rgba(0, 0, 0, .35), 0 12px 30px rgba(0, 0, 0, .3);
  transition: border-color .25s, box-shadow .3s, filter .3s, opacity .3s;
}
.rps-hand.you { --ring: rgba(124, 92, 255, .55); }
.rps-hand.house { --ring: rgba(232, 121, 249, .45); }
.rps-glyph {
  display: block;
  font-size: clamp(54px, 13vw, 82px);
  line-height: 1;
  user-select: none;
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, .35));
}
/* the house hand faces back across the table */
.rps-hand.house .rps-glyph { transform: scaleX(-1); }

/* rock... paper... scissors... - one pump per beat */
.rps-hand.pump .rps-glyph { animation: rps-pump .29s cubic-bezier(.3, .7, .4, 1); }
.rps-hand.house.pump .rps-glyph { animation-name: rps-pump-house; }
@keyframes rps-pump {
  0%   { transform: translateY(0) rotate(0); }
  45%  { transform: translateY(-30px) rotate(-16deg); }
  100% { transform: translateY(0) rotate(0); }
}
@keyframes rps-pump-house {
  0%   { transform: scaleX(-1) translateY(0) rotate(0); }
  45%  { transform: scaleX(-1) translateY(-30px) rotate(-16deg); }
  100% { transform: scaleX(-1) translateY(0) rotate(0); }
}

/* ...shoot: the hand opens with a pop */
.rps-hand.reveal .rps-glyph { animation: rps-reveal .42s cubic-bezier(.2, 1.7, .4, 1); }
.rps-hand.house.reveal .rps-glyph { animation-name: rps-reveal-house; }
@keyframes rps-reveal { 0% { transform: scale(.55); } 60% { transform: scale(1.16); } 100% { transform: scale(1); } }
@keyframes rps-reveal-house { 0% { transform: scaleX(-1) scale(.55); } 60% { transform: scaleX(-1) scale(1.16); } 100% { transform: scaleX(-1) scale(1); } }

.rps-hand.win {
  --ring: var(--win);
  box-shadow: 0 0 0 6px rgba(61, 220, 151, .16), 0 0 44px rgba(61, 220, 151, .38), inset 0 -10px 24px rgba(0, 0, 0, .3);
}
.rps-hand.lose { --ring: rgba(255, 93, 122, .6); filter: saturate(.35) brightness(.8); opacity: .8; animation: rps-shake .38s ease-in-out; }
.rps-hand.draw { --ring: var(--warn); box-shadow: 0 0 0 5px rgba(255, 176, 32, .14), inset 0 -10px 24px rgba(0, 0, 0, .3); animation: rps-wobble .5s ease-in-out; }
@keyframes rps-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-9px) rotate(-4deg); }
  40% { transform: translateX(8px) rotate(3deg); }
  60% { transform: translateX(-6px); }
  80% { transform: translateX(4px); }
}
@keyframes rps-wobble { 0%, 100% { transform: rotate(0); } 30% { transform: rotate(-6deg); } 65% { transform: rotate(5deg); } }

.rps-vs {
  min-width: 58px;
  padding: 7px 12px;
  border-radius: 999px;
  text-align: center;
  font-size: 13px;
  font-weight: 900;
  letter-spacing: .08em;
  color: var(--text-dim);
  background: var(--bg-2);
  border: 1px solid var(--line);
  transition: background .25s, color .25s, border-color .25s;
}
.rps-vs.win  { color: #062a18; background: var(--win); border-color: var(--win); animation: rps-hit .45s cubic-bezier(.2, 1.6, .4, 1); }
.rps-vs.lose { color: #fff; background: var(--lose); border-color: var(--lose); animation: rps-hit .45s cubic-bezier(.2, 1.6, .4, 1); }
.rps-vs.draw { color: #2b1c00; background: var(--warn); border-color: var(--warn); animation: rps-hit .45s cubic-bezier(.2, 1.6, .4, 1); }

.rps-status { min-height: 24px; font-size: 16px; font-weight: 750; color: var(--text-dim); text-align: center; }
/* the stage is always laid out left to right, but a sentence in Hebrew or Arabic
   still has to read in its own direction - so each line takes it from its text */
.rps-status, .rps-tag, .rps-vs, .rps-pick b { unicode-bidi: plaintext; }
/* spaced capitals are a Latin habit; Hebrew and Arabic letters just drift apart */
[dir=rtl] .rps-tag, [dir=rtl] .rps-vs { letter-spacing: 0; }
.rps-status.counting { color: var(--text); letter-spacing: .04em; }
.rps-status.win { color: var(--win); }
.rps-status.lose { color: var(--lose); }
.rps-status.draw { color: var(--warn); }

/* ---- the picks ---- */
.rps-picks {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(0, .8fr);
  gap: 10px;
  width: 100%;
  max-width: 560px;
}
.rps-pick {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 12px 6px 10px;
  border-radius: 14px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  transition: transform .15s, border-color .15s, background .15s, opacity .2s;
}
.rps-pick b { font-size: 13px; font-weight: 750; }
.rps-pick-glyph { font-size: 34px; line-height: 1.1; transition: transform .2s cubic-bezier(.2, 1.6, .4, 1); }
.rps-pick kbd {
  position: absolute;
  top: 6px; right: 7px;
  font: 700 10px/1 var(--mono);
  padding: 3px 5px;
  border-radius: 5px;
  color: var(--text-mute);
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
}
.rps-picks.live .rps-pick:hover:not(:disabled) { transform: translateY(-3px); border-color: #e879f9; background: var(--surface-3); }
.rps-picks.live .rps-pick:hover:not(:disabled) .rps-pick-glyph { transform: scale(1.14) rotate(-8deg); }
.rps-pick:active:not(:disabled) { transform: translateY(0) scale(.97); }
.rps-pick:disabled { opacity: .45; cursor: default; }
.rps-pick.chosen { border-color: #e879f9; background: color-mix(in srgb, #e879f9 12%, var(--bg-2)); opacity: 1; }
.rps-random b { color: var(--text-dim); }

/* ---- history ---- */
.rps-history { display: flex; gap: 6px; max-width: 100%; overflow-x: auto; padding-bottom: 2px; scrollbar-width: none; }
.rps-history::-webkit-scrollbar { display: none; }
.rps-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 14px;
  background: var(--surface-2);
  border: 1px solid transparent;
}
.rps-chip i { font-style: normal; line-height: 1; }
.rps-chip small { color: var(--text-mute); font-size: 10px; }
.rps-chip .rps-mirror { display: inline-block; transform: scaleX(-1); }
.rps-chip.win  { background: rgba(61, 220, 151, .13); border-color: rgba(61, 220, 151, .35); }
.rps-chip.lose { background: rgba(255, 93, 122, .12); border-color: rgba(255, 93, 122, .35); }
.rps-chip.draw { background: rgba(255, 176, 32, .11); border-color: rgba(255, 176, 32, .3); }

/* ---- sparks off a winning hand ---- */
.rps-spark {
  position: absolute;
  width: 8px; height: 8px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0, #7dffc4 45%, rgba(61, 220, 151, 0) 70%);
  pointer-events: none;
  animation: rps-spark .75s cubic-bezier(.15, .7, .3, 1) forwards;
  z-index: 3;
}
@keyframes rps-spark {
  0%   { transform: translate(0, 0) scale(1.4); opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) scale(.2); opacity: 0; }
}

@media (max-width: 640px) {
  .game-stage.rps-stage { padding-top: 58px; gap: 14px; }
  .rps-arena { gap: 8px; }
  .rps-vs { min-width: 48px; padding: 6px 8px; font-size: 11.5px; }
  .rps-picks { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .rps-random { grid-column: 1 / -1; flex-direction: row; justify-content: center; padding: 8px; }
  .rps-random .rps-pick-glyph { font-size: 20px; }
  .rps-step { min-width: 66px; padding: 6px 8px; }
}
@media (max-width: 640px), (hover: none) { .rps-pick kbd { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .rps-hand .rps-glyph, .rps-hand, .rps-step.hit, .rps-vs, .rps-spark { animation-duration: .01s !important; }
}

/* ---------------------------------------------------------------------------
   Bars
   -------------------------------------------------------------------------
   Thirty ingots on a dark tray. A picked ingot lifts and takes the
   difficulty's colour; on a bet every tile turns over on its X axis to show
   its multiplier, coloured by how much it is worth. The turn is a transform
   only, so a whole board of them stays smooth on a phone. */

.game-stage.bars-stage { justify-content: flex-start; gap: 14px; padding-top: 66px; }

.bars-grid {
  --pick: #7dd3fc;
  --pick-soft: rgba(125, 211, 252, .18);
  display: grid;
  grid-template-columns: repeat(var(--cols, 6), minmax(0, 1fr));
  gap: 9px;
  width: min(100%, 560px);
  padding: 12px;
  border-radius: 18px;
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(255, 196, 64, .06), transparent 60%),
    linear-gradient(180deg, #121526, #0c0e1b);
  border: 1px solid var(--line-soft);
  box-shadow: inset 0 2px 14px rgba(0, 0, 0, .45);
}
.bars-grid.d-medium { --pick: #3b82f6; --pick-soft: rgba(59, 130, 246, .22); }
.bars-grid.d-hard   { --pick: #22c55e; --pick-soft: rgba(34, 197, 94, .2); }
.bars-grid.d-expert { --pick: #fbbf24; --pick-soft: rgba(251, 191, 36, .22); }

.bars-cell {
  position: relative;
  aspect-ratio: 1.18;
  padding: 0;
  border: 0;
  background: none;
  perspective: 600px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.bars-cell:disabled { cursor: default; }
.bars-inner {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform .42s cubic-bezier(.3, .9, .35, 1.08);
}
.bars-cell.open .bars-inner { transform: rotateX(180deg); }

.bars-front, .bars-back {
  position: absolute;
  inset: 0;
  border-radius: 11px;
  display: grid;
  place-items: center;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* ---- the face-down tile: an ingot on a slate ---- */
.bars-front {
  background: linear-gradient(180deg, #23283f, #1a1e31);
  border: 1px solid rgba(255, 255, 255, .06);
  box-shadow: 0 3px 0 #0b0d18, 0 6px 12px rgba(0, 0, 0, .35);
  transition: background .2s, border-color .2s, box-shadow .2s, transform .2s;
}
.bars-ingot {
  position: relative;
  width: 64%;
  height: 46%;
  clip-path: polygon(14% 0, 86% 0, 100% 100%, 0 100%);
  background: linear-gradient(180deg, #ffe9a3 0%, #f5c542 34%, #d99a16 72%, #b37710 100%);
  filter: saturate(.55) brightness(.72);
  transition: filter .2s, transform .2s;
}
.bars-ingot::before {           /* the ingot's top face catching the light */
  content: "";
  position: absolute;
  left: 18%; right: 18%; top: 0; height: 30%;
  background: linear-gradient(180deg, rgba(255, 255, 255, .75), rgba(255, 255, 255, .1));
  clip-path: polygon(0 0, 100% 0, 92% 100%, 8% 100%);
}
.bars-ingot::after {            /* a sheen that sweeps across on hover */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, .55) 50%, transparent 65%);
  transform: translateX(-120%);
}

.bars-grid:not(.revealed) .bars-cell:not(:disabled):hover .bars-front { transform: translateY(-2px); border-color: rgba(255, 255, 255, .14); }
.bars-grid:not(.revealed) .bars-cell:not(:disabled):hover .bars-ingot { filter: saturate(.85) brightness(.9); }
.bars-grid:not(.revealed) .bars-cell:not(:disabled):hover .bars-ingot::after { transform: translateX(120%); transition: transform .55s ease; }

/* ---- picked ---- */
.bars-cell.picked .bars-front {
  background: linear-gradient(180deg, color-mix(in srgb, var(--pick) 30%, #23283f), color-mix(in srgb, var(--pick) 16%, #1a1e31));
  border-color: var(--pick);
  box-shadow: 0 3px 0 color-mix(in srgb, var(--pick) 45%, #0b0d18), 0 0 0 3px var(--pick-soft), 0 8px 20px var(--pick-soft);
  transform: translateY(-2px);
}
.bars-cell.picked .bars-ingot { filter: none; transform: scale(1.06); }
.bars-cell.picked:not(.open) .bars-front { animation: bars-pick .3s cubic-bezier(.2, 1.6, .4, 1); }
@keyframes bars-pick { 0% { transform: translateY(0) scale(.94); } 100% { transform: translateY(-2px) scale(1); } }

.bars-cell.nope .bars-front { animation: bars-nope .32s ease-in-out; }
@keyframes bars-nope { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }

/* ---- the face-up tile, coloured by what it holds ---- */
.bars-back {
  transform: rotateX(180deg);
  background: #1b1e30;
  border: 1px solid rgba(255, 255, 255, .06);
  color: #8a90ad;
}
.bars-val {
  font-size: clamp(10px, 2.6vw, 15px);
  font-weight: 850;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.3px;
  white-space: nowrap;
}
.bars-cell.t1 .bars-back { background: #262a40; color: #e6e8f2; }
.bars-cell.t2 .bars-back { background: linear-gradient(180deg, rgba(61, 220, 151, .22), rgba(61, 220, 151, .1)); color: #5ff0ad; border-color: rgba(61, 220, 151, .3); }
.bars-cell.t3 .bars-back { background: linear-gradient(180deg, rgba(56, 189, 248, .26), rgba(56, 189, 248, .1)); color: #8adcff; border-color: rgba(56, 189, 248, .35); }
.bars-cell.t4 .bars-back { background: linear-gradient(180deg, rgba(192, 132, 252, .34), rgba(147, 51, 234, .16)); color: #e2c4ff; border-color: rgba(192, 132, 252, .45); }
.bars-cell.t5 .bars-back {
  background: linear-gradient(180deg, #ffe69a, #f5b82e 55%, #d58e0c);
  color: #3a2500;
  border-color: #ffd36b;
  box-shadow: 0 0 18px rgba(255, 196, 64, .45);
}

/* the rest of the board steps back once it has shown its hand */
/* Dimmed on the face, never on .bars-inner: opacity on a preserve-3d element
   flattens it, and a flattened tile shows the back of its ingot instead of
   its multiplier. */
.bars-cell.open.dim .bars-back { opacity: .5; }
.bars-cell.open.dim.t4 .bars-back, .bars-cell.open.dim.t5 .bars-back { opacity: .82; }

/* a picked tile, turned: ringed in the difficulty colour and landed with a pop */
.bars-cell.mine .bars-back { box-shadow: 0 0 0 3px var(--pick), 0 10px 24px var(--pick-soft); }
.bars-cell.mine.t5 .bars-back { box-shadow: 0 0 0 3px var(--pick), 0 0 34px rgba(255, 196, 64, .6); }
.bars-cell.land { animation: bars-land .5s cubic-bezier(.2, 1.5, .4, 1); z-index: 2; }
@keyframes bars-land { 0% { transform: scale(1); } 40% { transform: scale(1.14); } 100% { transform: scale(1.04); } }
.bars-cell.mine { transform: scale(1.04); z-index: 1; }

/* ---- above and below the board ---- */
.bars-head {
  display: flex;
  align-items: stretch;
  gap: 10px;
  width: min(100%, 560px);
}
.bars-head > div {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 9px 14px;
  border-radius: 12px;
  background: var(--bg-2);
  border: 1px solid var(--line-soft);
}
.bars-head span { font-size: 10.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--text-mute); unicode-bidi: plaintext; }
.bars-total { flex: 1; }
.bars-total-v { font-size: 26px; font-weight: 850; font-variant-numeric: tabular-nums; letter-spacing: -.5px; transition: color .2s; }
.bars-total-v.win { color: var(--win); text-shadow: 0 0 18px rgba(61, 220, 151, .35); }
.bars-total-v.lose { color: var(--text-dim); }
.bars-picked { min-width: 108px; text-align: center; align-items: center; }
.bars-picked b { font-size: 20px; font-variant-numeric: tabular-nums; }
[dir=rtl] .bars-head span { letter-spacing: 0; }

.bars-hint { min-height: 18px; font-size: 13px; font-weight: 650; color: var(--text-mute); text-align: center; unicode-bidi: plaintext; }

.bars-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; width: min(100%, 560px); }
.bars-chip {
  padding: 4px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  background: #1b1e30;
  color: #8a90ad;
  border: 1px solid rgba(255, 255, 255, .06);
  cursor: help;
}
.bars-chip.t1 { background: #262a40; color: #e6e8f2; }
.bars-chip.t2 { background: rgba(61, 220, 151, .14); color: #5ff0ad; border-color: rgba(61, 220, 151, .3); }
.bars-chip.t3 { background: rgba(56, 189, 248, .15); color: #8adcff; border-color: rgba(56, 189, 248, .32); }
.bars-chip.t4 { background: rgba(192, 132, 252, .2); color: #e2c4ff; border-color: rgba(192, 132, 252, .4); }
.bars-chip.t5 { background: linear-gradient(180deg, #ffe69a, #e9a51c); color: #3a2500; border-color: #ffd36b; }

.bars-spark {
  position: absolute;
  width: 7px; height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0, #e2c4ff 45%, rgba(192, 132, 252, 0) 70%);
  pointer-events: none;
  z-index: 4;
  animation: bars-spark .8s cubic-bezier(.15, .7, .3, 1) forwards;
}
.bars-spark.gold { background: radial-gradient(circle, #fff 0, #ffd36b 45%, rgba(255, 196, 64, 0) 70%); width: 9px; height: 9px; }
@keyframes bars-spark {
  0%   { transform: translate(0, 0) scale(1.5); opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) scale(.2); opacity: 0; }
}

.game-stage.busy .bars-cell { pointer-events: none; }

@media (max-width: 640px) {
  .game-stage.bars-stage { padding-top: 56px; gap: 11px; }
  .bars-grid { gap: 6px; padding: 8px; border-radius: 14px; }
  .bars-front, .bars-back { border-radius: 8px; }
  .bars-total-v { font-size: 22px; }
  .bars-picked { min-width: 84px; }
  .bars-chip { font-size: 10.5px; padding: 3px 7px; }
}
@media (prefers-reduced-motion: reduce) {
  .bars-inner { transition-duration: .01s; }
  .bars-cell.land, .bars-spark, .bars-cell.picked:not(.open) .bars-front { animation-duration: .01s !important; }
}

/* ---- email verification gate ---- */
.verify-card { text-align: center; }
.verify-icon { font-size: 40px; line-height: 1; margin-bottom: 8px; }
.verify-card .lede { unicode-bidi: plaintext; }
.verify-form { margin: 6px 0 10px; }
.verify-code {
  width: 100%;
  text-align: center;
  font-family: var(--mono);
  font-size: 30px !important;
  font-weight: 800;
  letter-spacing: .45em;
  padding: 14px 10px 14px calc(10px + .45em) !important;
  margin-bottom: 12px;
  direction: ltr;
}
.verify-code::placeholder { letter-spacing: .3em; }
.verify-note { min-height: 18px; margin: 10px 0 0; font-size: 12.5px; unicode-bidi: plaintext; }
.verify-foot { margin: 14px 0 0; font-size: 12.5px; }
.linkish { background: none; border: 0; padding: 0; color: var(--violet); font: inherit; font-weight: 650; cursor: pointer; text-decoration: underline; }

/* ==========================================================================
   Profile pictures
   ========================================================================== */
.avatar {
  display: inline-grid;
  place-items: center;
  flex: none;
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-style: normal;
  font-weight: 900;
  line-height: 1;
  color: #0a0b14;
}
.avatar > svg, .avatar > img { width: 100%; height: 100%; display: block; object-fit: cover; }
/* The fallback: the initial on the brand gradient, exactly as every account
   looked before pictures existed. */
.avatar.initial { background: var(--grad); border-color: transparent; }
.avatar.profile { border-radius: 20px !important; }

.avatar-card .avatar-editor { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
.avatar-preview .avatar { box-shadow: var(--shadow); }
.avatar-actions { flex: 1 1 240px; }
.avatar-buttons { display: flex; gap: 10px; flex-wrap: wrap; }
.avatar-status { margin: 12px 0 10px; font-size: 12.5px; }

.avatar-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
  gap: 10px;
  margin-top: 6px;
}
.avatar-tile {
  padding: 6px;
  border-radius: 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  transition: transform .14s ease, border-color .14s ease;
}
.avatar-tile:hover { transform: translateY(-2px); border-color: var(--violet); }
.avatar-tile.on { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(255,176,32,.3); }
.avatar-tile svg { display: block; border-radius: 12px; }

/* ==========================================================================
   Live Holdem

   The room is a fixed layer over the whole app rather than a page inside it,
   so nothing below this point has to co-operate with the shell grid. It is
   built for landscape: everything is sized off the table own height so the
   same rules serve a small phone on its side and a desktop alike.
   ========================================================================== */

/* the page underneath, which is mostly a way back into the room */
.live-placeholder { display: grid; place-items: center; gap: 16px; padding: 30px 18px; text-align: center; }
.live-placeholder-felt {
  width: min(100%, 300px);
  aspect-ratio: 3 / 2;
  border-radius: 50% / 42%;
  background: radial-gradient(120% 120% at 50% 20%, #1d7a58 0%, #145741 55%, #0f4231 100%);
  border: 6px solid #2a1d15;
  box-shadow: inset 0 0 40px rgba(0,0,0,.45);
  opacity: .55;
}
.live-placeholder p { color: var(--text-dim); font-size: 13.5px; max-width: 42ch; margin: 0; }

body.live-open { overflow: hidden; }

.live-room {
  position: fixed;
  inset: 0;
  z-index: 300;
  background:
    radial-gradient(1200px 700px at 50% -10%, rgba(56,224,165,.10), transparent 62%),
    var(--bg);
  color: var(--text);
  display: flex;
  flex-direction: column;
  /* A phone in landscape puts its notch on one of the long edges, and the
     browser chrome slides in and out over the other. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

.live-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }

/* ---- top bar ------------------------------------------------------------ */
.live-top {
  flex: none;
  height: 46px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 12px;
  border-bottom: 1px solid var(--line-soft);
  background: rgba(8,10,18,.6);
}
.live-top .spacer { flex: 1; }
.live-title { display: flex; align-items: baseline; gap: 9px; min-width: 0; }
.live-title b { font-size: 14.5px; font-weight: 800; white-space: nowrap; }
.live-stake {
  font-size: 11.5px;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.live-balance {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border-radius: 20px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 12.5px;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
}
.live-icon {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  flex: none;
}
.live-icon:hover { color: var(--text); border-color: var(--violet); }
.live-icon.exit:hover { color: var(--lose); border-color: var(--lose); }

.live-hand-no { font-style: normal; font-size: 11.5px; color: var(--text-mute); white-space: nowrap; font-variant-numeric: tabular-nums; }

/* ---- the room ------------------------------------------------------------
   Three columns: what has happened on the left, the table in the middle, the
   decision on the right. The panels are frosted so the room's floor runs
   under them instead of stopping at a black edge.

   The columns stay left-to-right in a right-to-left language too. The action
   buttons belong under the right thumb whichever way the words run; only the
   text inside the panels turns round. */
.live-body { position: relative; z-index: 1; }

.live-main {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 270px minmax(0, 1fr) 300px;
  direction: ltr;
}
:root[dir="rtl"] .live-side { direction: rtl; }

.live-side {
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px;
  background: rgba(8, 10, 18, .52);
  -webkit-backdrop-filter: blur(12px) saturate(1.2);
  backdrop-filter: blur(12px) saturate(1.2);
  overflow: hidden;
}
.live-side.left { border-right: 1px solid var(--line-soft); }
.live-side.right { border-left: 1px solid var(--line-soft); }
.live-grow { flex: 1; }

.live-card {
  background: rgba(18, 21, 38, .84);
  border: 1px solid var(--line);
  border-radius: 13px;
  padding: 11px 13px;
}
.live-card h4 {
  margin: 0 0 7px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-mute);
}
.live-kv {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 3px 0;
  font-size: 12.5px;
  color: var(--text-dim);
}
.live-kv b { color: var(--text); font-weight: 750; font-variant-numeric: tabular-nums; white-space: nowrap; }
.live-kv b.gold { color: var(--gold); }
.live-kv b.win { color: var(--win); }

.live-info-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.live-info-head .live-rung-mark { width: 30px; height: 30px; }
.live-info-head b { display: block; font-size: 15px; font-weight: 800; line-height: 1.2; }
.live-info-head span { display: block; font-size: 11.5px; color: var(--gold); font-variant-numeric: tabular-nums; }

.live-history-card { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.live-history { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.live-history.in-sheet { max-height: min(60vh, 420px); }
.live-history-line {
  padding: 5px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 12px;
  line-height: 1.4;
  color: var(--text-dim);
}
.live-history-line:first-child { color: var(--text); }
.live-history-empty { margin: 4px 0; font-size: 12px; color: var(--text-mute); }

.live-seat-controls { display: flex; gap: 6px; }
.live-seat-controls .live-chip-btn { flex: 1; }
.live-chip-btn {
  padding: 7px 10px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 650;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.live-chip-btn:hover:not(:disabled) { color: var(--text); border-color: var(--violet); }
.live-chip-btn.primary { background: var(--grad-gold); color: #2b1c00; border-color: transparent; font-weight: 800; }
.live-chip-btn.danger { color: #ff8b9a; }
.live-chip-btn.danger:hover:not(:disabled) { color: var(--lose); border-color: var(--lose); }
.live-chip-btn:disabled { opacity: .55; cursor: default; }

/* the panels folded into a column of buttons, for narrower screens */
.live-railnav { display: none; flex: 1; flex-direction: column; align-items: center; gap: 4px; min-height: 0; }
.live-rail-btn {
  width: 56px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 7px 2px;
  border-radius: 11px;
  background: none;
  border: 1px solid transparent;
  color: var(--text-dim);
  font-size: 9.5px;
  font-weight: 700;
  line-height: 1.15;
  text-align: center;
}
.live-rail-btn svg { flex: none; }
.live-rail-btn span { max-width: 100%; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.live-rail-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.live-rail-btn.danger { color: #ff8b9a; }
.live-rail-btn:disabled { opacity: .45; }
.live-rail-btn.phone-only { display: none; }

/* ---- the decision --------------------------------------------------------- */
.live-dock { display: flex; flex-direction: column; gap: 9px; }
.live-turn { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 18px; }
.live-status { font-size: 12.5px; font-weight: 650; color: var(--text-dim); line-height: 1.35; }
.live-status.waiting { color: var(--gold); }
.live-turn-secs { flex: none; font-size: 12px; font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; }
.live-turnbar { height: 5px; border-radius: 5px; background: rgba(255,255,255,.1); overflow: hidden; }
.live-turnbar i { display: block; height: 100%; width: 0; background: var(--grad-gold); border-radius: 5px; }
.live-turnbar i.low { background: linear-gradient(120deg, #ff9a6b, var(--lose)); }
.live-turnbar.idle { opacity: .35; }
.live-turnbar.idle i { width: 0 !important; }
.live-dock > .live-chip-btn { padding: 12px; font-size: 14px; }

.live-actions { display: flex; flex-direction: column; gap: 9px; }
.live-raise { display: flex; flex-direction: column; gap: 8px; }
.live-sizes { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.live-sizes button {
  padding: 6px 0;
  border-radius: 8px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 700;
}
.live-sizes button:hover { color: var(--gold); border-color: var(--gold); }
.live-slider-row { display: flex; align-items: center; gap: 10px; }
.live-slider { flex: 1; min-width: 0; accent-color: var(--gold); }
.live-slider-val { min-width: 56px; text-align: end; font-size: 13px; color: var(--gold); font-variant-numeric: tabular-nums; }
.live-stepper {
  display: none;
  grid-template-columns: 32px 1fr 32px;
  align-items: center;
  height: 34px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.live-stepper button { height: 100%; background: none; border: 0; color: var(--text-dim); font-size: 18px; font-weight: 800; }
.live-stepper button:hover { color: var(--gold); }
.live-stepper b { text-align: center; font-size: 13px; color: var(--gold); font-variant-numeric: tabular-nums; }

.live-buttons { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 7px; }
.live-act {
  min-height: 48px;
  padding: 8px 10px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 850;
  border: 1px solid transparent;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.live-act.fold { background: var(--surface-2); border-color: var(--line); color: var(--text-dim); }
.live-act.fold:hover { color: var(--lose); border-color: var(--lose); }
.live-act.check, .live-act.call { background: var(--grad); color: #07081a; }
.live-act.raise { background: var(--grad-gold); color: #2b1c00; }
.live-act:active { transform: translateY(1px); }

/* ==========================================================================
   The table

   Everything drawn on it is measured in --u: one percent of the table's own
   width, held between 5 and 12 pixels. The phone and the monitor therefore
   draw the same picture at different sizes, and nothing on it is ever smaller
   than it can be read at.
   ========================================================================== */
.live-stage {
  position: relative;
  container-type: size;
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  padding: 50px 30px;
}
/* a lamp over the felt */
.live-stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--room-spot);
  pointer-events: none;
}

/* The table's shape follows the room it is given: long and low where the
   stage is wide and short (a phone on its side), rounder where it is tall (a
   desktop between two panels), so it fills the space instead of leaving a
   band of floor above and below it. */
.live-table {
  --ratio: 1.45;
  position: relative;
  container-type: inline-size;
  width: min(100cqw, calc(100cqh * var(--ratio)));
  aspect-ratio: var(--ratio);
}
.live-table > * { --u: clamp(5px, 1cqw, 12px); }
@container (min-aspect-ratio: 16 / 10) { .live-table { --ratio: 1.6; } }
@container (min-aspect-ratio: 18 / 10) { .live-table { --ratio: 1.8; } }
@container (min-aspect-ratio: 20 / 10) { .live-table { --ratio: 2; } }
@container (min-aspect-ratio: 22 / 10) { .live-table { --ratio: 2.1; } }

/* the shadow the table throws on the floor */
.live-table::before {
  content: "";
  position: absolute;
  inset: 6% -5% -12%;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--room-under, rgba(0,0,0,.7)), rgba(0,0,0,.35) 60%, transparent);
  pointer-events: none;
}

/* The rail: padded leather the colour of caramel, edged in dark wood, with a
   warm line of light where it meets the cloth - the look of a social-casino
   table rather than a card room's. */
.live-rail {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(255,236,196,.55), transparent 55%),
    linear-gradient(180deg, #f2c27e 0%, #d9944a 38%, #b06a2a 72%, #7d4318 100%);
  box-shadow:
    0 0 0 calc(var(--u) * .55) #4a2410,
    0 calc(var(--u) * 2.2) calc(var(--u) * 6) rgba(0,0,0,.7),
    inset 0 calc(var(--u) * .35) calc(var(--u) * .5) rgba(255,246,220,.6),
    inset 0 calc(var(--u) * -.5) calc(var(--u) * 1) rgba(60,24,6,.55);
  pointer-events: none;
}
/* the stitching along the middle of the pad */
.live-rail::after {
  content: "";
  position: absolute;
  inset: calc(var(--u) * 1.5);
  border-radius: 999px;
  border: calc(var(--u) * .16) dashed rgba(90,44,14,.45);
}
.live-felt {
  position: absolute;
  inset: calc(var(--u) * 3.3);
  border-radius: 999px;
  background:
    radial-gradient(70% 80% at 50% 38%, var(--felt-hi, #e0383a) 0%, var(--felt, #b81f25) 48%, var(--felt-lo, #6e0d12) 100%);
  box-shadow:
    inset 0 0 calc(var(--u) * 6) rgba(40,0,4,.75),
    inset 0 calc(var(--u) * 1) calc(var(--u) * 2) rgba(0,0,0,.45);
  pointer-events: none;
}
/* the cloth's grain, barely there */
.live-felt::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: repeating-radial-gradient(circle at 50% 40%, rgba(255,255,255,.018) 0 2px, transparent 2px 4px);
}
/* the glowing edge where the rail meets the cloth */
.live-felt::before {
  content: "";
  position: absolute;
  inset: calc(var(--u) * -.45);
  border-radius: 999px;
  border: calc(var(--u) * .4) solid var(--room-inlay, #ffb257);
  box-shadow: var(--room-inlay-glow, 0 0 calc(var(--u) * 1.4) rgba(255,160,60,.75), inset 0 0 calc(var(--u) * 1) rgba(255,160,60,.5));
}
/* the betting line: a lighter oval printed into the cloth */
.live-betline {
  position: absolute;
  inset: 17% 11%;
  border-radius: 999px;
  border: calc(var(--u) * .22) solid rgba(255,150,130,.28);
  pointer-events: none;
}
.live-mark {
  position: absolute;
  left: 50%; top: 79%;
  transform: translate(-50%, -50%);
  text-align: center;
  white-space: nowrap;
  pointer-events: none;
}
.live-mark b { display: block; font-size: calc(var(--u) * 2.6); font-weight: 900; letter-spacing: .4em; margin-right: -.4em; line-height: 1; color: rgba(255,220,200,.12); }
.live-mark span { font-size: calc(var(--u) * 1.1); font-weight: 700; letter-spacing: .22em; text-transform: uppercase; color: rgba(255,220,200,.15); }

.live-centre {
  position: absolute;
  z-index: 2;
  left: 50%; top: 47%;
  transform: translate(-50%, -50%);
  width: 64%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--u) * 1);
}
.live-pot {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--u) * .7);
  padding: calc(var(--u) * .3) calc(var(--u) * 1.6) calc(var(--u) * .3) calc(var(--u) * .5);
  border-radius: 9em;
  background: rgba(30,6,8,.72);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.08), 0 calc(var(--u) * .3) calc(var(--u) * .8) rgba(0,0,0,.35);
  font-size: calc(var(--u) * 2);
  font-weight: 850;
  color: #fff;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.live-pot small { display: none; }
.live-pot .live-chips { width: calc(var(--u) * 2.3); height: calc(var(--u) * 2.3); }
.live-pot .live-chips i { display: none; }
.live-pot .live-chips i:first-child {
  display: block;
  inset: 0;
  width: auto; height: auto;
  border-radius: 50%;
  background: radial-gradient(circle, #2ec4b6 0 34%, #fff 35% 42%, #1a9e92 43%);
  border: calc(var(--u) * .28) dashed rgba(255,255,255,.9);
  box-shadow: 0 1px 2px rgba(0,0,0,.5);
}

/* a short stack of chips, drawn */
.live-chips { position: relative; flex: none; width: calc(var(--u) * 2.4); height: calc(var(--u) * 2.6); }
.live-chips i {
  position: absolute;
  left: 0;
  width: 100%;
  height: calc(var(--u) * 1.1);
  border-radius: 50%;
  background: linear-gradient(180deg, #ff5a5f, #c81d25);
  border: calc(var(--u) * .18) dashed rgba(255,255,255,.85);
  box-shadow: 0 1px 0 #6a0a0f;
}
.live-chips i:nth-child(1) { bottom: 0; }
.live-chips i:nth-child(2) { bottom: calc(var(--u) * .6); background: linear-gradient(180deg, #3b82f6, #1d4ed8); box-shadow: 0 1px 0 #0b2a6e; }
.live-chips i:nth-child(3) { bottom: calc(var(--u) * 1.2); background: linear-gradient(180deg, #2ec4b6, #138a7f); box-shadow: 0 1px 0 #075049; }

.live-board { display: flex; gap: calc(var(--u) * .6); justify-content: center; }
.live-table .card-face {
  width: calc(var(--u) * 7.4);
  height: calc(var(--u) * 10.4);
  border-radius: calc(var(--u) * .7);
  font-size: calc(var(--u) * 3.8);
  box-shadow: 0 calc(var(--u) * .5) calc(var(--u) * 1.2) rgba(40,0,0,.5);
}
.live-table .card-face .corner { font-size: calc(var(--u) * 2.2); top: calc(var(--u) * .35); left: calc(var(--u) * .55); }
.live-table .card-face .corner.br { top: auto; left: auto; bottom: calc(var(--u) * .35); right: calc(var(--u) * .55); }
.live-table .card-face.wide-rank .corner { font-size: calc(var(--u) * 1.8); }
.live-table .card-face.back { border-width: calc(var(--u) * .22); }
.live-slot {
  width: calc(var(--u) * 7.4);
  height: calc(var(--u) * 10.4);
  border-radius: calc(var(--u) * .7);
  border: calc(var(--u) * .16) solid rgba(255,170,150,.16);
  background: rgba(60,0,6,.18);
}
.live-summary {
  max-width: 100%;
  font-size: calc(var(--u) * 1.6);
  font-weight: 800;
  text-align: center;
  color: #ffe08a;
  text-shadow: 0 2px 8px rgba(0,0,0,.7);
}

/* the winning five, and everything that played no part */
.live-table .card-face.used { box-shadow: 0 0 0 calc(var(--u) * .25) #ffd34d, 0 0 calc(var(--u) * 2) rgba(255,211,77,.7); transform: translateY(calc(var(--u) * -.6)); z-index: 2; }
.live-table .card-face.spare { opacity: .45; filter: saturate(.5) brightness(.85); }

/* ---- waiting for people -------------------------------------------------
   The state a new table spends most of its time in, and the one where a player
   who has just bought in is most likely to decide the game is broken. It sits
   in the middle of the felt where the board would be, because that is where
   they are already looking. */
.live-wait {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .5em;
  max-width: 30em;
  padding: 1em 1.6em;
  border-radius: 1.2em;
  background: rgba(30,4,8,.72);
  border: 1px solid rgba(255,190,160,.18);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  text-align: center;
  font-size: calc(var(--u) * 1.45);
}
.live-wait-title { font-size: 1.15em; font-weight: 800; color: #ffd34d; }
.live-wait-body { font-size: .88em; line-height: 1.55; color: rgba(255,235,225,.8); }
.live-wait-count {
  font-style: normal;
  font-size: .78em;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: rgba(255,220,210,.55);
}

/* three dots that fill in turn - a heartbeat, so the panel does not read as a
   frozen screen */
.live-wait-dots { display: flex; gap: .4em; }
.live-wait-dots i {
  width: .5em; height: .5em;
  border-radius: 50%;
  background: #ffd34d;
  opacity: .25;
  animation: liveWait 1.4s ease-in-out infinite;
}
.live-wait-dots i:nth-child(2) { animation-delay: .18s; }
.live-wait-dots i:nth-child(3) { animation-delay: .36s; }
@keyframes liveWait {
  0%, 60%, 100% { opacity: .25; transform: scale(1); }
  30%           { opacity: 1;   transform: scale(1.25); }
}

/* ---- the dealer -----------------------------------------------------------
   Behind the far rail, top and centre, with only her shoulders and hands
   above it. Sized in the table's own unit like everything else, and placed
   so her hands rest on the rail whatever shape the table is. */
.live-croupier {
  position: absolute;
  z-index: 1;
  left: 50%;
  top: calc(9% - var(--u) * 14);
  width: calc(var(--u) * 15);
  transform: translateX(-50%);
  pointer-events: none;
}
.live-croupier > svg { display: block; width: 100%; height: auto; filter: drop-shadow(0 calc(var(--u) * .6) calc(var(--u) * .8) rgba(0,0,0,.45)); }
.live-croupier.thanking > svg { animation: liveBow 1.1s ease-in-out; transform-origin: 50% 100%; }
@keyframes liveBow {
  0%, 100% { transform: none; }
  30%      { transform: rotate(-3deg) translateY(calc(var(--u) * .3)); }
  60%      { transform: rotate(2deg); }
}
.live-tip {
  position: absolute;
  left: 50%;
  top: calc(100% - var(--u) * .6);
  transform: translateX(-50%);
  pointer-events: auto;
  padding: calc(var(--u) * .25) calc(var(--u) * 1.3);
  border-radius: calc(var(--u) * .6);
  border: calc(var(--u) * .14) solid #8a5a1e;
  background: linear-gradient(180deg, #fff3d6 0%, #f0d29a 55%, #d9b26a 100%);
  color: #4a2a08;
  font-size: calc(var(--u) * 1.35);
  font-weight: 800;
  white-space: nowrap;
  box-shadow: 0 calc(var(--u) * .3) calc(var(--u) * .8) rgba(0,0,0,.45), inset 0 1px 0 #fff;
  cursor: pointer;
}
.live-tip:hover:not(:disabled) { filter: brightness(1.08); }
.live-tip:active:not(:disabled) { transform: translateX(-50%) translateY(1px); }
.live-tip:disabled { opacity: .6; cursor: default; }

/* her thanks, in a bubble over her shoulder */
.live-thanks {
  position: absolute;
  left: 72%;
  top: calc(var(--u) * 1);
  display: flex;
  align-items: center;
  gap: calc(var(--u) * .4);
  padding: calc(var(--u) * .4) calc(var(--u) * 1);
  border-radius: calc(var(--u) * 1.4) calc(var(--u) * 1.4) calc(var(--u) * 1.4) calc(var(--u) * .2);
  background: #fff;
  color: #7a1f3d;
  font-size: calc(var(--u) * 1.35);
  font-weight: 800;
  white-space: nowrap;
  box-shadow: 0 calc(var(--u) * .3) calc(var(--u) * 1) rgba(0,0,0,.4);
  opacity: 0;
  transform: scale(.3);
  transform-origin: 0 100%;
  pointer-events: none;
}
.live-thanks i { font-style: normal; color: #ff3d7f; font-size: 1.2em; }
.live-croupier.thanking .live-thanks { animation: liveThanks 2.8s ease forwards; }
@keyframes liveThanks {
  0%   { opacity: 0; transform: scale(.3); }
  12%  { opacity: 1; transform: scale(1.08); }
  20%  { transform: scale(1); }
  80%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(.9) translateY(calc(var(--u) * -1)); }
}

/* ---- seats ----------------------------------------------------------------
   A seat is a round portrait on the rail, with the name and stack in a small
   plate under it and the cards tucked beside it on the felt side. The seat box
   is exactly the portrait, so RING's x/y is the middle of the face. */
.live-seats, .live-bets, .live-fx { position: absolute; inset: 0; pointer-events: none; }
.live-bets { z-index: 2; }
.live-seats { z-index: 3; }
.live-fx { z-index: 4; }

.live-seat {
  --av: calc(var(--u) * 7.2);
  position: absolute;
  width: var(--av);
  height: var(--av);
  transform: translate(-50%, -50%);
  pointer-events: auto;
}
.live-seat.mine { --av: calc(var(--u) * 8.6); }

.live-pod {
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: 50%;
  padding: calc(var(--u) * .35);
  background: linear-gradient(160deg, #6a4a3a, #24140e);
  box-shadow: 0 calc(var(--u) * .5) calc(var(--u) * 1.4) rgba(0,0,0,.6), inset 0 0 0 calc(var(--u) * .14) rgba(255,220,180,.35);
}
.live-pod .avatar {
  width: 100% !important;
  height: 100% !important;
  border-radius: 50% !important;
  font-size: calc(var(--av) * .42) !important;
}
.live-seat.mine .live-pod { background: linear-gradient(160deg, #ffd88a, #b8741e); }
.live-seat.won .live-pod {
  background: linear-gradient(160deg, #fff2a8, #e0a21a);
  box-shadow: 0 0 calc(var(--u) * 3) rgba(255,214,77,.85), 0 calc(var(--u) * .5) calc(var(--u) * 1.4) rgba(0,0,0,.6);
  animation: liveWinGlow 1.2s ease-in-out infinite;
}
@keyframes liveWinGlow { 50% { box-shadow: 0 0 calc(var(--u) * 4.5) rgba(255,214,77,1), 0 calc(var(--u) * .5) calc(var(--u) * 1.4) rgba(0,0,0,.6); } }
.live-seat.folded .live-pod .avatar { filter: grayscale(.85) brightness(.6); }
.live-seat.away .live-pod, .live-seat.out .live-pod { opacity: .62; }

/* the time left, swept across the face */
.live-sweep {
  position: absolute;
  inset: calc(var(--u) * .35);
  border-radius: 50%;
  display: none;
  pointer-events: none;
  background: conic-gradient(var(--sweep, rgba(76,217,100,.42)) var(--left, 100%), transparent 0);
  mix-blend-mode: screen;
}
.live-seat.acting .live-sweep { display: block; }
.live-pod[data-level="mid"] { --sweep: rgba(255,204,0,.42); --run: #ffcc00; }
.live-pod[data-level="low"] { --sweep: rgba(255,59,48,.48); --run: #ff3b30; }

/* the clock ring, just outside the portrait, emptying from the top */
.live-clock {
  position: absolute;
  inset: calc(var(--u) * -.75);
  width: calc(100% + var(--u) * 1.5);
  height: calc(100% + var(--u) * 1.5);
  overflow: visible;
  transform: rotate(-90deg);
  pointer-events: none;
}
.live-clock circle { fill: none; stroke-width: 6; }
.live-clock-track { stroke: rgba(0,0,0,.45); }
.live-clock-run {
  stroke: var(--run, #4cd964);
  stroke-linecap: round;
  filter: drop-shadow(0 0 3px var(--run, #4cd964));
  transition: stroke .3s ease;
}
.live-seat.mine.acting .live-pod { animation: liveGlow 1.6s ease-in-out infinite; }
@keyframes liveGlow {
  50% { box-shadow: 0 0 0 calc(var(--u) * .5) rgba(255,214,77,.25), 0 0 calc(var(--u) * 4) rgba(255,214,77,.6); }
}

/* the name and stack, in a plate tucked under the portrait */
.live-plate {
  position: absolute;
  z-index: 3;
  left: 50%;
  top: calc(100% - var(--u) * 1);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: calc(var(--av) * 1.25);
  padding: calc(var(--u) * .15) calc(var(--u) * 1);
  border-radius: calc(var(--u) * .7);
  background: rgba(14,6,6,.86);
  box-shadow: 0 calc(var(--u) * .3) calc(var(--u) * .8) rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,210,170,.16);
  line-height: 1.2;
  white-space: nowrap;
  pointer-events: none;
}
.live-plate b { font-size: calc(var(--u) * 1.25); font-weight: 700; color: rgba(255,255,255,.85); max-width: calc(var(--u) * 11); overflow: hidden; text-overflow: ellipsis; }
.live-stack { font-size: calc(var(--u) * 1.5); font-weight: 850; color: #fff; font-variant-numeric: tabular-nums; }
.live-seat.mine .live-stack { color: #ffd34d; }
.live-seat.won .live-plate { box-shadow: 0 0 0 calc(var(--u) * .15) #ffd34d, 0 calc(var(--u) * .3) calc(var(--u) * .8) rgba(0,0,0,.5); }

/* what the seat last did: a bubble over the portrait */
.live-badge {
  position: absolute;
  z-index: 3;
  left: 50%;
  top: calc(var(--u) * -1.4);
  transform: translateX(-50%);
  font-style: normal;
  font-size: calc(var(--u) * 1.15);
  font-weight: 900;
  letter-spacing: .05em;
  text-transform: uppercase;
  line-height: 1.55;
  padding: 0 calc(var(--u) * .8);
  border-radius: 9em;
  background: #3a3f55;
  color: #fff;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0,0,0,.45);
  animation: liveBadge .3s ease-out;
}
@keyframes liveBadge { from { transform: translateX(-50%) scale(.4); opacity: 0; } }
.live-badge.call { background: linear-gradient(180deg, #34c759, #1f8f3c); }
.live-badge.check { background: linear-gradient(180deg, #5b8cff, #3460d6); }
.live-badge.bet, .live-badge.raise { background: linear-gradient(180deg, #ffb340, #e07b00); }
.live-badge.allin { background: linear-gradient(180deg, #ff4d6d, #c1121f); }
.live-badge.fold { background: #4a4a52; color: rgba(255,255,255,.75); }

.live-tag {
  position: absolute;
  z-index: 3;
  right: calc(var(--u) * -1.4);
  bottom: calc(var(--u) * .4);
  font-style: normal;
  font-size: calc(var(--u) * .95);
  font-weight: 900;
  letter-spacing: .08em;
  text-transform: uppercase;
  line-height: 1.7;
  padding: 0 calc(var(--u) * .6);
  border-radius: 9em;
  background: var(--surface-3);
  color: var(--text-dim);
}
.live-tag.house { background: var(--grad); color: #0a0b14; }

/* cards, on the felt side of the portrait */
.live-cards { position: absolute; z-index: 1; display: flex; pointer-events: none; }
.live-seat.c-right .live-cards { left: calc(100% - var(--u) * 1.4); top: 50%; transform: translateY(-62%); }
.live-seat.c-left .live-cards { right: calc(100% - var(--u) * 1.4); top: 50%; transform: translateY(-62%); }
.live-seat.c-down .live-cards { left: 50%; top: calc(100% + var(--u) * 2.9); transform: translateX(-50%); }
.live-seat.c-up .live-cards { left: 50%; bottom: calc(100% - var(--u) * 1); transform: translateX(-50%); }

.live-cards.backs i {
  width: calc(var(--u) * 3);
  height: calc(var(--u) * 4.3);
  border-radius: calc(var(--u) * .4);
  border: calc(var(--u) * .2) solid #fff;
  background:
    radial-gradient(circle at 50% 50%, rgba(255,215,120,.6) 0 calc(var(--u) * .5), transparent calc(var(--u) * .55)),
    repeating-linear-gradient(45deg, #a3162a 0 calc(var(--u) * .4), #7a0f1f calc(var(--u) * .4) calc(var(--u) * .8));
  box-shadow: 0 2px 5px rgba(0,0,0,.45);
}
.live-cards.backs i:first-child { transform: rotate(-8deg); }
.live-cards.backs i + i { margin-left: calc(var(--u) * -1.7); transform: rotate(8deg) translateY(calc(var(--u) * .2)); }
.live-seat.folded .live-cards.backs { opacity: 0; }

.live-cards.shown { gap: calc(var(--u) * .3); }
.live-cards.shown .card-face { width: calc(var(--u) * 5.2); height: calc(var(--u) * 7.4); font-size: calc(var(--u) * 2.7); }
.live-cards.shown .card-face .corner { font-size: calc(var(--u) * 1.55); }

/* your own two, which are the ones you actually have to read */
.live-seat.mine .live-cards { left: calc(100% + var(--u) * .4); transform: translateY(-58%); }
.live-cards.mine .card-face { width: calc(var(--u) * 7.4); height: calc(var(--u) * 10.4); border-radius: calc(var(--u) * .8); font-size: calc(var(--u) * 4); }
.live-cards.mine .card-face .corner { font-size: calc(var(--u) * 2.4); }
.live-cards.mine .card-face:first-child { transform: rotate(-6deg) translateY(calc(var(--u) * .3)); }
.live-cards.mine .card-face + .card-face { margin-left: calc(var(--u) * -2.2); transform: rotate(6deg); }
.live-seat.mine.folded .live-cards { opacity: .45; filter: grayscale(.6); }

.live-made {
  position: absolute;
  z-index: 4;
  left: 50%;
  bottom: calc(100% + var(--u) * 1);
  transform: translateX(-50%);
  font-style: normal;
  font-size: calc(var(--u) * 1.35);
  font-weight: 800;
  white-space: nowrap;
  padding: calc(var(--u) * .15) calc(var(--u) * .9);
  border-radius: 9em;
  background: linear-gradient(180deg, #ffe27a, #e0a21a);
  color: #3a2200;
  box-shadow: 0 2px 8px rgba(0,0,0,.45);
}
.live-seat.c-down .live-made { bottom: auto; top: calc(100% + var(--u) * 11); }
.live-seat.mine .live-made { left: calc(100% + var(--u) * 6); bottom: calc(100% + var(--u) * 2.2); }

/* chips, on the betting line */
.live-bet {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: calc(var(--u) * .4);
  animation: liveBetIn .28s ease-out;
}
@keyframes liveBetIn { from { opacity: 0; transform: translate(-50%, -50%) scale(.6); } }
.live-bet span {
  font-size: calc(var(--u) * 1.45);
  font-weight: 850;
  line-height: 1.6;
  padding: 0 calc(var(--u) * .8);
  border-radius: 9em;
  background: rgba(30,6,8,.75);
  color: #fff;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.live-bet.win span { color: #ffd34d; }

.live-dealer {
  position: absolute;
  transform: translate(-50%, -50%);
  width: calc(var(--u) * 2.3);
  height: calc(var(--u) * 2.3);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #ffffff, #d9dbe6);
  color: #55586a;
  font-style: normal;
  font-size: calc(var(--u) * 1.25);
  font-weight: 900;
  box-shadow: 0 2px 6px rgba(0,0,0,.55), inset 0 0 0 calc(var(--u) * .18) #b9bccb;
}

/* ---- things in flight ----------------------------------------------------- */
.live-fly {
  position: absolute;
  left: var(--tx);
  top: var(--ty);
  transform: translate(-50%, -50%);
  animation-name: liveFly;
  animation-timing-function: cubic-bezier(.25,.7,.35,1);
  animation-fill-mode: both;
  pointer-events: none;
}
@keyframes liveFly {
  from { left: var(--fx); top: var(--fy); opacity: 1; }
  85%  { opacity: 1; }
  to   { left: var(--tx); top: var(--ty); opacity: 0; }
}
.live-fly.card {
  width: calc(var(--u) * 2.8);
  height: calc(var(--u) * 4);
  border-radius: calc(var(--u) * .35);
  border: calc(var(--u) * .18) solid #fff;
  background: repeating-linear-gradient(45deg, #a3162a 0 calc(var(--u) * .4), #7a0f1f calc(var(--u) * .4) calc(var(--u) * .8));
  box-shadow: 0 3px 8px rgba(0,0,0,.5);
  animation-name: liveFly, liveSpin;
}
@keyframes liveSpin { from { rotate: -200deg; } to { rotate: 0deg; } }
.live-fly.chip.big .live-chips { transform: scale(1.5); }

/* ---- an empty chair --------------------------------------------------------- */
.live-seat.empty { --av: calc(var(--u) * 6.4); }
.live-empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: calc(var(--u) * .2) dashed rgba(255,220,190,.35);
  background: rgba(20,6,6,.55);
  color: rgba(255,230,210,.6);
  padding: 0;
}
.live-empty i { font-style: normal; font-size: calc(var(--u) * 3); line-height: 1; font-weight: 300; }
.live-empty span {
  position: absolute;
  left: 50%;
  bottom: calc(var(--u) * -1.3);
  transform: translateX(-50%);
  padding: calc(var(--u) * .1) calc(var(--u) * 1.2);
  border-radius: 9em;
  background: linear-gradient(180deg, #43d36b, #1c8a3c);
  border: calc(var(--u) * .12) solid #b6f5c6;
  color: #fff;
  font-size: calc(var(--u) * 1.3);
  font-weight: 900;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0,0,0,.5);
}
.live-empty:hover:not(:disabled) { border-color: #43d36b; color: #fff; background: rgba(28,138,60,.35); }
.live-empty:disabled { opacity: .55; cursor: default; }

/* ---- along the foot of the table ------------------------------------------ */
.live-banner {
  position: absolute;
  z-index: 5;
  left: 50%;
  bottom: 6px;
  transform: translateX(-50%);
  max-width: 92%;
  font-size: clamp(14px, 2.6vh, 26px);
  font-weight: 900;
  font-stretch: condensed;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 2px 0 rgba(0,0,0,.6), 0 0 14px rgba(0,0,0,.8);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}
.live-sound {
  position: absolute;
  z-index: 5;
  right: 10px;
  bottom: 10px;
  width: 40px; height: 40px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, #4a2a3a, #1d0f17);
  border: 2px solid #c58aa6;
  color: #fff;
  box-shadow: 0 3px 8px rgba(0,0,0,.5);
}
.live-sound.off { color: rgba(255,255,255,.5); border-color: rgba(197,138,166,.5); }

/* ---- the corners of the stage, outside the curve of the table ----------- */
.live-corner {
  position: absolute;
  z-index: 4;
  display: none;
  align-items: center;
  gap: 6px;
  max-width: 45%;
  padding: 4px 10px;
  border-radius: 20px;
  background: rgba(8,10,18,.74);
  border: 1px solid var(--line);
  font-size: 11.5px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.live-corner span { color: var(--gold); font-variant-numeric: tabular-nums; }
.live-corner.tl { top: 8px; left: 8px; }
.live-corner.tr { top: 8px; right: 8px; font-variant-numeric: tabular-nums; }
.live-corner.bl { bottom: 8px; left: 8px; color: var(--text-dim); font-weight: 600; display: none; }

/* ==========================================================================
   The rooms

   Each table has its own floor (see ROOMS in live.js): three carpets and two
   neons. Every room is the same four things - a floor, a lamp over the felt,
   a darkening towards the walls, and the colour of the table's inlay.
   ========================================================================== */
.live-room {
  --room-spot: radial-gradient(ellipse 50% 58% at 50% 52%, rgba(255,214,150,.17), rgba(255,214,150,.05) 45%, transparent 72%);
}
.live-room::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 85% 95% at 50% 50%, transparent 50%, rgba(0,0,0,.72) 100%);
  pointer-events: none;
}

/* Bronze - the classic: burgundy diamonds with a gold line */
.live-room[data-room="carpet-red"] {
  background:
    linear-gradient(rgba(10,4,8,.34), rgba(10,4,8,.34)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='72'%3E%3Crect width='72' height='72' fill='%23380c1d'/%3E%3Cpath d='M36 3 69 36 36 69 3 36Z' fill='none' stroke='%23d9a441' stroke-opacity='.28' stroke-width='2'/%3E%3Cpath d='M36 20 52 36 36 52 20 36Z' fill='%23561531'/%3E%3Cpath d='M36 28 44 36 36 44 28 36Z' fill='%23d9a441' fill-opacity='.3'/%3E%3Ccircle cx='0' cy='0' r='9' fill='%23182c5a' fill-opacity='.8'/%3E%3Ccircle cx='72' cy='0' r='9' fill='%23182c5a' fill-opacity='.8'/%3E%3Ccircle cx='0' cy='72' r='9' fill='%23182c5a' fill-opacity='.8'/%3E%3Ccircle cx='72' cy='72' r='9' fill='%23182c5a' fill-opacity='.8'/%3E%3Ccircle cx='0' cy='0' r='3' fill='%23d9a441' fill-opacity='.45'/%3E%3Ccircle cx='72' cy='0' r='3' fill='%23d9a441' fill-opacity='.45'/%3E%3Ccircle cx='0' cy='72' r='3' fill='%23d9a441' fill-opacity='.45'/%3E%3Ccircle cx='72' cy='72' r='3' fill='%23d9a441' fill-opacity='.45'/%3E%3C/svg%3E") 0 0 / 72px 72px,
    #380c1d;
}

/* Silver - royal blue rosettes with a silver ring */
.live-room[data-room="carpet-blue"] {
  --room-spot: radial-gradient(ellipse 50% 58% at 50% 52%, rgba(220,236,255,.15), rgba(220,236,255,.04) 45%, transparent 72%);
  --room-inlay: rgba(205,222,240,.5);
  background:
    linear-gradient(rgba(4,8,18,.3), rgba(4,8,18,.3)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80'%3E%3Crect width='80' height='80' fill='%230b1936'/%3E%3Ccircle cx='40' cy='40' r='25' fill='none' stroke='%239cc3e6' stroke-opacity='.2' stroke-width='2'/%3E%3Crect x='27' y='27' width='26' height='26' fill='%2316295a'/%3E%3Crect x='27' y='27' width='26' height='26' fill='%2316295a' transform='rotate(45 40 40)'/%3E%3Ccircle cx='40' cy='40' r='9' fill='none' stroke='%23cfe3f5' stroke-opacity='.3' stroke-width='1.5'/%3E%3Ccircle cx='40' cy='40' r='3' fill='%23cfe3f5' fill-opacity='.4'/%3E%3Cpath d='M0 0h14L0 14zM80 0H66l14 14zM0 80h14L0 66zM80 80H66l14-14z' fill='%232aa3b8' fill-opacity='.3'/%3E%3C/svg%3E") 0 0 / 80px 80px,
    #0b1936;
}

/* Gold - emerald art deco fans */
.live-room[data-room="carpet-deco"] {
  --room-inlay: rgba(236,196,104,.65);
  background:
    linear-gradient(rgba(2,12,9,.3), rgba(2,12,9,.3)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60'%3E%3Crect width='60' height='60' fill='%23082a22'/%3E%3Cg fill='none' stroke='%23d8b35a' stroke-opacity='.3' stroke-width='1.6'%3E%3Cpath d='M0 30a30 30 0 0 1 60 0M10 30a20 20 0 0 1 40 0M20 30a10 10 0 0 1 20 0'/%3E%3Cpath d='M-30 60a30 30 0 0 1 60 0M30 60a30 30 0 0 1 60 0M-20 60a20 20 0 0 1 40 0M40 60a20 20 0 0 1 40 0M-10 60a10 10 0 0 1 20 0M50 60a10 10 0 0 1 20 0'/%3E%3C/g%3E%3Cpath d='M25 30a5 5 0 0 1 10 0zM-5 60a5 5 0 0 1 10 0zM55 60a5 5 0 0 1 10 0z' fill='%23d8b35a' fill-opacity='.35'/%3E%3C/svg%3E") 0 0 / 60px 60px,
    #082a22;
}

/* Diamond - ZANA neon, cyan on a floor grid */
.live-room[data-room="neon-cyan"] {
  --room-spot: radial-gradient(ellipse 50% 58% at 50% 52%, rgba(150,220,255,.13), transparent 70%);
  --room-inlay: rgba(34,198,232,.8);
  --room-inlay-glow: 0 0 10px rgba(34,198,232,.55), inset 0 0 8px rgba(34,198,232,.35);
  --room-under: rgba(34,198,232,.3);
  background:
    radial-gradient(900px 620px at 0% 0%, rgba(34,198,232,.26), transparent 70%),
    radial-gradient(900px 620px at 100% 100%, rgba(124,92,255,.26), transparent 70%),
    linear-gradient(rgba(34,198,232,.07) 1px, transparent 1px) 0 0 / 44px 44px,
    linear-gradient(90deg, rgba(34,198,232,.07) 1px, transparent 1px) 0 0 / 44px 44px,
    #050a1a;
}

/* Ultimate - ZANA neon, violet and magenta */
.live-room[data-room="neon-violet"] {
  --room-spot: radial-gradient(ellipse 50% 58% at 50% 52%, rgba(232,180,255,.13), transparent 70%);
  --room-inlay: rgba(232,121,249,.8);
  --room-inlay-glow: 0 0 12px rgba(232,121,249,.55), inset 0 0 8px rgba(124,92,255,.4);
  --room-under: rgba(168,85,247,.35);
  background:
    radial-gradient(900px 620px at 100% 0%, rgba(232,121,249,.24), transparent 70%),
    radial-gradient(900px 620px at 0% 100%, rgba(124,92,255,.32), transparent 70%),
    repeating-linear-gradient(135deg, rgba(232,121,249,.06) 0 1px, transparent 1px 22px),
    repeating-linear-gradient(45deg, rgba(124,92,255,.05) 0 1px, transparent 1px 22px),
    #0c0618;
}

@media (prefers-reduced-motion: reduce) {
  .live-wait-dots i { animation: none; opacity: .7; }
  .live-seat.mine.acting .live-pod, .live-seat.won .live-pod, .live-croupier.thanking > svg { animation: none; }
  .live-fx { display: none; }
}

.live-buyin { width: 100%; }
.live-buyin-quick { display: flex; gap: 8px; margin-top: 10px; }
.live-buyin-quick button {
  flex: 1;
  padding: 8px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  font-weight: 650;
  font-size: 13px;
}
.live-buyin-quick button:hover:not(:disabled) { color: var(--gold); border-color: var(--gold); }
.live-buyin-quick button:disabled { opacity: .45; cursor: default; }

/* ---- the sheet -----------------------------------------------------------
   Every dialog the table needs, inside the room.

   The app opens its dialogs on a layer at z-index 200. The room is at 300, so
   a dialog opened that way renders *underneath* the felt: invisible, and still
   swallowing every tap - which is why choosing a buy-in used to mean leaving
   the table. This is a child of the room instead, so it is always on top of
   it, and it works the same in full screen and out of it. */
.live-sheet {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 10px;
  background: rgba(4, 5, 10, .68);
  backdrop-filter: blur(6px);
  animation: fade .16s ease;
}
.live-sheet.hidden { display: none; }

.live-sheet-card {
  width: min(100%, 460px);
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 16px 18px 18px;
  border-radius: 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 -10px 44px rgba(0, 0, 0, .6);
  animation: liveSheetUp .2s cubic-bezier(.2, .9, .3, 1);
}
@keyframes liveSheetUp { from { transform: translateY(16px); opacity: 0; } to { transform: none; opacity: 1; } }

.live-sheet-head { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 12px; }
.live-sheet-titles { flex: 1; min-width: 0; }
.live-sheet-head h2 { margin: 0; font-size: 17px; font-weight: 800; }
.live-sheet-head p { margin: 3px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-dim); }
.live-sheet-back, .live-sheet-x {
  flex: none;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
}
.live-sheet-back:hover, .live-sheet-x:hover { color: var(--text); border-color: var(--violet); }
.live-sheet-note { margin: 12px 0 0; font-size: 12px; line-height: 1.55; color: var(--text-mute); }
.live-sheet-warn { margin: 6px 0 14px; font-size: 13.5px; line-height: 1.55; color: var(--warn); }

/* ---- the ladder ---------------------------------------------------------- */
.live-rungs { display: flex; flex-direction: column; gap: 8px; }
.live-rung {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 11px 13px;
  border-radius: 13px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  text-align: start;
  transition: border-color .14s ease, transform .14s ease;
}
.live-rung:hover:not(:disabled) { border-color: var(--gold); transform: translateY(-1px); }
.live-rung.on { border-color: var(--win); background: rgba(61, 220, 151, .12); }
.live-rung:disabled { opacity: .45; cursor: default; }

/* A chip in the rung's own metal, so the ladder reads as a ladder at a glance
   rather than as five identical rows with different numbers on them. */
.live-rung-mark {
  flex: none;
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, .22);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .25);
}
.live-rung-mark[data-rung="bronze"]   { background: linear-gradient(140deg, #d6975a, #8a5423); }
.live-rung-mark[data-rung="silver"]   { background: linear-gradient(140deg, #dfe6f0, #92a0b5); }
.live-rung-mark[data-rung="gold"]     { background: linear-gradient(140deg, #ffd977, #d79412); }
.live-rung-mark[data-rung="diamond"]  { background: linear-gradient(140deg, #9fe9ff, #2b8fd0); }
.live-rung-mark[data-rung="ultimate"] { background: linear-gradient(140deg, #c79bff, #6d3ddd); }

.live-rung-main { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
.live-rung-main b { font-size: 14.5px; font-weight: 800; }
.live-rung-main span { font-size: 11.5px; color: var(--gold); font-variant-numeric: tabular-nums; }
.live-rung-side { flex: none; display: flex; flex-direction: column; align-items: flex-end; line-height: 1.3; }
.live-rung-buyin { font-size: 11.5px; color: var(--text-dim); font-variant-numeric: tabular-nums; white-space: nowrap; }
.live-rung-people { font-size: 10.5px; color: var(--text-mute); white-space: nowrap; }
.live-rung.on .live-rung-people { color: var(--win); font-weight: 700; }

/* ---- choosing an amount --------------------------------------------------
   The number is the point of this screen, so it is the biggest thing on it and
   the slider is a plain track underneath. */
.live-amount-row {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 9px;
  margin: 6px 0 10px;
}
.live-amount {
  font-size: 34px;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.live-depth { font-size: 12px; color: var(--text-mute); }

.live-buyin-range { width: 100%; accent-color: var(--gold); height: 26px; }
.live-range-ends {
  display: flex;
  justify-content: space-between;
  font-size: 11.5px;
  color: var(--text-mute);
  font-variant-numeric: tabular-nums;
  margin-top: -2px;
}
.live-quick { display: flex; gap: 8px; margin-top: 12px; }
.live-quick button {
  flex: 1;
  padding: 9px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 12.5px;
  font-weight: 700;
}
.live-quick button:hover { color: var(--gold); border-color: var(--gold); }

/* ---- the ladder on the page underneath ---------------------------------- */
.live-ladder-mini {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: min(100%, 420px);
  margin-top: 4px;
}
.live-ladder-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 12px;
  padding: 9px 12px;
  border-radius: 11px;
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  text-align: start;
}
.live-ladder-row.on { border-color: var(--win); }
.live-ladder-row b { font-size: 13px; font-weight: 750; }
.live-ladder-row span { font-size: 11.5px; color: var(--gold); text-align: end; font-variant-numeric: tabular-nums; }
.live-ladder-row i { font-style: normal; font-size: 11px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.live-ladder-row u { text-decoration: none; font-size: 11px; color: var(--text-mute); text-align: end; }

/* On a phone in landscape the sheet has almost no height to work with, so it
   stops being a sheet and becomes a panel that fills what there is. */
@media (orientation: landscape) and (max-height: 460px) {
  .live-sheet { align-items: stretch; padding: 6px; }
  .live-sheet-card { width: min(100%, 560px); margin: auto; padding: 12px 14px 14px; border-radius: 14px; }
  .live-sheet-head { margin-bottom: 8px; }
  .live-sheet-head h2 { font-size: 15px; }
  .live-sheet-head p { font-size: 11.5px; }
  .live-rung { padding: 8px 11px; gap: 9px; }
  .live-rung-mark { width: 24px; height: 24px; border-width: 2px; }
  .live-amount { font-size: 27px; }
  .live-amount-row { margin: 2px 0 6px; }
  .live-sheet-note { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .live-sheet-card { animation: none; }
}

/* ---- turn the phone ------------------------------------------------------
   The table is 16:9. A phone held upright gives it a third of the width it
   needs, and shrinking it to fit makes every seat a smear - so the room asks
   to be turned instead. Only on a small screen: a narrow desktop window is
   still perfectly readable and should not be told to rotate a monitor. */
.live-rotate { display: none; }

@media (orientation: portrait) and (max-width: 900px) {
  .live-rotate {
    position: absolute;
    inset: 0;
    z-index: 4;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 18px;
    padding: 30px;
    text-align: center;
    background: var(--bg);
    color: var(--text-dim);
  }
  .live-rotate svg { color: var(--gold); animation: liveTurn 2.4s ease-in-out infinite; }
  .live-rotate h2 { margin: 0; font-size: 19px; color: var(--text); }
  .live-rotate p { margin: 0; font-size: 13.5px; max-width: 32ch; }
  .live-body { display: none; }
}

@keyframes liveTurn {
  0%, 42%   { transform: rotate(0deg); }
  58%, 100% { transform: rotate(-90deg); }
}

/* ---- tablets and small laptops -------------------------------------------
   Not enough width for both panels open. The left one folds into a rail of
   buttons that open the sheet, and the actions stack up in a column so the
   biggest button is the one nearest the thumb. */
@media (max-width: 1279px) {
  .live-main { grid-template-columns: 72px minmax(0, 1fr) 250px; }
  .live-side.left { padding: 10px 7px; }
  .live-side.left > .live-card, .live-side.left > .live-seat-controls { display: none; }
  .live-railnav { display: flex; }
  .live-side.right { padding: 12px; }
  .live-session { display: none; }
  .live-stage { padding: 54px 22px; }
  .live-corner.bl:not(:empty) { display: block; }

  .live-buttons { grid-auto-flow: row; }
  .live-act.raise { order: -2; }
  .live-act.call, .live-act.check { order: -1; }
  .live-act { min-height: 54px; font-size: 15px; }
}

/* ---- a phone on its side ---------------------------------------------------
   Height is what there is least of, so there is no top bar and no bottom bar:
   a thin column of buttons on the left, the actions down the right, and the
   table's name and the balance in the corners the curve of the table leaves
   empty. */
@media (orientation: landscape) and (max-height: 460px) {
  .live-top { display: none; }
  .live-main { grid-template-columns: 50px minmax(0, 1fr) 136px; }

  .live-side { gap: 6px; }
  .live-side.left { padding: 6px 4px; }
  .live-railnav { gap: 2px; }
  .live-rail-btn { width: 40px; padding: 7px 0; }
  .live-rail-btn span { display: none; }
  .live-rail-btn.phone-only { display: flex; }

  .live-side.right { padding: 7px 7px 8px; }
  .live-spot { display: none; }
  .live-dock { background: none; border: 0; padding: 0; gap: 6px; flex: 1; }
  .live-side.right > .live-grow { display: none; }
  .live-status { font-size: 10.5px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .live-turn-secs { font-size: 10.5px; }
  .live-turnbar { height: 4px; }
  .live-dock > .live-chip-btn { padding: 10px 6px; font-size: 13px; }

  .live-actions { flex: 1; justify-content: flex-end; gap: 6px; }
  .live-raise { gap: 5px; }
  .live-sizes { grid-template-columns: 1fr 1fr; gap: 4px; }
  .live-sizes button { padding: 4px 0; font-size: 11px; }
  .live-slider-row { display: none; }
  .live-stepper { display: grid; }
  .live-buttons { gap: 6px; }
  .live-act { min-height: 44px; padding: 6px; font-size: 13.5px; border-radius: 11px; }
  .live-act.fold { min-height: 38px; }

  /* the dealer stands above the far rail, so the top keeps room for her head */
  .live-stage { padding: 44px 8px 20px; }
  .live-corner.tl, .live-corner.tr { display: flex; }
  .live-corner { font-size: 10.5px; padding: 3px 8px; }
  .live-corner.tl { top: 5px; left: 5px; }
  .live-corner.tr { top: 5px; right: 5px; }
  .live-corner.bl { bottom: 5px; left: 5px; }
}

@media (prefers-reduced-motion: reduce) {
  .live-rotate svg { animation: none; }
}

/* the top bar carries the player's own picture, so the button is the picture */
.icon-btn.avatar-btn { padding: 0; overflow: hidden; }
.icon-btn.avatar-btn .avatar { border-radius: 8px !important; }

/* ---- the terms ---------------------------------------------------------- */
.terms-page { max-width: 780px; }
.terms-banner { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 16px 0 24px; }
.terms-banner .btn { flex: none; }
.terms-clause { margin-top: 26px; }
.terms-clause h2 {
  display: flex;
  align-items: baseline;
  gap: 11px;
  font-size: 16.5px;
  margin: 0 0 10px;
}
.terms-clause h2 i {
  font-style: normal;
  flex: none;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 8px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 12.5px;
  font-weight: 800;
  color: var(--text-dim);
}
.terms-clause p {
  margin: 0 0 11px;
  font-size: 14px;
  line-height: 1.68;
  color: var(--text-dim);
}
.terms-clause .table-wrap { margin: 4px 0 14px; }
.terms-edge { margin: 4px 0 14px; }
.terms-foot { margin-top: 32px; font-size: 13px; }

/* ---- Back Games ---------------------------------------------------------- */
.bg-card { margin-bottom: 18px; }
.bg-card h2 { margin: 0 0 4px; font-size: 16px; }
.bg-note { margin: 0 0 14px; font-size: 12.5px; line-height: 1.55; }
.bg-warn { margin: 14px 0; }

.bg-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 0;
  border-top: 1px solid var(--line-soft);
}
.bg-row:first-of-type { border-top: none; }
.bg-label { flex: 0 0 210px; font-size: 13.5px; font-weight: 650; }
.bg-control { flex: 1; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bg-control .dim { font-size: 12px; }

.bg-num {
  width: 92px;
  padding: 7px 10px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}
.bg-range { width: 190px; accent-color: var(--gold); }
.bg-peek-val { min-width: 46px; font-variant-numeric: tabular-nums; color: var(--gold); }

.bg-tables { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.bg-table {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 9px 12px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  font-size: 12.5px;
}
.bg-table b { flex: 0 0 90px; font-size: 13px; }
.bg-table .btn { margin-inline-start: auto; }

.bg-games td { vertical-align: middle; }
.bg-state { margin-top: 3px; }
.bg-chip {
  display: inline-block;
  font-style: normal;
  font-size: 10.5px;
  font-weight: 750;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 20px;
  background: var(--surface-3);
  color: var(--text-mute);
}
.bg-chip.paused { background: rgba(255,176,32,.18); color: var(--warn); }
.bg-chip.forced { background: rgba(61,220,151,.18); color: var(--win); }
.bg-forced-cell { display: flex; align-items: center; gap: 7px; }
.bg-forced-cell .bg-num { width: 78px; }
.bg-who { font-size: 12px; }
tr.bg-paused { background: rgba(255,176,32,.06); }
tr.bg-forced { background: rgba(61,220,151,.06); }


@media (max-width: 720px) {
  .bg-label { flex: 1 1 100%; }
  .bg-row { padding: 12px 0; }
}

/* ---- the operator's winning-streak switch, above a game ------------------
   A strip, not a card. It sits between the game's title and its board, and
   every pixel it takes is a pixel of board on a phone - so it is one row, the
   badge is the only decoration, and what it does is in the tooltip and on the
   Back Games screen rather than in a paragraph here. */
.wm-bar {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  padding: 4px 6px 4px 8px;
  border-radius: 20px;
  background: var(--surface-2);
  border: 1px dashed var(--line);
}
.wm-bar.on { border-style: solid; border-color: var(--gold); background: rgba(255,176,32,.1); }
.wm-mark {
  flex: none; font-style: normal; font-size: 9px; font-weight: 850;
  letter-spacing: .09em; padding: 2px 7px; border-radius: 20px;
  background: var(--grad); color: #0a0b14;
}
.wm-btn {
  padding: 4px 12px;
  border-radius: 20px;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}
.wm-btn:hover { color: var(--text); border-color: var(--violet); }
.wm-btn.on { background: var(--grad-gold); border-color: transparent; color: #2b1c00; }
