:root {
  --bg: #170f2e;
  --surface: #241a47;
  --raised: #2f2359;
  --border: #3f3172;
  --text: #f4f0ff;
  --dim: #b3a8d9;
  --faint: #8579b8;
  --violet: #8b5cff;
  --violet-hi: #a47dff;
  --pink: #ff6fb5;
  --win: #34e5a4;
  --lose: #ff5e7a;
  --gold: #ffd23d;
  --font: 'Nunito', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --display: 'Fredoka', 'Nunito', system-ui, sans-serif;
  --cjk-sc: 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans CJK SC', 'Source Han Sans SC';
  --cjk-jp: 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', 'Yu Gothic', 'Noto Sans CJK JP', Meiryo;
  --radius: 22px;
}

/* ---- one face per language ----
 *
 * A font stack falls back PER CHARACTER, which is fine when the scripts are
 * different - Chinese glyphs coming from a Chinese font while the digits beside
 * them stay in Fredoka reads as normal typesetting. It is not fine when the
 * fallback happens inside a single WORD, and that is exactly what Vietnamese
 * did here.
 *
 * Fredoka ships latin, latin-ext and hebrew. Vietnamese needs U+1EA0-1EF9 - the
 * vowels carrying a tone mark on top of a circumflex or breve: ạ ấ ầ ể ộ ợ ứ ữ.
 * Those are NOT in latin-ext, while Ă Đ Ơ Ư are. So "CHỨNG ĐƯỢC" was drawn in
 * two different typefaces with two different sets of metrics, letter by letter,
 * and it looked broken because it was.
 *
 * Vietnamese therefore drops Fredoka entirely and uses Baloo 2, which covers the
 * whole language in one face and is the closest rounded display font to Fredoka
 * in weight and shape. Russian needs no rule: Fredoka has no Cyrillic at all, so
 * every Cyrillic letter already comes from Nunito and a Russian heading is
 * uniform by accident. CJK keeps Fredoka in front for the digits and addresses
 * that sit inside Chinese and Japanese text, with a real CJK face behind it -
 * better than whatever system-ui happens to pick.
 *
 * `lang` is set by js/platform/i18n.js, which is the only thing that writes it. */
:root[lang="vi"] {
  --display: 'Baloo 2', 'Nunito', system-ui, sans-serif;
}
:root[lang="zh"] {
  --font: 'Nunito', var(--cjk-sc), system-ui, sans-serif;
  --display: 'Fredoka', var(--cjk-sc), 'Nunito', system-ui, sans-serif;
}
:root[lang="ja"] {
  --font: 'Nunito', var(--cjk-jp), system-ui, sans-serif;
  --display: 'Fredoka', var(--cjk-jp), 'Nunito', system-ui, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15.5px;
  font-weight: 600;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background:
    radial-gradient(760px 380px at 18% -6%, rgba(139, 92, 255, 0.34), transparent 68%),
    radial-gradient(640px 360px at 88% 4%, rgba(255, 111, 181, 0.24), transparent 66%);
  pointer-events: none;
}

/* ---------------- top bar ---------------- */
#topbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 0 14px;
  background: rgba(23, 15, 46, 0.8);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--border);
  z-index: 20;
}
.brand { font-size: 21px; letter-spacing: 2px; flex: none; }
.brand-name { display: none; }

.wallet-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  background: var(--raised);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 7px 5px 5px;
  min-width: 0;
}
.wallet-chip canvas { border-radius: 50%; flex: none; }
#walletAddr { white-space: nowrap; color: var(--dim); }
.wallet-chip .net { display: none; }
.chip-btn {
  font-family: var(--font);
  font-size: 14px;
  color: var(--dim);
  background: transparent;
  border: none;
  border-radius: 50%;
  width: 30px; height: 30px;
  cursor: pointer;
  flex: none;
  transition: background 0.15s, color 0.15s, transform 0.15s;
}
.chip-btn:hover { background: rgba(255,255,255,0.1); color: var(--text); transform: scale(1.1); }

.purse-chip {
  font-family: var(--display);
  font-weight: 600;
  font-size: 15px;
  color: #3a2a00;
  background: linear-gradient(180deg, #ffe27a, var(--gold));
  border-radius: 999px;
  padding: 3px 12px;
  flex: none;
  box-shadow: 0 3px 0 rgba(180, 140, 0, 0.55);
}

/* ---------------- layout ---------------- */
#stage {
  min-height: 100vh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  /* 80px clears the fixed top bar; --banner-h is set from the wrong-network
     banner's real height whenever it appears (see loginui.js). */
  padding: calc(80px + var(--banner-h, 0px)) 14px 42px;
  position: relative;
}

