:root {
  --bg: #0e1420;
  --bg-2: #172033;
  --panel: #1a2436;
  --panel-2: #212d43;
  --tile: #2c3a54;
  --tile-hover: #35476a;
  --tile-edge: #3b4f74;
  --text: #e6ecf7;
  --text-dim: #8c9bb5;
  --gem: #23d18b;
  --gem-bg: #12352b;
  --mine: #ff5c5c;
  --mine-bg: #3a1b22;
  --gold: #ffc44d;
  --accent: #3d8bff;
  --radius: 10px;
  --tile-gap: clamp(5px, 1.4vw, 9px);
}

* { box-sizing: border-box; }

/* A class rule with display: flex outranks the user agent's [hidden] rule, so
   state the override explicitly or every "hidden" panel renders. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
}

.sprite { display: none; }

/* ---------- top bar ---------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px clamp(12px, 3vw, 28px);
  background: var(--bg-2);
  border-bottom: 1px solid #223049;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: .3px;
  color: var(--text);
  text-decoration: none;
}

a.brand:hover { color: var(--gem); }

.user-email {
  font-size: 13px;
  color: var(--text-dim);
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.brand-icon { width: 24px; height: 24px; color: var(--gem); }

.topbar-right { display: flex; align-items: center; gap: 12px; }

.balance {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.25;
}

.balance-label { font-size: 11px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .6px; }
.balance-value { font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; }

/* ---------- layout ---------- */
.layout {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr) 240px;
  gap: clamp(12px, 2vw, 22px);
  align-items: start;
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(14px, 3vw, 26px) clamp(12px, 3vw, 28px) 40px;
}

.panel {
  background: var(--panel);
  border: 1px solid #253350;
  border-radius: 14px;
  padding: 16px;
}

/* ---------- controls ---------- */
.field { margin-bottom: 14px; }

.field label {
  display: block;
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 6px;
  text-transform: uppercase;
  letter-spacing: .5px;
}

.input-row { display: flex; gap: 6px; }

input[type="text"], select {
  flex: 1;
  min-width: 0;
  height: 40px;
  padding: 0 12px;
  background: var(--bg);
  border: 1px solid #2f3f5e;
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
  font-variant-numeric: tabular-nums;
}

input[type="text"]:focus-visible, select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* A select outside an .input-row is a plain block child, so `flex: 1` above
   does nothing and the control takes its intrinsic width - the widest option.
   One long label then pushes it past the panel edge. */
.field > select { width: 100%; }

input[readonly] { color: var(--text-dim); font-size: 12px; }

.chip {
  height: 40px;
  min-width: 42px;
  padding: 0 10px;
  background: var(--panel-2);
  border: 1px solid #33456a;
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

.chip:hover { background: #2a3956; }

.stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin: 16px 0;
}

.stat {
  background: var(--bg);
  border-radius: var(--radius);
  padding: 9px 11px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.stat-wide { grid-column: 1 / -1; }
.stat-label { font-size: 11px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .5px; }
.stat-value { font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums; }
.stat-value.accent { color: var(--gold); }

/* Payout has stopped tracking the multiplier because the max win clamped it. */
.stat-value.capped { color: var(--gem); }
.stat-value.capped::after {
  content: " max win";
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .5px;
}

.primary-btn {
  position: relative;
  width: 100%;
  height: 48px;
  background: var(--gem);
  border: none;
  border-radius: var(--radius);
  color: #06231a;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: transform .08s ease, filter .15s ease;
}

/* ---------------------------------------------------------------------------
   Rewards hidden in the board
   --------------------------------------------------------------------------- */

/* The golden frame. It says a crystal is somewhere in this board and nothing
   more - never which cell, because naming one would name a safe one.

   Deliberately not the flat --gold of the cash-out button: that button is an
   action, this is a state, and the two share a screen. A ring and a glow read
   as an atmosphere rather than as something to press. */
.board-wrap.rewarded::after {
  content: '';
  position: absolute;
  inset: -6px;
  border-radius: calc(var(--radius) + 6px);
  border: 2px solid rgb(226 178 58 / .85);
  box-shadow:
    0 0 0 1px rgb(226 178 58 / .25),
    0 0 22px rgb(226 178 58 / .35),
    inset 0 0 26px rgb(226 178 58 / .12);
  pointer-events: none;
  animation: rewarded-in .5s ease both;
}

@keyframes rewarded-in {
  from { opacity: 0; transform: scale(1.03); }
  to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .board-wrap.rewarded::after { animation: none; }
}

/* A tile holding a crystal. `taken` is one the player opened and walked away
   with; without it the tile is where the crystal turned out to be, shown when
   the round is over and there is nothing left to give away. */
.tile.reward .face-back,
.shaft-tile.reward .face-back { color: var(--reward, #e2b23a); }

.tile.reward,
.shaft-tile.reward {
  box-shadow: inset 0 0 0 2px rgb(226 178 58 / .55);
}

.tile.reward.taken,
.shaft-tile.reward.taken {
  box-shadow:
    inset 0 0 0 2px rgb(226 178 58 / .9),
    0 0 16px rgb(226 178 58 / .45);
}

/* "This game hides crystals", on a lobby card. Three coloured markers and the
   word beside them: legible without hovering, because hover does not exist on
   a phone. Deliberately no drop rates - a published number is a claim a player
   can check, and this one is not settled yet. */
/* Its own row at the foot of the card, outside the link. */
.game-rewards {
  position: relative;
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 10px 16px 12px;
  border-top: 1px solid rgb(255 255 255 / .05);
}

/* The detail, behind a button rather than a hover: hover does not exist on a
   phone, and an explanation half the audience cannot reach explains nothing. */
.reward-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: auto;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
}

.reward-info svg { width: 15px; height: 15px; }
.reward-info:hover { color: var(--text); }
.reward-info:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.reward-tip {
  position: absolute;
  right: 12px;
  bottom: calc(100% - 4px);
  z-index: 5;
  width: min(280px, calc(100vw - 48px));
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel-2);
  box-shadow: 0 12px 30px rgb(0 0 0 / .5);
  font-size: 12px;
  line-height: 1.55;
  color: var(--text-dim);
  text-align: left;
  cursor: default;
}

.reward-pip {
  display: inline-flex;
  width: 13px;
  height: 13px;
  color: var(--reward, #e2b23a);
}

.reward-pip svg { width: 100%; height: 100%; }

.game-rewards-label {
  margin-left: 5px;
  font-size: 11px;
  letter-spacing: .3px;
  color: var(--text-dim);
}

/* The inventory on the account page: its own card, across the width of the
   grid. It used to sit inside the balance card and crowded it, and the two are
   different subjects anyway - that card is money, this is the things dug out of
   the boards. */
.acc-inventory {
  grid-column: 1 / -1;
}

.acc-inventory .bonus-head { margin-bottom: 2px; }
.acc-inventory .bonus-head h2 { margin: 0; }

/* One tile per crystal, not a line per tier. They are not interchangeable:
   each is worth a multiple of the stake of the round it came out of, so
   thirteen rubies are thirteen different amounts and a count describes none of
   them. */
.crystals {
  list-style: none;
  margin: 12px 0 10px;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}

.crystal {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  width: 84px;
}

/* Sized to the profile avatar, and framed in the tier's colour - the frame is
   what says how rare it is. */
.crystal-badge {
  display: grid;
  place-items: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  border: 2px solid var(--reward, #e2b23a);
  background:
    radial-gradient(circle at 50% 35%, rgb(255 255 255 / .06), transparent 60%),
    var(--panel-2);
  box-shadow: 0 0 0 1px rgb(0 0 0 / .35), 0 0 14px -4px var(--reward, #e2b23a);
}

.crystal-icon {
  width: 34px;
  height: 34px;
  color: var(--reward, #e2b23a);
}

.crystal-value {
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* A frame colour on its own is a rarity some players cannot read, so the name
   travels under it. */
.crystal-name {
  font-size: 11px;
  letter-spacing: .3px;
  color: var(--text-dim);
}

/* The tail of a long grind, when there are more than the grid lists. */
.crystal-more {
  justify-content: center;
  height: 72px;
  font-size: 12px;
  color: var(--text-dim);
}

.fund-btn.convert {
  width: 100%;
  margin-top: 4px;
}

@media (min-width: 720px) {
  .fund-btn.convert {
    width: auto;
    min-width: 220px;
  }
}

/* The boost, said out loud. A player can measure their own find rate from the
   revealed seeds, so an unannounced one would eventually read as a rigged
   game - and a fair one is worth saying anyway. */
.boost-note {
  margin: 0 0 8px;
  font-size: 12px;
  color: var(--gold);
}

/* Debug mode: the tile a crystal is on, pointed at before it is opened.
   An outline and nothing else, so a tester never reads "it is here" as "you
   have it" - the collected marker is a filled crystal and this must not look
   like one. */
.tile.reward.hinted .face-back,
.shaft-tile.reward.hinted .face-back { color: transparent; }

.tile.reward.hinted,
.shaft-tile.reward.hinted {
  box-shadow: inset 0 0 0 2px var(--reward, #e2b23a);
  opacity: .85;
}

/* And the board says the mode is on, because a raised find rate read as the
   real one is the whole risk of leaving it switched on. */
.board-wrap.debug-rewards::before {
  content: 'DEBUG: crystals shown';
  position: absolute;
  top: -10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--gold);
  color: #2b1d00;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .6px;
  white-space: nowrap;
  pointer-events: none;
}

/* Tier colours. Never the only signal - the name travels with the crystal
   everywhere it is shown. */
.tier-ruby     { --reward: #e2585f; }
.tier-sapphire { --reward: #5b8cf0; }
.tier-diamond  { --reward: #6fe3e1; }

.primary-btn:hover { filter: brightness(1.08); }
.primary-btn:active { transform: scale(.985); }
/* The dip a click gives the button, borrowed by the Space shortcut - a key
   press moves nothing on screen otherwise. */
.primary-btn.keyed { transform: scale(.985); filter: brightness(1.08); }
.primary-btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }
.primary-btn.cashout { background: var(--gold); color: #2b1d00; }

/* The label is its own element so the game can rewrite the caption - "Cash out
   $2.18", "Revealing…" - without wiping the key hint beside it. */
.btn-label { display: block; }

/* Taken out of the flow so the caption stays optically centred in the button
   whatever length it grows to. Hidden by default and shown only where a
   keyboard is a given: see below. */
.btn-key {
  display: none;
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  padding: 2px 7px;
  border-radius: 5px;
  background: rgb(0 0 0 / .16);
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .3px;
  line-height: 1.5;
  opacity: .72;
  pointer-events: none;
}

.primary-btn:disabled .btn-key { opacity: .5; }

/* Same query as DESKTOP in js/hotkey.js. A hint for a key that does nothing,
   or a key nothing hints at, are both worse than neither - so the two are
   written to be checked against each other. */
@media (hover: hover) and (pointer: fine) {
  .btn-key { display: block; }
}

.ghost-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  padding: 0 14px;
  background: transparent;
  border: 1px solid #33456a;
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

.ghost-btn:hover { background: var(--panel-2); }

.icon-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  background: transparent;
  border: 1px solid #33456a;
  border-radius: var(--radius);
  color: var(--gem);
  cursor: pointer;
}

.icon-toggle:hover { background: var(--panel-2); }
.icon-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.icon-toggle svg { width: 19px; height: 19px; }
.icon-toggle .ic-off { display: none; }
.icon-toggle.off { color: var(--text-dim); }
.icon-toggle.off .ic-on { display: none; }
.icon-toggle.off .ic-off { display: block; }
.ghost-btn.wide { width: 100%; justify-content: center; margin-bottom: 14px; }
.btn-icon { width: 16px; height: 16px; }

.hint { margin: 12px 0 0; font-size: 12px; color: var(--text-dim); min-height: 30px; line-height: 1.5; }
.hint.warn { color: var(--mine); }

/* ---------- board ---------- */
.board-section { display: flex; justify-content: center; }

.board-wrap {
  position: relative;
  width: 100%;
  max-width: 520px;
  aspect-ratio: 1;
}

.board {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-template-rows: repeat(5, 1fr);
  gap: var(--tile-gap);
  width: 100%;
  height: 100%;
}

/* The particle layer sits above the grid and never intercepts input, so the
   DOM tiles keep all hit testing, focus and keyboard behaviour. */
.fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 3;
}

.tile {
  position: relative;
  padding: 0;
  border: none;
  background: none;
  perspective: 700px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.tile:disabled { cursor: default; }

/* Absolute rather than width/height: 100%. The inner element is a <span>, and
   percentage sizing does not apply to inline boxes; inset: 0 against the
   positioned button gives it a definite size in every browser. */
.tile-inner {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform .4s cubic-bezier(.2, .85, .3, 1);
}

.tile.open .tile-inner { transform: rotateY(180deg); }

/* Only transform and opacity are animated, so every reveal stays on the
   compositor and holds 60fps on cheap phones. */
.face {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.face-front {
  background: var(--tile);
  border-bottom: 3px solid #1f2b41;
  transition: background .15s ease, transform .1s ease;
}

.tile:not(:disabled):hover .face-front { background: var(--tile-hover); }
.tile:not(:disabled):active .face-front { transform: translateY(2px); }
.tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius); }

.face-back {
  transform: rotateY(180deg);
  background: var(--gem-bg);
  color: var(--gem);
}

.tile.mine .face-back { background: var(--mine-bg); color: var(--mine); }

/* Mines revealed after the round ends stay muted, so the tile the player
   actually hit reads as the one that mattered. */
.tile.cold .face-back { background: #202b40; color: #5d6a83; }
.tile.dim .face-back { opacity: .55; }

.face-back svg { width: 48%; height: 48%; }

.tile.pop .tile-inner { animation: pop .32s ease-out; }

@keyframes pop {
  0% { transform: rotateY(180deg) scale(1); }
  45% { transform: rotateY(180deg) scale(1.14); }
  100% { transform: rotateY(180deg) scale(1); }
}

.board-wrap.shake { animation: shake .38s ease-out; }

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-8px); }
  40% { transform: translateX(7px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(3px); }
}

@media (prefers-reduced-motion: reduce) {
  .tile-inner { transition: none; }
  .tile.pop .tile-inner, .board-wrap.shake { animation: none; }
}

/* ---------- digger shaft ---------- */
/* The shaft is as tall as the rows it shows, not square like the Mines grid. */
.board-wrap-shaft {
  aspect-ratio: auto;
  --row-h: clamp(46px, 12vw, 72px);
  --rail-w: clamp(62px, 17vw, 92px);
  /* One row plus the gap under it. Every slide is a whole number of these, so
     the window always lands on a row boundary. */
  --row-step: calc(var(--row-h) + var(--tile-gap));
}

.shaft {
  position: relative;
  height: calc(var(--visible-rows, 6) * var(--row-step));
  overflow: hidden;

  /* The rock fades out where the shaft continues past the window, which is what
     sells it as deeper than what is on screen. An edge with nothing beyond it
     gets no fade: at the surface the first row is fully lit, and at the floor
     so is the last. A fade there would only shade the row the player is
     looking at. The two ends are switched by classes from shaft.js. */
  --fade-top: 0%;
  --fade-bottom: 100%;
  -webkit-mask-image: linear-gradient(
    180deg, transparent 0, #000 var(--fade-top), #000 var(--fade-bottom), transparent 100%
  );
  mask-image: linear-gradient(
    180deg, transparent 0, #000 var(--fade-top), #000 var(--fade-bottom), transparent 100%
  );
}

.shaft.has-rock-above { --fade-top: 7%; }
.shaft.has-rock-below { --fade-bottom: 93%; }

.shaft-track {
  display: flex;
  flex-direction: column;
  transition: transform .45s cubic-bezier(.2, .85, .3, 1);
  will-change: transform;
}

.shaft-row {
  display: grid;
  grid-template-columns: var(--rail-w) repeat(var(--shaft-columns, 3), 1fr);
  gap: var(--tile-gap);
  height: var(--row-h);
  margin-bottom: var(--tile-gap);
  flex: none;
  opacity: .4;
  transition: opacity .3s ease;
}

.shaft-row.is-current,
.shaft-row.is-revealed { opacity: 1; }
.shaft-row.is-cleared { opacity: .72; }
/* Rock the player has not reached. Stated rather than left to the default, so
   changing how an unbuilt row looks cannot silently change this one. */
.shaft-row.is-locked { opacity: .4; }

.row-rail {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
  padding-right: 4px;
  line-height: 1.15;
  text-align: right;
}

.row-mult {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: clamp(12px, 3.2vw, 15px);
  color: var(--text-dim);
}

.row-pay {
  font-variant-numeric: tabular-nums;
  font-size: clamp(10px, 2.6vw, 12px);
  color: var(--text-dim);
  opacity: .75;
}

/* The row being dug is the only one the eye should go to. */
.shaft-row.is-current .row-mult { color: var(--gem); }
.shaft-row.is-current .row-pay { color: var(--text); opacity: 1; }
.shaft-row.is-cleared .row-mult { color: var(--text); }

.shaft-tile {
  position: relative;
  padding: 0;
  border: none;
  background: none;
  perspective: 700px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.shaft-tile:disabled { cursor: default; }

.shaft-tile .tile-inner {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform .4s cubic-bezier(.2, .85, .3, 1);
}

.shaft-tile.open .tile-inner { transform: rotateY(180deg); }

.shaft-tile .face-front {
  background: var(--tile);
  border-bottom: 3px solid #1f2b41;
  transition: background .15s ease, transform .1s ease;
}

.shaft-tile:not(:disabled):hover .face-front { background: var(--tile-hover); }
.shaft-tile:not(:disabled):active .face-front { transform: translateY(2px); }
.shaft-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius); }

.shaft-tile .face-back {
  transform: rotateY(180deg);
  background: var(--gem-bg);
  color: var(--gem);
}

.shaft-tile.charge .face-back { background: var(--mine-bg); color: var(--mine); }
.shaft-tile.cold .face-back { background: #202b40; color: #5d6a83; }
.shaft-tile .face-back svg { width: 48%; height: 48%; }

.shaft-tile.pop .tile-inner { animation: pop .32s ease-out; }

/* A faint pulse on the live row, so on a phone it is obvious which row takes
   the next pick without having to compare opacities. */
.shaft-row.is-current .shaft-tile:not(.open) .face-front {
  box-shadow: inset 0 0 0 1.5px var(--tile-edge);
}

@media (prefers-reduced-motion: reduce) {
  .shaft-track { transition: none; }
  .shaft-tile .tile-inner { transition: none; }
  .shaft-tile.pop .tile-inner { animation: none; }
}

/* ---------- digger live ---------- */
/* Nine levels are on screen at once here, against six in the solo shaft, so the
   rows were made shorter to fit them. Taken too far: a tile 91px wide and 35px
   tall reads as a bar rather than a place you might stand, and the icon inside
   it is sized by the shorter side.

   The ceiling is 64px rather than the solo shaft's 72px, and that is the whole
   constraint: nine levels at 72px would stand 729px tall, which pushes the
   bottom levels under the fold on a laptop. A player has ten seconds to plot a
   path through all nine - having to scroll to find the last one loses the round.
   At 64px the shaft is 648px, and the whole thing fits above the fold. */
.board-wrap-live {
  aspect-ratio: auto;
  --row-h: clamp(48px, 12vw, 64px);
  --rail-w: clamp(62px, 17vw, 92px);
}

.live-shaft { display: flex; flex-direction: column; gap: var(--tile-gap); }

.live-row {
  display: grid;
  grid-template-columns: var(--rail-w) repeat(var(--shaft-columns, 3), 1fr);
  gap: var(--tile-gap);
  height: var(--row-h);
  opacity: .62;
  transition: opacity .2s ease;
}

.live-row.is-bought,
.live-row.is-next,
.live-row.is-open { opacity: 1; }

/* The row waiting for a pick is the only one that should pull the eye. */
.live-row.is-next .live-tile .face-front {
  box-shadow: inset 0 0 0 1.5px var(--accent);
}

.live-tile {
  position: relative;
  padding: 0;
  border: none;
  background: none;
  perspective: 700px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.live-tile .tile-inner {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform .35s cubic-bezier(.2, .85, .3, 1);
}

.live-tile.open .tile-inner { transform: rotateY(180deg); }

.live-tile .face-front {
  background: var(--tile);
  border-bottom: 3px solid #1f2b41;
  transition: background .15s ease;
}

.live-tile:hover .face-front { background: var(--tile-hover); }
.live-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius); }

.live-tile .face-back {
  transform: rotateY(180deg);
  background: var(--gem-bg);
  color: var(--gem);
}

.live-tile.charge .face-back { background: var(--mine-bg); color: var(--mine); }
.live-tile .face-back svg { width: 44%; height: 44%; }

/* Your own pick: a filled outline, unmistakable against the crowd dots. */
.live-tile.mine-pick .face-front {
  background: #24405f;
  box-shadow: inset 0 0 0 2px var(--gold);
}

/* Where everyone else is standing. Small, quiet, and stacked along the bottom
   of the tile so they never cover the gem or the charge. */
/* Anchored to the left edge, not centred.
   The gem or the charge sits in the middle of the tile, so a centred row of
   faces lands right on top of it - which is what the screenshot showed. Growing
   from the left keeps the icon clear no matter how many players pile on, and
   makes the row start in the same place on every tile so the eye can compare
   them down a column. */
.tile-marks {
  position: absolute;
  left: 6px;
  right: 4px;
  bottom: 3px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 3px;
  pointer-events: none;
  z-index: 2;
  /* Last resort. The sizing above is meant to fit, but a tile is only as wide
     as the layout gives it, and a clipped face is far better than a row running
     across the tile beside it. */
  overflow: hidden;
}

.pick-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-dim);
  opacity: .85;
}

.pick-dot.pick-mine { background: var(--gold); }

/* ---------- the clock ---------- */
.live-clock {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 10px;
  margin-bottom: 14px;
}

.clock-phase { font-size: 12px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .5px; }
.clock-time { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text); }

.clock-bar {
  grid-column: 1 / -1;
  height: 5px;
  border-radius: 3px;
  background: var(--bg);
  overflow: hidden;
}

.clock-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--gem);
  transition: width .12s linear, background .2s ease;
}

.clock-fill.urgent { background: var(--gold); }

/* ---------- the table ---------- */
/* A busy table holds more names than the panel should grow to fit, so the list
   scrolls inside it rather than stretching the page under the shaft. */
.live-side .live-players { max-height: 46vh; overflow-y: auto; }

.live-pot { margin: 0 0 10px; font-size: 12.5px; color: var(--text-dim); }
.live-players { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.live-player {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: 8px;
  align-items: center;
  padding: 7px 10px;
  background: var(--bg);
  border-radius: var(--radius);
  font-size: 12.5px;
}

.lp-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lp-depth { color: var(--text-dim); font-variant-numeric: tabular-nums; }
.lp-amt { font-variant-numeric: tabular-nums; color: var(--text-dim); }

.live-player.won { background: #12352b; }
.live-player.won .lp-depth, .live-player.won .lp-amt { color: var(--gem); }
.live-player.lost .lp-amt { color: var(--mine); }

@media (prefers-reduced-motion: reduce) {
  .live-tile .tile-inner { transition: none; }
  .clock-fill { transition: none; }
}

/* ---------- win overlay ---------- */
.board-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 4;
  pointer-events: none;
}

.overlay-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 18px 34px;
  background: rgba(14, 20, 32, .82);
  border: 2px solid var(--gem);
  border-radius: 16px;
  animation: overlayIn .3s cubic-bezier(.2, .9, .3, 1);
}

@keyframes overlayIn {
  from { opacity: 0; transform: scale(.85); }
  to { opacity: 1; transform: scale(1); }
}

.overlay-mult { font-size: 34px; font-weight: 700; color: var(--gem); font-variant-numeric: tabular-nums; }
.overlay-amount { font-size: 16px; color: var(--text); font-variant-numeric: tabular-nums; }

/* ---------- history ---------- */
.history h2 { margin: 0 0 12px; font-size: 13px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .6px; }
.history-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.history-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 10px;
  background: var(--bg);
  border-radius: 8px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.history-item .mult { font-weight: 600; }
.history-item.win .mult { color: var(--gem); }
.history-item.loss .mult { color: var(--mine); }
.history-item .amt { color: var(--text-dim); }
.history-empty { color: var(--text-dim); font-size: 13px; }

/* ---------- modal ---------- */
.modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(6, 10, 18, .72);
  z-index: 10;
}