.overlay {
  position: fixed;
  inset: 0;
  display: flex;
  /* NOT align-items:center.
     
     A flex child taller than its container overflows in BOTH directions when it
     is centred, and the part above the top edge cannot be scrolled to - the
     scroll range starts at the container's top, which is already past it. The
     cashier's heading was simply unreachable once the history made the card
     tall. `margin:auto` on the card centres it while there is room and stops
     centring when there is not, which is the behaviour people expect anyway. */
  align-items: flex-start;
  justify-content: center;
  padding: 18px;
  background: rgba(12, 7, 26, 0.8);
  backdrop-filter: blur(7px);
  z-index: 30;
  overflow: auto;
}
.overlay > .card { margin: auto; }
/* The sign-in screen is a whole page, not a dialog over one, so it sits BELOW
   the top bar rather than on top of it. Without this the menu button - and with
   it the language picker and the provably-fair page - were unreachable at
   exactly the moment a new player most wants them: before signing in. */
#loginOverlay { background: var(--bg); backdrop-filter: none; z-index: 15; }
.hidden { display: none !important; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.06);
  padding: 26px 22px;
  width: 100%;
  max-width: 420px;
  text-align: center;
}
.card h1 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 30px;
  line-height: 1.18;
  margin: 14px 0 10px;
  background: linear-gradient(100deg, #ffd23d, var(--pink) 55%, var(--violet-hi));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.card h2 { font-family: var(--display); font-weight: 600; font-size: 23px; margin: 0 0 14px; }
.card .sub { color: var(--dim); font-size: 15px; font-weight: 600; margin: 0 0 20px; }
.card .sub.small { font-size: 13.5px; margin: 16px 0 10px; color: var(--faint); }
.fox { font-size: 54px; line-height: 1; }
.status { font-size: 13.5px; line-height: 1.45; margin: 14px 0 0; min-height: 18px; color: var(--lose); }
.status a { color: var(--violet-hi); }

/* ---------------- buttons ---------------- */
.btn-primary {
  font-family: var(--display);
  font-weight: 600;
  font-size: 18px;
  color: #fff;
  background: linear-gradient(135deg, var(--violet-hi), var(--pink));
  border: none;
  border-radius: 16px;
  padding: 15px 18px;
  width: 100%;
  cursor: pointer;
  box-shadow: 0 5px 0 #6a3fd0, 0 12px 24px rgba(139, 92, 255, 0.34);
  transition: transform 0.1s, box-shadow 0.1s, filter 0.15s;
}
.btn-primary:hover:not(:disabled) { filter: brightness(1.07); }
.btn-primary:active:not(:disabled) { transform: translateY(4px); box-shadow: 0 1px 0 #6a3fd0; }
.btn-primary:disabled { opacity: 0.4; cursor: not-allowed; box-shadow: none; }
.btn-primary.rebuy {
  background: linear-gradient(135deg, #5cf0bb, #16c48d);
  box-shadow: 0 5px 0 #0e9a6d, 0 12px 24px rgba(52, 229, 164, 0.3);
  margin-top: 10px;
}
.btn-primary.rebuy:active:not(:disabled) { box-shadow: 0 1px 0 #0e9a6d; }

.btn-ghost {
  font-family: var(--display);
  font-weight: 500;
  font-size: 15px;
  background: transparent;
  color: var(--dim);
  border: 2px solid var(--border);
  border-radius: 14px;
  padding: 11px 16px;
  margin-top: 10px;
  width: 100%;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.btn-ghost:hover { background: rgba(255,255,255,0.06); color: var(--text); border-color: var(--violet); }

.code { font-family: var(--display); font-weight: 600; color: var(--gold); }

/* ---------------- lists ---------------- */
.board { list-style: none; padding: 0; margin: 0 0 6px; text-align: left; }
.board li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  padding: 11px 13px;
  border-radius: 14px;
  background: var(--raised);
  border: 2px solid transparent;
  margin-bottom: 8px;
}
.board li.me { border-color: var(--violet); background: rgba(139,92,255,0.16); }
.board .rank { width: 20px; color: var(--faint); font-family: var(--display); }
.board .addr { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dim); }
.board .score, .board .stake { font-family: var(--display); font-weight: 600; font-size: 16px; color: var(--gold); }
.board .empty, .board li.loading { justify-content: center; color: var(--faint); background: transparent; }
.board li button.sit {
  font-family: var(--display);
  font-weight: 600;
  font-size: 14px;
  color: #fff;
  background: linear-gradient(135deg, var(--violet-hi), var(--pink));
  border: none;
  border-radius: 11px;
  padding: 7px 15px;
  cursor: pointer;
  flex: none;
  box-shadow: 0 3px 0 #6a3fd0;
  transition: transform 0.1s, box-shadow 0.1s;
}
.board li button.sit:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 #6a3fd0; }
.board li button.sit:disabled { background: var(--border); color: var(--faint); cursor: default; box-shadow: none; }

/* ---------------- points ---------------- */
.purse-line {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 10px;
  font-size: 12.5px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--faint);
  margin: -4px 0 16px;
}
.purse-line b { font-family: var(--display); font-weight: 600; font-size: 34px; color: var(--gold); }

.stake-row { display: flex; gap: 9px; margin-bottom: 11px; }
.stake-all { width: auto; flex: none; padding: 12px 17px; margin-top: 0; font-size: 14px; }

/* ---------------- the table ---------------- */
#arena {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 18px;
  margin-bottom: 14px;
  background: #1a1033;
}

.seats { display: flex; align-items: stretch; gap: 8px; margin: 0 0 14px; }
.seat {
  flex: 1;
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 16px;
  padding: 10px 8px;
  min-height: 80px;
  transition: border-color 0.2s, background 0.2s;
}
.seat.turn { border-color: var(--violet); background: rgba(139,92,255,0.16); }
.seat .who { display: block; font-family: var(--display); font-size: 11px; letter-spacing: 1.2px; color: var(--faint); margin-bottom: 5px; }
.seat .bal { display: block; font-size: 13px; color: var(--dim); }
.seat .state { display: block; font-size: 12.5px; color: var(--faint); margin-top: 3px; }
.seat .state.locked { color: var(--win); }
.seat-vs { align-self: center; font-family: var(--display); font-size: 13px; color: var(--faint); flex: none; }

/* ---------------- pick a hand ---------------- */
.hands { display: flex; gap: 9px; margin-bottom: 14px; }
.hand {
  flex: 1;
  font-family: var(--display);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.4px;
  color: var(--dim);
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 18px;
  padding: 13px 4px 11px;
  cursor: pointer;
  transition: transform 0.14s cubic-bezier(.34,1.56,.64,1), border-color 0.15s, background 0.15s, color 0.15s;
}
.hand .ico { display: block; font-size: 32px; line-height: 1; margin-bottom: 7px; }
.hand:hover:not(:disabled) { border-color: var(--violet); color: var(--text); transform: translateY(-4px) scale(1.04); }
.hand:active:not(:disabled) { transform: translateY(0) scale(0.98); }
.hand:disabled { opacity: 0.32; cursor: default; }
.hand.chosen {
  opacity: 1;
  color: #06301f;
  background: linear-gradient(135deg, #5cf0bb, #16c48d);
  border-color: transparent;
  box-shadow: 0 5px 0 #0e9a6d;
}

/* ---------------- sealed hashes ---------------- */
.sealed {
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 16px;
  padding: 12px 13px 10px;
  margin-bottom: 14px;
  text-align: left;
}
.seal-title { font-family: var(--display); font-size: 11.5px; letter-spacing: 1.2px; color: var(--faint); margin: 0 0 9px; text-align: center; }
.seal-row { display: flex; align-items: flex-start; gap: 9px; margin-bottom: 7px; }
.seal-row .who { font-family: var(--display); font-size: 11px; color: var(--faint); width: 38px; flex: none; padding-top: 2px; }
.seal-row code {
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 10.5px;
  line-height: 1.45;
  word-break: break-all;
  color: var(--violet-hi);
  flex: 1;
}
.seal-row code.empty { color: var(--faint); }

/* ---------------- result ---------------- */
.result { margin-bottom: 14px; }
.result .throw { display: none; }
.result .verdict { font-family: var(--display); font-weight: 600; font-size: 30px; }
.result .verdict.win { color: var(--win); }
.result .verdict.lose { color: var(--lose); }
.result .verdict.draw { color: var(--violet-hi); }
.result .delta { font-size: 14.5px; color: var(--dim); margin-top: 4px; }

/* ---------------- check it yourself ---------------- */
.verify {
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 16px;
  padding: 12px 13px;
  margin-bottom: 12px;
  text-align: left;
}
.verify .v-title { font-family: var(--display); font-size: 11.5px; letter-spacing: 1.2px; color: var(--faint); margin: 0 0 9px; text-align: center; }
.verify .v-row {
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 10.5px;
  line-height: 1.5;
  word-break: break-all;
  color: var(--dim);
  margin-bottom: 6px;
}
.verify .v-row .tick { font-family: var(--display); font-size: 11px; color: var(--win); }
.verify .v-row .cross { font-family: var(--display); font-size: 11px; color: var(--lose); }
.verify .v-note { font-family: var(--font); font-size: 12.5px; color: var(--faint); margin: 9px 0 0; line-height: 1.45; }

.stake-line {
  font-size: 13px;
  color: var(--faint);
  margin: -8px 0 14px;
}

.copy-btn {
  font-family: var(--display);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.6px;
  color: var(--violet-hi);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 7px 12px;
  margin-top: 8px;
  width: 100%;
  cursor: pointer;
}
.copy-btn:hover { background: rgba(139,92,255,0.12); color: var(--text); }
.seal-hint { font-size: 11.5px; color: var(--faint); margin: 8px 0 0; line-height: 1.4; }
.verify .v-row .v-head { display: block; font-family: var(--display); font-size: 12px; color: var(--text); margin-bottom: 2px; }
.verify .v-row { padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.verify .v-row:last-of-type { border-bottom: none; }

/* ---------------- wallet picker ---------------- */
.wallet-list { list-style: none; padding: 0; margin: 0; }
.wallet-list.busy { opacity: 0.55; pointer-events: none; }
.wallet-option {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
  margin-bottom: 9px;
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 14px;
  cursor: pointer;
  transition: border-color 0.15s, transform 0.12s, background 0.15s;
}
.wallet-option:hover { border-color: var(--violet); transform: translateY(-2px); }
.wallet-option.picked { border-color: var(--violet); background: rgba(139,92,255,0.14); }
.wallet-option .w-ico { width: 30px; height: 30px; border-radius: 8px; flex: none; object-fit: contain; }
.w-ico-fallback { display: flex; align-items: center; justify-content: center; font-size: 17px; background: rgba(255,255,255,0.06); }
.wallet-option .w-name { flex: 1; text-align: left; font-family: var(--display); font-weight: 500; font-size: 15px; }
.wallet-option .w-go { color: var(--faint); font-size: 20px; }
.wallet-list .empty { text-align: center; color: var(--faint); padding: 14px; }

/* ---------------- wrong-network banner ---------------- */
.net-banner {
  position: fixed;
  top: 60px; left: 0; right: 0;
  z-index: 19;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 9px 14px;
  font-size: 13.5px;
  color: #3a2300;
  background: linear-gradient(180deg, #ffd86b, var(--gold));
}
.btn-switch {
  font-family: var(--display);
  font-weight: 600;
  font-size: 13px;
  color: #fff;
  background: #2a1d00;
  border: none;
  border-radius: 9px;
  padding: 6px 13px;
  cursor: pointer;
}
.btn-switch:disabled { opacity: 0.5; cursor: wait; }
#walletNet.wrong { color: var(--gold); }

/* ---------------- cashier ---------------- */
.bank-tabs { display: flex; gap: 6px; margin-bottom: 14px; }
.bank-tab { padding: 10px 6px; }
/* Its own scroll, so a long history lengthens a list rather than the card. */
#bankLog .board { max-height: 46vh; overflow-y: auto; margin-bottom: 4px; }
#bankLog .board li { flex-wrap: wrap; }
.log-when { width: 100%; font-size: 11px; color: var(--faint); }
.bank-tab {
  flex: 1;
  font-family: var(--display);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.8px;
  color: var(--faint);
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 10px;
  cursor: pointer;
}
.bank-tab.on { color: #fff; background: linear-gradient(135deg, var(--violet-hi), var(--pink)); border-color: transparent; }
.wide-input {
  font-family: ui-monospace, Menlo, monospace;
  font-size: 12px;
  color: var(--text);
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 11px 12px;
  width: 100%;
  margin-bottom: 9px;
}
.wide-input:focus { outline: none; border-color: var(--violet); }
.stake-row .unit { align-self: center; font-family: var(--display); font-weight: 600; color: var(--faint); flex: none; }
#depAmount, #wdPoints {
  flex: 1; font-family: var(--display); font-weight: 600; font-size: 19px; text-align: center;
  color: var(--text); background: var(--raised); border: 2px solid var(--border);
  border-radius: 14px; padding: 12px 8px; width: 100%; -moz-appearance: textfield;
}
#depAmount:focus, #wdPoints:focus { outline: none; border-color: var(--violet); }
#wdPoints::-webkit-outer-spin-button, #wdPoints::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.addr-code {
  font-family: ui-monospace, Menlo, monospace;
  font-size: 11px;
  color: var(--violet-hi);
  word-break: break-all;
  cursor: pointer;
}
.board .dim { color: var(--faint); }
.board a { color: var(--violet-hi); }

.fallback { margin: 10px 0 12px; text-align: left; }
.fallback summary { font-size: 13px; color: var(--faint); cursor: pointer; padding: 6px 0; }
.fallback summary:hover { color: var(--dim); }

/* ---- saved payout addresses ---- */
.saved-head { letter-spacing: 1px; color: var(--faint); margin-bottom: 7px; }
.saved-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 11px; }
.saved-row { display: flex; gap: 6px; align-items: stretch; }
.saved-pick {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-family: var(--font);
  font-size: 13px;
  color: var(--dim);
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 9px 12px;
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s, color 0.15s;
}
.saved-pick:hover { border-color: var(--violet); color: var(--text); }
.saved-pick.on { border-color: var(--violet); color: var(--text); background: rgba(139, 92, 255, 0.16); }
.saved-pick .nick { font-family: var(--display); font-weight: 600; color: var(--text); flex: none; }
.saved-pick .hex { font-family: ui-monospace, Menlo, monospace; font-size: 11px; color: var(--faint); }
.saved-pick.on .hex { color: var(--violet-hi); }
.saved-drop {
  flex: none;
  width: 36px;
  font-family: var(--font);
  font-size: 15px;
  color: var(--faint);
  background: transparent;
  border: 2px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.saved-drop:hover { color: var(--lose); border-color: var(--lose); }
#btnWdSave { margin-top: 0; margin-bottom: 10px; font-size: 13px; padding: 9px 14px; }

/* ==========================================================
 *  Wide screens.
 *
 *  The phone layout is one column and stays that way. Everything below only
 *  starts at 900px, where there is room to stop stacking: the lobby splits into
 *  "open a table" beside "tables waiting". A table in play deliberately does
 *  NOT split - it holds one width from the first hand to the last, so nothing
 *  moves under the cursor while a round is running.
 * ========================================================== */

/* ---- the lobby, two panes ---- */
.lobby {
  display: grid;
  gap: 16px;
  width: 100%;
  max-width: 440px;
  margin: 0 auto;
}
.lobby .card { max-width: none; }
.pane { padding: 24px 20px; }
.pane-head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-bottom: 16px;
}
.pane-head h2 { margin: 0; }
.count {
  font-family: var(--display);
  font-weight: 600;
  font-size: 13px;
  color: var(--violet-hi);
  background: rgba(139, 92, 255, 0.18);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 11px;
  min-width: 30px;
}

/* ---- stake presets ---- */
.presets {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-bottom: 16px;
}
.preset {
  font-family: var(--display);
  font-weight: 600;
  font-size: 16px;
  color: var(--dim);
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 13px;
  padding: 11px 4px;
  cursor: pointer;
  transition: transform 0.12s cubic-bezier(.34,1.56,.64,1), border-color 0.15s, color 0.15s, background 0.15s;
}
.preset:hover:not(:disabled) { border-color: var(--violet); color: var(--text); transform: translateY(-2px); }
.preset:active:not(:disabled) { transform: translateY(0); }
.preset.on {
  color: #fff;
  background: linear-gradient(135deg, var(--violet-hi), var(--pink));
  border-color: transparent;
  box-shadow: 0 4px 0 #6a3fd0;
}
.preset:disabled { opacity: 0.28; cursor: not-allowed; }

/* ---- the open tables, as cards ---- */
#rpsOpenList.tables { display: grid; gap: 10px; grid-template-columns: 1fr; margin-bottom: 0; }
#rpsOpenList.tables li {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 3px;
  padding: 15px 14px 13px;
  margin: 0;
  border-radius: 17px;
  background: var(--raised);
  border: 2px solid var(--border);
  transition: border-color 0.15s, transform 0.12s;
}
#rpsOpenList.tables li:hover { border-color: var(--violet); transform: translateY(-2px); }
#rpsOpenList.tables li.me { border-color: var(--violet); background: rgba(139,92,255,0.16); }
#rpsOpenList.tables li.empty,
#rpsOpenList.tables li.loading {
  grid-column: 1 / -1;
  align-items: center;
  background: transparent;
  border-style: dashed;
  color: var(--faint);
  padding: 26px 14px;
}
#rpsOpenList.tables li:hover.empty { transform: none; border-color: var(--border); }
.t-stake {
  font-family: var(--display);
  font-weight: 600;
  font-size: 30px;
  line-height: 1.1;
  color: var(--gold);
}
.t-stake em {
  font-family: var(--font);
  font-style: normal;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--faint);
  margin-left: 7px;
  vertical-align: 3px;
}
.t-line { font-size: 11.5px; color: var(--dim); letter-spacing: 0.2px; white-space: nowrap; }
.t-host {
  font-family: ui-monospace, Menlo, monospace;
  font-size: 11.5px;
  color: var(--dim);
  margin-bottom: 9px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#rpsOpenList.tables li button.sit { width: 100%; padding: 9px 12px; border-radius: 12px; }

/* ---- a table in play ---- */
.table-card { max-width: 440px; }
.table-grid { display: block; }
.table-actions { display: block; }

@media (min-width: 900px) {
  #stage { padding: calc(88px + var(--banner-h, 0px)) 26px 52px; }
  /* Line the top bar up with the content instead of hugging the window edge. */
  #topbar { padding: 0 max(18px, calc((100vw - 1180px) / 2)); }
  .brand-name {
    display: inline;
    font-family: var(--display);
    font-weight: 600;
    font-size: 15px;
    letter-spacing: 2.4px;
    color: var(--faint);
    margin-left: 12px;
    vertical-align: middle;
  }

  .lobby {
    grid-template-columns: 372px minmax(0, 1fr);
    align-items: start;
    gap: 20px;
    max-width: 1180px;
  }
  .pane { padding: 28px 24px; }
  .pane-tables { min-height: 420px; }
  .pane-head { justify-content: flex-start; }

  #rpsOpenList.tables { grid-template-columns: repeat(auto-fill, minmax(216px, 1fr)); gap: 12px; }

  /* The arena is drawn at a fixed size; letting it stretch across a 900px card
     would only make it soft. It stays its own size, centred. */
  #arena { max-width: 470px; margin: 0 auto 14px; }

  /* One width, start to finish - and that is still the rule. What changed is
     WHICH width: the card used to widen the moment a hand was sealed, which
     moved everything under the cursor mid-game. Below 1040px it stays one
     narrow column the whole time; above it, the evidence gets a column of its
     own from the moment you sit down, so nothing reflows when a hash arrives
     either. */
  .table-card { max-width: 560px; padding: 30px 28px; }
  .table-grid { text-align: center; }
  .table-side { display: block; }
  .table-actions { display: flex; gap: 12px; justify-content: center; }
  .table-actions .btn-primary, .table-actions .btn-ghost { width: auto; min-width: 220px; }
  .table-actions .btn-ghost { margin-top: 0; }

  .hand { padding: 16px 6px 13px; font-size: 13px; }
  .hand .ico { font-size: 38px; }
  .seat { padding: 12px 10px; }
}

/* A really wide window gets a third column of tables rather than four fat ones. */
@media (min-width: 1360px) {
  .lobby { max-width: 1320px; grid-template-columns: 392px minmax(0, 1fr); }
  #topbar { padding: 0 max(18px, calc((100vw - 1320px) / 2)); }
}

/* ---- how to get in from a phone ---- */
.phone-hint {
  font-size: 13px;
  line-height: 1.5;
  color: var(--dim);
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 14px;
  padding: 13px 14px;
  margin: 4px 0 0;
  text-align: left;
}
.phone-hint b { color: var(--text); font-weight: 700; }
.phone-hint .copy-btn { margin-top: 10px; }

/* ---- the ready check ---- */
.ready-box { margin-bottom: 14px; }
.ready-box .btn-primary { font-size: 19px; letter-spacing: 0.4px; }
.ready-box .btn-primary:disabled { opacity: 0.45; }

/* ---- the clock, where you can actually see it ---- */
.clock {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 3px;
  margin: -4px 0 12px;
  font-family: var(--display);
  line-height: 1;
  color: var(--dim);
  transition: color 0.2s;
}
.clock b { font-weight: 600; font-size: 46px; letter-spacing: -1px; }
.clock span { font-weight: 500; font-size: 17px; opacity: 0.75; }
/* The last few seconds are the ones worth noticing. */
.clock.soon { color: var(--gold); }
.clock.now { color: var(--lose); animation: clock-pulse 1s ease-in-out infinite; }
@keyframes clock-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.09); }
}
@media (prefers-reduced-motion: reduce) { .clock.now { animation: none; } }