.modal-card {
  width: 100%;
  max-width: 460px;
  max-height: 86vh;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid #2b3a58;
  border-radius: 16px;
  padding: 20px;
}

.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.modal-head h2 { margin: 0; font-size: 17px; }
.modal-text { margin: 0 0 16px; font-size: 13px; color: var(--text-dim); line-height: 1.6; }

.icon-btn {
  width: 32px;
  height: 32px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: var(--text-dim);
  font-size: 15px;
  cursor: pointer;
}

.icon-btn:hover { background: var(--panel-2); color: var(--text); }

.revealed { display: flex; flex-direction: column; gap: 8px; }

.revealed-item {
  padding: 10px;
  background: var(--bg);
  border-radius: 8px;
  font-size: 11px;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  color: var(--text-dim);
  word-break: break-all;
  line-height: 1.6;
}

.revealed-item b { color: var(--text); font-weight: 500; }

/* ---------- lobby ---------- */
.lobby {
  max-width: 900px;
  margin: 0 auto;
  padding: clamp(22px, 4vw, 44px) clamp(12px, 3vw, 28px) 70px;
}

.lobby-intro {
  margin: 0 0 22px;
  font-size: 14px;
  color: var(--text-dim);
}

/* Two per row on desktop, one on a phone.
   auto-fill, not auto-fit: auto-fit collapses the empty tracks, so a lobby
   with a single game would stretch that one card across the full width. */
.game-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

/* The list item is only a grid cell; the link is the card. Making it a flex
   container is what lets the link fill the row height, so cards in the same
   row stay level even when one tagline wraps. */
/* The card is the bordered box, not the link inside it. The link used to carry
   the border, but the rewards row has to live outside it - it holds a button,
   and a button inside an anchor follows the anchor when pressed - so the frame
   moved out to hold both. */
.game-card {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid #253350;
  border-radius: 16px;
  overflow: hidden;
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}

.game-card:hover {
  border-color: var(--gem);
  transform: translateY(-3px);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .38);
}

.game-card:focus-within { border-color: var(--gem); }

.game-link {
  display: flex;
  flex-direction: column;
  width: 100%;
  flex: 1;
  color: var(--text);
  text-decoration: none;
  transition: border-color .18s ease, transform .14s ease, box-shadow .18s ease;
}

/* The lift is on the card now, so hovering the link alone does nothing. Kept as
   a rule rather than deleted so the hover target is stated in one place: the
   card is what the pointer is over, the link is only part of it. */
.game-link:hover { text-decoration: none; }

.game-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Cover art stands in for a real illustration: a coloured wash, a dot grid for
   texture, and the game's icon oversized. Swap it for artwork per game later
   without touching the card structure. */
.game-cover {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 8;
  background:
    radial-gradient(120% 140% at 50% 115%, rgba(35, 209, 139, .22), transparent 60%),
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .022) 0 1px, transparent 1px 14px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .022) 0 1px, transparent 1px 14px),
    #131d30;
  border-bottom: 1px solid #253350;
}