/* ---- the two buttons people actually reach for ---- */
.chip-btn.big {
  width: 38px;
  height: 38px;
  font-size: 20px;
  line-height: 1;
  background: var(--raised);
  border: 1px solid var(--border);
}
.chip-btn.big:hover {
  background: rgba(139, 92, 255, 0.22);
  border-color: var(--violet);
  transform: translateY(-1px) scale(1.06);
}
.chip-btn.big:active { transform: translateY(0) scale(0.97); }
@media (min-width: 900px) {
  .chip-btn.big { width: 42px; height: 42px; font-size: 22px; }
}
/* Three buttons used to sit here and, at 375px, pushed the trophy 23px past the
   right edge. There is one now, so the address can stay until the screen is
   genuinely tiny. */
@media (max-width: 380px) {
  #walletAddr { display: none; }
  .wallet-chip { gap: 6px; }
  .brand-hands { font-size: 17px; letter-spacing: 1px; }
}

/* ---- results ---- */
.board-tab {
  flex: 1;
  font-family: var(--display);
  font-weight: 500;
  font-size: 12.5px;
  letter-spacing: 0.6px;
  color: var(--faint);
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 10px 6px;
  cursor: pointer;
}
.board-tab.on { color: #fff; background: linear-gradient(135deg, var(--violet-hi), var(--pink)); border-color: transparent; }
.scroll-list { max-height: 46vh; overflow-y: auto; }
/* The date sits on its own line, so it has to be allowed to take one - without
   this the row stays one line and squeezes the stake out of existence. */
#gamesList li { flex-wrap: wrap; }
.g-when { width: 100%; font-size: 11px; color: var(--faint); line-height: 1.35; }
#gamesList .addr { font-size: 13px; }
.g-out { font-family: var(--display); font-weight: 600; font-size: 14px; flex: none; }
.g-out.win { color: var(--win); }
.g-out.lose { color: var(--lose); }
.g-out.returned { color: var(--dim); }
.board li .delta-pts { font-family: var(--display); font-weight: 600; font-size: 15px; }
.board li .delta-pts.up { color: var(--win); }
.board li .delta-pts.down { color: var(--lose); }
.board li .delta-pts.flat { color: var(--faint); }

/* ---- the menu ----
   One button in the bar, everything else on a sheet under it. The language row
   is deliberately above the log-out row and below everything that needs a
   session: it is the only item that is worth anything to somebody who has not
   signed in yet, and they meet it on the sign-in screen. */
.top-right { display: flex; align-items: center; gap: 8px; min-width: 0; }

.menu-panel {
  position: fixed;
  top: 58px;
  right: 12px;
  width: min(280px, calc(100vw - 24px));
  padding: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: 0 18px 40px rgba(8, 4, 20, 0.55);
  z-index: 25;
  animation: menuIn 0.13s ease-out;
}
@keyframes menuIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) { .menu-panel { animation: none; } }

.menu-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  font-family: var(--font);
  font-weight: 700;
  font-size: 14.5px;
  text-align: left;
  color: var(--text);
  background: transparent;
  border: none;
  border-radius: 12px;
  padding: 11px 12px;
  cursor: pointer;
}
.menu-item:hover { background: var(--raised); }
.menu-item.danger { color: var(--lose); }
.mi-ico { font-size: 19px; line-height: 1; flex: none; width: 24px; text-align: center; }

.menu-sep { height: 1px; background: var(--border); margin: 7px 4px; }
.menu-head {
  margin: 2px 12px 7px;
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--faint);
}
.menu-langs { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 6px 4px; }
.lang-chip {
  font-family: var(--font);
  font-weight: 700;
  font-size: 13px;
  color: var(--dim);
  background: var(--raised);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 7px 12px;
  cursor: pointer;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.lang-chip:hover { color: var(--text); border-color: var(--violet); }
.lang-chip.on {
  color: #fff;
  background: linear-gradient(135deg, var(--violet-hi), var(--pink));
  border-color: transparent;
}

/* ---- provably fair ---- */
.fair-tab {
  flex: 1;
  font-family: var(--display);
  font-weight: 500;
  font-size: 11.5px;
  letter-spacing: 0.5px;
  color: var(--faint);
  background: var(--raised);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 10px 4px;
  cursor: pointer;
}
.fair-tab.on { color: #fff; background: linear-gradient(135deg, var(--violet-hi), var(--pink)); border-color: transparent; }

#fairOverlay > .card { max-width: 560px; text-align: left; }
.fair-pane { max-height: 56vh; overflow-y: auto; padding-right: 4px; }
.fair-step { margin-bottom: 15px; }
.fair-step h3 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 14.5px;
  color: var(--text);
  margin: 0 0 4px;
}
.fair-step p {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.6;
  color: var(--dim);
}
/* The one section that says what this scheme does NOT prove. It is the most
   useful thing on the page, so it does not get to look like the rest of it. */
.fair-step.warn {
  border-left: 3px solid var(--gold);
  padding-left: 12px;
}
.fair-step.warn h3 { color: var(--gold); }
.fair-formula {
  margin: 0 0 14px;
  padding: 10px 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow-x: auto;
  white-space: pre;
}

/* ---- prose that sits where a hex string usually goes ----
 *
 * Four boxes on this page are monospace because they normally hold an address
 * or a hash. They do not always: an empty seat says "chưa chọn", an
 * unconfigured cashier says "chưa cấu hình", a payout field is prompted with a
 * whole sentence, and a table card ends with "· bạn". Monospace faces are
 * chosen for their digits and very often have no Vietnamese tone marks at all,
 * so those words came out half in Menlo and half in whatever the browser
 * reached for next - the same mid-word split the display font had, in a corner
 * small enough to miss.
 *
 * The fix is not a better monospace font, which is the reader's machine to
 * decide. It is that prose was never monospace to begin with. */
.seal-row code.empty,
.addr-code.empty,
.t-mine {
  font-family: var(--font);
  letter-spacing: normal;
}
.wide-input::placeholder { font-family: var(--font); }

/* ---- the proof of a past game ---- */
/* The history row is a flex line that already wraps for the date, so the button
   goes on the end of it rather than into a column of its own. */
.proof-btn {
  font-family: var(--display);
  font-weight: 600;
  font-size: 10.5px;
  letter-spacing: 0.8px;
  color: var(--violet-hi);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 11px;
  margin-left: auto;
  cursor: pointer;
  flex: none;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.proof-btn:hover { color: #fff; background: rgba(139, 92, 255, 0.24); border-color: var(--violet); }

#proofOverlay > .card { max-width: 620px; text-align: left; }
#proofBody .v-row {
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--faint);
  word-break: break-all;
  margin-bottom: 7px;
}
/* The label and the hash are two different things and want two different
   fonts; without the break they ran together as "MATCHESkeccak256(" and the
   line read like a bug in the proof rather than a proof. */
#proofBody .v-head {
  display: block;
  font-family: var(--display);
  font-size: 12px;
  color: var(--text);
  margin-bottom: 3px;
  word-break: normal;
}
#proofBody .v-head .tick { color: var(--win); margin-left: 5px; }
#proofBody .v-head .cross { color: var(--lose); margin-left: 5px; }
#proofBody .fair-step.warn .v-row { font-family: var(--font); font-size: 12px; word-break: normal; }
#proofBody .fair-step.warn .tick { color: var(--win); }
#proofBody .fair-step.warn .cross { color: var(--lose); font-weight: 800; }
#proofBody .dim { color: var(--faint); }
#proofBody .loading { color: var(--faint); font-size: 13px; }