.game-cover-glow {
  position: absolute;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: currentColor;
  opacity: .13;
  filter: blur(26px);
}

.game-cover-icon {
  position: relative;
  display: flex;
  transition: transform .2s cubic-bezier(.2, .85, .3, 1);
}

.game-cover-icon svg { width: 46px; height: 46px; }
.game-link:hover .game-cover-icon { transform: scale(1.08) translateY(-2px); }

.game-link.accent-gem { color: var(--gem); }
.game-link.accent-gold { color: var(--gold); }
.game-link.accent-blue { color: var(--accent); }

.game-badge {
  position: absolute;
  top: 12px;
  right: 12px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .8px;
  text-transform: uppercase;
}

.game-badge.tone-hot { background: #ff5c3d; color: #2a0a02; }
.game-badge.tone-new { background: var(--gem); color: #06231a; }
.game-badge.tone-default { background: var(--panel-2); color: var(--text); }

/* The mode sits opposite the badge and is deliberately quieter: it states a
   fact about the game rather than advertising it. */
.game-mode {
  position: absolute;
  top: 12px;
  left: 12px;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .5px;
  text-transform: uppercase;
  backdrop-filter: blur(2px);
}

.game-mode.mode-solo {
  border-color: #3b4f74;
  background: rgba(19, 29, 48, .72);
  color: #9fb2d0;
}

.game-mode.mode-multiplayer {
  border-color: #3d8bff;
  background: rgba(15, 32, 60, .78);
  color: #7fb0ff;
}

.game-info {
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex: 1;
  padding: 14px 16px 16px;
  color: var(--text);
}

.game-name { font-size: 16px; font-weight: 600; letter-spacing: .2px; }
.game-tagline { font-size: 12.5px; color: var(--text-dim); line-height: 1.5; }

.game-foot { display: flex; margin-top: auto; padding-top: 12px; }

.game-play {
  padding: 8px 20px;
  border-radius: var(--radius);
  background: var(--gem);
  color: #06231a;
  font-size: 13.5px;
  font-weight: 600;
  transition: filter .15s ease;
}

.game-link:hover .game-play { filter: brightness(1.1); }

.game-empty { color: var(--text-dim); font-size: 14px; }

@media (prefers-reduced-motion: reduce) {
  .game-link, .game-cover-icon { transition: none; }
  .game-link:hover { transform: none; }
  .game-link:hover .game-cover-icon { transform: none; }
}

/* ---------- account ---------- */
.account {
  max-width: 1000px;
  margin: 0 auto;
  padding: clamp(20px, 4vw, 40px) clamp(12px, 3vw, 28px) 60px;
}

.account-error {
  margin: 0 0 18px;
  padding: 12px 14px;
  background: var(--mine-bg);
  border-radius: var(--radius);
  color: var(--mine);
  font-size: 13px;
}

.acc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 16px;
  margin-bottom: 26px;
  align-items: start;
}

.acc-card h2,
.acc-history h2 {
  margin: 0 0 16px;
  font-size: 13px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .7px;
}

.acc-card input[type="text"],
.acc-card input[type="password"] {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  background: var(--bg);
  border: 1px solid #2f3f5e;
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
}

.acc-card input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.acc-card input[readonly] { color: var(--text-dim); }
.acc-card .input-row input { width: auto; }

.field-note { margin: 7px 0 0; font-size: 11.5px; color: var(--text-dim); line-height: 1.5; }

.form-msg {
  margin: 0 0 12px;
  padding: 9px 11px;
  border-radius: var(--radius);
  font-size: 12.5px;
  line-height: 1.5;
}

.form-msg.ok { background: var(--gem-bg); color: var(--gem); }
.form-msg.bad { background: var(--mine-bg); color: var(--mine); }

.meta {
  margin: 18px 0 0;
  padding-top: 14px;
  border-top: 1px solid #253350;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.meta > div { display: flex; justify-content: space-between; gap: 12px; }
.meta dt { font-size: 12px; color: var(--text-dim); }
.meta dd { margin: 0; font-size: 12.5px; font-variant-numeric: tabular-nums; }

.big-balance {
  margin: 0 0 16px;
  font-size: 32px;
  font-weight: 600;
  color: var(--gem);
  font-variant-numeric: tabular-nums;
}

.acc-stats { margin: 0; }
.stat-value.up { color: var(--gem); }
.stat-value.down { color: var(--mine); }

.acc-card .primary-btn { margin-top: 4px; }

/* ---------- balance split and wagering ---------- */
.split {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin: -6px 0 14px;
  padding: 11px 13px;
  background: var(--bg);
  border-radius: var(--radius);
}

.split-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.split-label { font-size: 12px; color: var(--text-dim); }
.split-value { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
.split-value.locked { color: var(--gold); }

.bonus-box {
  margin-bottom: 14px;
  padding: 12px 13px;
  background: var(--bg);
  border: 1px solid #33456a;
  border-radius: var(--radius);
}

.bonus-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 8px; }

.bonus-title {
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .6px;
}

/* Beside the label, not between the two of them: the head is space-between, so
   a third child left to itself would be stranded in the middle. margin-right
   pushes the percentage back to the edge it belongs on. */
.info-btn {
  margin-right: auto;
  margin-left: 6px;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
  border-radius: 50%;
  transition: color .15s ease;
}

.info-btn:hover { color: var(--text); }
.info-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.info-btn svg { width: 15px; height: 15px; }

/* ---------- avatars ---------- */
/* Round everywhere, and object-fit so a rectangular upload is cropped to the
   circle rather than squashed into it. */
.avatar {
  border-radius: 50%;
  object-fit: cover;
  background: var(--bg);
  display: block;
  flex: none;
}

.avatar-lg { width: 72px; height: 72px; border: 2px solid var(--panel-2); }

.avatar-row { display: flex; gap: 14px; align-items: center; margin-bottom: 16px; }
.avatar-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.avatar-actions .field-note { flex-basis: 100%; margin: 0; }

/* The upload control is a <label> for a hidden file input, so it needs the
   chip's own hover and pointer treatment. */
label.chip { display: inline-flex; align-items: center; cursor: pointer; }

/* The randomiser carries an icon, so it needs the same inline-flex treatment
   as the upload label rather than the default button layout. */
#avatarRandom { display: inline-flex; align-items: center; gap: 6px; }
#avatarRandom:disabled { opacity: .5; cursor: default; }

/* ---------- who is standing where ---------- */
/* Overlapped on purpose: ten faces across a 90px tile only fit if they share
   space, and the negative margin is what keeps the row centred as it grows. */
/* Ten faces plus the count have to fit inside a tile that is 91px wide on a
   phone. At 18px each with a 6px overlap the row runs to 166px and spills onto
   the neighbouring column, so the size and the overlap are both derived from
   the viewport and only a slice of each face shows. The brief allows this:
   "пусть накладываются друг на друга если что". */
.board-wrap-live {
  --face: clamp(15px, 4.4vw, 20px);
  /* How much of each face is visible before the next one covers it. Half, so
     each circle is exactly half-hidden by its neighbour. Fewer of them fit at
     this spacing, which is why the count is measured rather than fixed. */
  --face-step: calc(var(--face) * 0.5);
}

.pick-face {
  width: var(--face);
  height: var(--face);
  border-radius: 50%;
  object-fit: cover;
  border: 1.5px solid var(--bg-2);
  margin-right: calc(var(--face-step) - var(--face));
  background: var(--bg);
  flex: none;
}

.pick-face:last-of-type { margin-right: 0; }

/* Yours sits first and is the one with the gold ring. */
.pick-face.pick-mine {
  border-color: var(--gold);
  z-index: 2;
  position: relative;
}

/* Past ten, the rest become a number rather than more circles. */
.pick-more {
  margin-left: 5px;
  padding: 0 4px;
  height: var(--face, 18px);
  flex: none;
  display: inline-flex;
  align-items: center;
  border-radius: 9px;
  background: var(--panel-2);
  color: var(--text);
  font-size: clamp(9px, 2.4vw, 10.5px);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.lp-face { width: 22px; height: 22px; }

/* ---------- wagering rates ---------- */
.wager-group { margin-bottom: 14px; }

.wager-game {
  margin: 0 0 6px;
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .6px;
}

.wager-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 6px 10px;
  background: var(--bg);
  border-radius: var(--radius);
  font-size: 13px;
  margin-bottom: 4px;
}

.wager-rate { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text-dim); }
.wager-rate.full { color: var(--gem); }
.wager-rate.thin { color: var(--gold); }

.bonus-pct { font-size: 14px; font-weight: 600; color: var(--gold); font-variant-numeric: tabular-nums; }

.bonus-bar {
  height: 6px;
  background: #22304a;
  border-radius: 999px;
  overflow: hidden;
}

.bonus-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--gold);
  border-radius: 999px;
  transition: width .3s ease;
}