/* ---- the evidence, in a column of its own ----
 *
 * Wide enough for a 66-character hash without wrapping, present from the moment
 * the table opens so that nothing moves when the first hand is sealed, and
 * sticky so it is still beside you when the page scrolls to the hands. */
@media (min-width: 1040px) {
  .table-card { max-width: 980px; }
  .table-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 372px;
    gap: 26px;
    align-items: start;
    text-align: center;
  }
  /* The evidence column must not drive the card's height.
     
     The provably-fair panel arrives at the result carrying a line per hand, and
     because a grid row is as tall as its tallest item, the whole card grew by
     217px the instant a game ended - a jump at exactly the moment everyone is
     looking at the screen. `min-height: 0` lets this column be shorter than its
     own content, so the row is sized by the board on the left and this side
     scrolls instead of stretching. */
  .table-side {
    display: block;
    text-align: left;
    align-self: stretch;
    position: relative;
  }
  /* Out of flow ON PURPOSE. `min-height: 0` was not enough: an `auto` grid row
     is still as tall as its tallest item's content, so the panel arriving at
     the result stretched the row and with it the card. Taking the contents out
     of the flow entirely leaves the row to be sized by the board on the left,
     and this column scrolls inside whatever height that gives it. */
  .side-stack {
    position: absolute;
    inset: 0;
    overflow-y: auto;
    scrollbar-width: thin;
  }
  .table-side .sealed, .table-side .verify { margin-top: 0; }
  /* The column scrolls as one now; a second scroller inside it just traps the
     wheel. */
  .table-side .seal-list { max-height: none; overflow-y: visible; }
}

.seal-list { max-height: 46vh; overflow-y: auto; }
.seal-round { padding-bottom: 8px; margin-bottom: 8px; border-bottom: 1px solid var(--border); }
.seal-round:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }
/* The round being played reads as the live one; the rest are the record. */
.seal-round.now .seal-round-title { color: var(--gold); }
.seal-round.now code { color: var(--text); }
.seal-round-title {
  font-family: var(--display);
  font-size: 10.5px;
  letter-spacing: 1.2px;
  color: var(--faint);
  margin: 0 0 5px;
}
.seal-round code { color: var(--dim); }

/* ---- a table that does not move under you ----
 *
 * Measured before it was written. Across one hand the card swung 77px: the
 * clock (46px) drops out of the flow the moment it stops being your turn and
 * takes the seats up with it; the READY button (53px) and the three hands
 * (94px) trade places; the result (71px) arrives at the end. Every one of
 * those moved everything below it, which is why pressing a hand made the page
 * jump under the cursor.
 *
 * So the pieces that come and go get a fixed place to come and go INSIDE.
 * Reserved only once somebody has actually sat down - an open table has no
 * hand to play and would just show a hole. */
.clock.idle { visibility: hidden; }
.table-card:not(.seated) .clock.idle { display: none; }

.play-slot { display: block; }
.table-card.seated .play-slot {
  /* The largest it ever has to hold: the play-again button and the result of
     the game just finished, together, with room for a reason line under it. */
  min-height: 150px;
}
/* The phase line changes with every state and is longer in some languages than
   others; two lines' worth is reserved so the wrap does not shunt the buttons. */
.table-card.seated #rpsPhase { min-height: 38px; }
/* "Leave table" and "Back to the tables" are not the same height. */
.table-actions { min-height: 52px; }
.seat .state.blank { visibility: hidden; }

/* ---- the one line that has to be read before pasting an address ----
 *
 * An EVM address is valid on every EVM chain, so a wallet left on the wrong
 * network will send without complaint and the money will not arrive here. That
 * is not a footnote; it sits against the address itself, in the colour the rest
 * of the page uses for things that cost money. */
.chain-warn {
  margin: 10px 0 0;
  padding: 10px 12px;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.5;
  color: var(--gold);
  background: rgba(255, 210, 61, 0.08);
  border: 1px solid rgba(255, 210, 61, 0.35);
  border-radius: 12px;
  text-align: left;
}