.bonus-note { margin: 9px 0 0; font-size: 11.5px; color: var(--text-dim); line-height: 1.55; }

/* ---------- funding ---------- */
.fund-actions { display: flex; gap: 8px; margin-bottom: 8px; }

.fund-btn {
  flex: 1;
  height: 40px;
  border: none;
  border-radius: var(--radius);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: filter .15s ease;
}

.fund-btn.deposit { background: var(--gem); color: #06231a; }
.fund-btn.withdraw { background: var(--panel-2); border: 1px solid #33456a; color: var(--text); }
.fund-btn:hover:not(:disabled) { filter: brightness(1.08); }
.fund-btn:disabled { opacity: .45; cursor: not-allowed; }

.fund-summary {
  display: flex;
  gap: 10px;
  margin-bottom: 12px;
}

.fund-summary > div {
  flex: 1;
  padding: 10px 12px;
  background: var(--bg);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.fund-label {
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .5px;
}

.fund-value { font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; }
.fund-value.up { color: var(--gem); }

.acc-funding { margin-bottom: 26px; }
.acc-history .pill.deposit { background: var(--gem-bg); color: var(--gem); }
.acc-history .pill.withdrawal { background: #2a3a55; color: #a9c0e4; }

/* ---------- account history ---------- */
.acc-history .scroll {
  overflow-x: auto;
  border: 1px solid #253350;
  border-radius: var(--radius);
}

.acc-history table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.acc-history th,
.acc-history td {
  padding: 9px 13px;
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid #1f2b41;
}

.acc-history th {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .6px;
}

.acc-history tbody tr:last-child td { border-bottom: none; }
.acc-history td.num, .acc-history th.num { text-align: right; }
.acc-history .up { color: var(--gem); }
.acc-history .down { color: var(--mine); }
.acc-history .empty { color: var(--text-dim); text-align: center; padding: 20px; }

.acc-history .pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .4px;
  text-transform: uppercase;
}

.acc-history .pill.bet { background: #2a3a55; color: #a9c0e4; }
.acc-history .pill.payout { background: var(--gem-bg); color: var(--gem); }
.acc-history .pill.grant { background: #3a3016; color: var(--gold); }

.muted { color: var(--text-dim); font-weight: 400; text-transform: none; letter-spacing: 0; }

/* ---------- pagination ---------- */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 14px;
}

.pager-info { font-size: 12px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.pager-controls { display: flex; align-items: center; gap: 6px; }
.pager-pages { display: flex; align-items: center; gap: 4px; }
.pager-gap { padding: 0 2px; color: var(--text-dim); }

.pager .chip { height: 32px; font-size: 12.5px; }
.pager .chip:disabled { opacity: .4; cursor: not-allowed; }

.page-btn {
  min-width: 32px;
  height: 32px;
  padding: 0 8px;
  background: transparent;
  border: 1px solid #2f3f5e;
  border-radius: 7px;
  color: var(--text);
  font: inherit;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.page-btn:hover { background: var(--panel-2); }
.page-btn.current { background: var(--gem); border-color: var(--gem); color: #06231a; font-weight: 600; }
.page-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.pager-size {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--text-dim);
}

.pager-size select {
  height: 32px;
  padding: 0 8px;
  background: var(--bg);
  border: 1px solid #2f3f5e;
  border-radius: 7px;
  color: var(--text);
  font: inherit;
  font-size: 12.5px;
}

/* ---------- auth ---------- */
.auth-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--panel);
  border: 1px solid #253350;
  border-radius: 16px;
  padding: 28px;
}

.auth-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  margin-bottom: 22px;
  font-size: 20px;
  font-weight: 600;
}

.auth-tabs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  padding: 4px;
  margin-bottom: 20px;
  background: var(--bg);
  border-radius: var(--radius);
}

.auth-tab {
  height: 36px;
  background: transparent;
  border: none;
  border-radius: 7px;
  color: var(--text-dim);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
}

.auth-tab.is-active { background: var(--panel-2); color: var(--text); font-weight: 600; }
.auth-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.auth-form input[type="email"],
.auth-form input[type="password"] {
  width: 100%;
  height: 42px;
  padding: 0 12px;
  background: var(--bg);
  border: 1px solid #2f3f5e;
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
}

.auth-form input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.auth-form .primary-btn { margin-top: 6px; }

.auth-error {
  margin: 0 0 14px;
  padding: 10px 12px;
  background: var(--mine-bg);
  border-radius: var(--radius);
  color: var(--mine);
  font-size: 13px;
  line-height: 1.5;
}

.auth-note {
  margin: 14px 0 0;
  font-size: 12px;
  color: var(--text-dim);
  text-align: center;
  line-height: 1.5;
}

/* ---------- toasts ---------- */
.toasts {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: max-content;
  max-width: min(440px, calc(100vw - 32px));
  z-index: 100;
  /* The stack itself must not swallow clicks on the page behind it; each
     toast turns pointer events back on for itself. */
  pointer-events: none;
}

.toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--border-strong, #33456a);
  background: var(--panel-2);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .45);
  font-size: 13.5px;
  line-height: 1.5;
  opacity: 1;
  transform: translateY(0);
  transition: opacity .22s ease, transform .22s cubic-bezier(.2, .85, .3, 1);
}

.toast.entering,
.toast.leaving {
  opacity: 0;
  transform: translateY(12px);
}

.toast.error {
  background: #3a1b22;
  border-color: #6b2a33;
  color: #ffd7d7;
}

.toast.ok {
  background: var(--gem-bg);
  border-color: #1c6b4d;
  color: #c7f7e4;
}

.toast.info {
  background: var(--panel-2);
  border-color: #33456a;
  color: var(--text);
}

.toast-text { flex: 1; }

.toast-close {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: -1px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 5px;
  color: inherit;
  opacity: .6;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
}

.toast-close:hover { opacity: 1; background: rgba(255, 255, 255, .08); }
.toast-close:focus-visible { outline: 2px solid currentColor; outline-offset: 1px; opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .toast { transition: opacity .15s ease; }
  .toast.entering, .toast.leaving { transform: none; }
}

/* ---------- responsive ---------- */

/* Narrow screens: the header runs out of room, so the labelled buttons drop to
   icons and match the toggles beside them. Scoped to .topbar so the wide
   labelled button inside the fairness dialog keeps its text. */
@media (max-width: 600px) {
  .topbar { padding: 12px 14px; }
  .topbar-right { gap: 8px; }

  .topbar .ghost-btn {
    width: 40px;
    padding: 0;
    gap: 0;
    justify-content: center;
  }

  .topbar .ghost-btn .btn-label { display: none; }
  .topbar .ghost-btn .btn-icon { width: 19px; height: 19px; }

  /* The address is the least useful thing in a cramped header - the account is
     already implied by being signed in. */
  .user-email { display: none; }
}
@media (max-width: 980px) {
  .layout { grid-template-columns: minmax(0, 1fr); }
  .board-section { order: -1; }
  .history { order: 1; }

  /* Stacked on a phone, the action button is the one control that must never
     need a scroll - during a round it is the cash-out, and a player who has to
     scroll to reach it loses the round while looking for it. So it sits
     directly under the board, and the inputs, which only matter between
     rounds, drop below it. */
  .controls {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  .controls .primary-btn { order: 0; }
  .controls .hint { order: 1; margin: 0; min-height: 0; }
  .controls .stats { order: 2; margin: 0; }
  .controls .field-bet { order: 3; margin: 0; }
  .controls .field-mines { order: 4; margin: 0; }
}
