/* Hao's Mahjong — UI chrome. Lacquer-and-gold "premium engine" look:
 * Marcellus display serif, Inter UI, deep green-black palette, gold accents,
 * vignette depth. No backdrop-filter (it tanks FPS — see project notes). */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --ink:    #e8e2d2;
  --ink-dim:#8d9a8c;
  --gold:   #d4af6e;
  --gold-hi:#f0d9a8;
  --lac-0:  #060a08;
  --lac-1:  #0b120e;
  --lac-2:  #101b14;
  --line:   #24352a;
  --line-hi:#3f5a45;
  --accent: #2f8a50;
  --font-ui: 'Inter', 'Segoe UI', system-ui, sans-serif;
  --font-display: 'Marcellus', 'Times New Roman', serif;
}

body {
  background: var(--lac-0);
  overflow: hidden;
  font-family: var(--font-ui);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}
#canvas { display: block; position: fixed; inset: 0; }

/* cinematic depth over the 3D scene */
#vignette {
  position: fixed; inset: 0; z-index: 5; pointer-events: none;
  background:
    radial-gradient(ellipse 130% 100% at 50% 42%, transparent 55%, rgba(2,4,3,0.55) 100%),
    linear-gradient(to bottom, rgba(2,4,3,0.35), transparent 14%, transparent 88%, rgba(2,4,3,0.4));
}

/* ── Panels / lobby ─────────────────────────────────────────── */
#lobby {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(ellipse 90% 70% at 50% 38%, rgba(18,42,28,0.55), rgba(4,7,5,0.94)),
    linear-gradient(160deg, rgba(6,10,8,0.9), rgba(10,8,4,0.92));
  overflow-y: auto; padding: 20px 0;
}
/* ── lobby ambience: drifting tiles + swaying lanterns ──────────
   slow (19-25s loops), soft, transform/opacity-only — festive without
   being busy, easy on older eyes; fully disabled for reduced-motion */
#lobby-fx { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
#lobby .panel { z-index: 1; }
.fx-tile {
  position: absolute; bottom: -110px;
  width: 58px; height: 76px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-style: normal; font-size: 34px;
  background: linear-gradient(180deg, #f4eedb, #e6dec4);
  color: #1f7a3d; border: 1px solid rgba(0,0,0,0.35);
  box-shadow: 0 10px 26px rgba(0,0,0,0.45);
  opacity: 0;
  animation: fx-drift 22s linear infinite;
}
.fx-tile.red { color: #c1272d; }
.fx-tile.blue { color: #22578f; }
@keyframes fx-drift {
  0%   { transform: translateY(0) rotate(-7deg); opacity: 0; }
  8%   { opacity: 0.5; }
  85%  { opacity: 0.5; }
  100% { transform: translateY(-118vh) rotate(10deg); opacity: 0; }
}
.fx-lantern {
  position: absolute; top: -10px; font-size: 52px;
  transform-origin: 50% 0;
  filter: drop-shadow(0 6px 14px rgba(255,80,40,0.35));
  animation: fx-sway 5.6s ease-in-out infinite;
}
@keyframes fx-sway { 0%, 100% { transform: rotate(-6deg); } 50% { transform: rotate(6deg); } }
.crest { animation: crest-bob 5.5s ease-in-out infinite; }
@keyframes crest-bob {
  0%, 100% { transform: translateY(0); box-shadow: 0 0 22px rgba(212,175,110,0.15), 0 0 0 4px rgba(212,175,110,0.06); }
  50% { transform: translateY(-5px); box-shadow: 0 0 30px rgba(212,175,110,0.3), 0 0 0 4px rgba(212,175,110,0.1); }
}
#btn-solo { animation: btn-breathe 3.6s ease-in-out infinite; }
@keyframes btn-breathe {
  0%, 100% { box-shadow: 0 1px 0 rgba(255,255,255,0.06) inset, 0 4px 14px rgba(0,0,0,0.35); }
  50% { box-shadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 4px 22px rgba(47,138,80,0.5); }
}
@media (prefers-reduced-motion: reduce) {
  #lobby-fx *, .crest, #btn-solo { animation: none !important; }
  .fx-tile { opacity: 0.3; bottom: auto; top: 20%; }
}

.panel {
  width: 360px; max-width: 92vw;
  background: linear-gradient(172deg, #0d1610 0%, #0a100c 60%, #0c110a 100%);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 30px 32px 24px;
  display: flex; flex-direction: column; gap: 13px;
  box-shadow:
    0 1px 0 rgba(240,217,168,0.07) inset,
    0 0 0 1px rgba(0,0,0,0.6),
    0 30px 80px rgba(0,0,0,0.75);
  animation: panel-in .45s cubic-bezier(.2,.9,.3,1);
  position: relative;
}
.panel::before { /* gold hairline crown */
  content: ''; position: absolute; top: 0; left: 24px; right: 24px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(212,175,110,0.55), transparent);
}
@keyframes panel-in { from { opacity: 0; transform: translateY(14px) scale(.985); } }

.crest {
  width: 58px; height: 58px; margin: 0 auto;
  border: 1px solid rgba(212,175,110,0.5);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-size: 30px; color: var(--gold);
  box-shadow: 0 0 22px rgba(212,175,110,0.15), 0 0 0 4px rgba(212,175,110,0.06);
}
.panel h1 {
  font-family: var(--font-display); font-weight: 400;
  font-size: 30px; letter-spacing: 1px; color: var(--ink);
  text-align: center;
}
.panel h2 { font-family: var(--font-display); font-weight: 400; font-size: 22px; color: var(--ink); }
.tagline {
  font-size: 10px; color: var(--ink-dim); letter-spacing: 4px;
  text-transform: uppercase; text-align: center;
}
.credit { font-size: 10px; color: #4a5648; text-align: center; margin-top: 6px; letter-spacing: 1px; }
.credit b { color: #6e7f6a; }
.code { color: var(--gold-hi); font-family: monospace; letter-spacing: 5px; }

input, select {
  background: #0a0f0b; border: 1px solid var(--line); border-radius: 8px;
  color: var(--ink); padding: 10px 13px; font-size: 14px; width: 100%;
  outline: none; font-family: var(--font-ui);
  transition: border-color .2s, box-shadow .2s;
}
input:focus, select:focus { border-color: var(--line-hi); box-shadow: 0 0 0 3px rgba(63,90,69,0.2); }
.row { display: flex; gap: 8px; align-items: end; }
.row label {
  flex: 1; font-size: 10px; color: var(--ink-dim); letter-spacing: 2px;
  text-transform: uppercase; display: flex; flex-direction: column; gap: 5px;
}
.join-row input { width: 116px; text-transform: uppercase; letter-spacing: 4px; font-family: monospace; }
.join-row { align-items: stretch; }

.btn {
  background: linear-gradient(180deg, #14231a, #0e1912);
  border: 1px solid var(--line-hi); border-radius: 9px;
  color: #d5e4d3; padding: 10px 18px; font-size: 14px; cursor: pointer;
  font-family: var(--font-ui); font-weight: 600; letter-spacing: 0.4px;
  box-shadow: 0 1px 0 rgba(255,255,255,0.06) inset, 0 4px 14px rgba(0,0,0,0.35);
  transition: border-color .18s, box-shadow .18s, transform .08s, filter .18s;
}
.btn:hover { border-color: #5b8a63; filter: brightness(1.15); box-shadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 6px 20px rgba(0,0,0,0.45); }
.btn:active { transform: scale(0.975); }
.btn.primary {
  background: linear-gradient(180deg, #2a7a45, #1b5a31);
  border-color: #3f9c5e; color: #f2fff4;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}
.btn.gold {
  background: linear-gradient(180deg, #3a2f16, #2a2110);
  border-color: rgba(212,175,110,0.55); color: var(--gold-hi);
}
.btn.gold:hover { border-color: var(--gold); box-shadow: 0 0 18px rgba(212,175,110,0.2); }
.btn.big { padding: 13px 18px; font-size: 15px; }
.link-btn {
  background: none; border: none; color: #57685a; font-size: 12px;
  cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
  font-family: var(--font-ui);
}
.link-btn:hover { color: #92ab95; }
.divider {
  display: flex; align-items: center; gap: 12px;
  color: #55684f; font-size: 9px; letter-spacing: 3px; text-transform: uppercase;
}
.divider::before, .divider::after {
  content: ''; flex: 1; height: 1px;
  background: linear-gradient(90deg, transparent, #22352a);
}
.divider::after { background: linear-gradient(90deg, #22352a, transparent); }

.check-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--ink-dim); cursor: pointer; user-select: none;
}
.check-row input[type="checkbox"] {
  width: 15px; height: 15px; accent-color: var(--gold); cursor: pointer;
}

#stats-line { font-size: 11px; color: #5d6e60; text-align: center; margin-top: 4px; letter-spacing: 0.4px; }

#room-players { list-style: none; display: flex; flex-direction: column; gap: 6px; }
#room-players li {
  padding: 9px 13px; border: 1px dashed #263c2c; border-radius: 8px;
  font-size: 13px; color: #6d8271;
}
#room-players li.human {
  border-style: solid; color: var(--ink); border-color: var(--line-hi);
  background: rgba(30,54,36,0.25);
}

/* ── HUD ────────────────────────────────────────────────────── */
#hud {
  position: fixed; top: 16px; left: 50%; transform: translateX(-50%); z-index: 20;
  display: flex; gap: 18px; align-items: baseline;
  background: linear-gradient(180deg, rgba(12,20,14,0.92), rgba(8,13,9,0.88));
  border: 1px solid rgba(212,175,110,0.22); border-radius: 999px;
  padding: 8px 22px;
  box-shadow: 0 1px 0 rgba(240,217,168,0.06) inset, 0 8px 26px rgba(0,0,0,0.5);
  pointer-events: none;
}
#hud-round { font-family: var(--font-display); font-size: 14px; color: var(--gold-hi); letter-spacing: 1px; }
#hud-wall { font-size: 11px; color: var(--ink-dim); letter-spacing: 1px; }
#hud-turn { font-size: 11px; color: var(--gold); letter-spacing: 0.6px; }

#top-buttons { position: fixed; top: 14px; right: 16px; z-index: 20; display: flex; gap: 8px; }
#top-buttons button {
  background: rgba(10,16,11,0.9); border: 1px solid var(--line); border-radius: 9px;
  color: #9fb5a1; font-size: 15px; width: 38px; height: 36px; cursor: pointer;
  transition: border-color .2s, color .2s;
}
#top-buttons button:hover { border-color: var(--gold); color: var(--gold-hi); }

.plate {
  position: fixed; z-index: 15;
  display: flex; gap: 10px; align-items: center;
  background: linear-gradient(180deg, rgba(12,19,13,0.92), rgba(8,12,9,0.9));
  border: 1px solid var(--line);
  border-radius: 10px; padding: 7px 14px 7px 8px; font-size: 12px;
  pointer-events: none;
  box-shadow: 0 6px 18px rgba(0,0,0,0.45);
  transition: border-color .3s, box-shadow .3s;
}
.plate .p-wind {
  width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(212,175,110,0.4);
  color: var(--gold); font-size: 12px; font-family: var(--font-display);
  background: rgba(212,175,110,0.06);
  white-space: nowrap; overflow: hidden;
}
.plate .p-name { color: var(--ink); font-weight: 600; letter-spacing: 0.3px; }
.plate .p-score { color: var(--ink-dim); font-family: monospace; font-size: 12px; }
.plate.turn {
  border-color: rgba(212,175,110,0.75);
  box-shadow: 0 0 0 1px rgba(212,175,110,0.25), 0 0 24px rgba(212,175,110,0.22), 0 6px 18px rgba(0,0,0,0.45);
  animation: plate-pulse 2.2s ease-in-out infinite;
}
@keyframes plate-pulse {
  50% { box-shadow: 0 0 0 1px rgba(212,175,110,0.4), 0 0 34px rgba(212,175,110,0.34), 0 6px 18px rgba(0,0,0,0.45); }
}
.plate.me .p-name { color: var(--gold-hi); }
.plate.dealer .p-wind {
  border-color: var(--gold); color: var(--gold-hi);
  background: rgba(212,175,110,0.16);
  box-shadow: 0 0 10px rgba(212,175,110,0.3);
}
/* wild-flower curse badge — the seat can only win by self-draw */
.plate.cursed::after {
  content: '邪';
  margin-left: 6px; padding: 1px 5px; border-radius: 6px;
  font-size: 11px; font-family: var(--font-display);
  color: #ff9d85; border: 1px solid rgba(255,138,107,0.55);
  background: rgba(120,30,16,0.35);
}
.plate[data-rel="0"] { bottom: 122px; left: 18px; }
.plate[data-rel="1"] { right: 18px; top: 50%; transform: translateY(-50%); }
.plate[data-rel="2"] { top: 66px; left: 50%; transform: translateX(-50%); }
.plate[data-rel="3"] { left: 18px; top: 50%; transform: translateY(-50%); }

/* the viewer's own melds + flowers as small 2D tiles right of the "You"
   plate (the 3D copies hide under the HUD stack on phones); `left` is set
   live in JS off the plate's actual width */
#my-exposed {
  position: fixed; left: 170px; bottom: 124px; z-index: 14;
  display: none; align-items: center; gap: 2px; flex-wrap: wrap;
  max-width: calc(100vw - 190px); pointer-events: none;
}
#my-exposed canvas {
  width: 28px; height: auto; aspect-ratio: 3 / 4; border-radius: 3px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.55), 0 0 0 1px rgba(0,0,0,0.25);
}
#my-exposed canvas.gap { margin-left: 8px; }
#my-exposed canvas.gap:first-child { margin-left: 0; }
body.showdown-on #my-exposed { visibility: hidden; }

/* the winner's full hand in the result card — scoring tiles glow gold,
   the winning tile wears a blue ring */
.win-hand { display: flex; flex-wrap: wrap; align-items: center; gap: 3px; margin: 4px 0 10px; }
.win-hand .wh-tile {
  width: 34px; height: auto; aspect-ratio: 3 / 4; border-radius: 4px;
  box-shadow: 0 2px 5px rgba(0,0,0,0.45);
}
.win-hand .wh-tile.hl {
  box-shadow: 0 0 0 2px var(--gold), 0 0 14px rgba(212,175,110,0.65);
}
.win-hand .wh-tile.win-tile {
  box-shadow: 0 0 0 2px #7ac6ff, 0 0 14px rgba(122,198,255,0.7);
  transform: translateY(-3px);
}
.win-hand .wh-gap { width: 7px; flex: none; }

/* the flower replacement mid-drag from the wall's tail to the hand */
.tail-ghost {
  position: fixed; width: 34px; height: 45px; z-index: 60;
  pointer-events: none; border-radius: 4px;
  box-shadow: 0 6px 14px rgba(0,0,0,0.55), 0 0 0 1px rgba(0,0,0,0.3);
}

/* showdown: everyone's hand is revealed top-down — pull the plates out of
   the play area and into the screen corners (the top plate used to sit
   directly ON the revealed hand) and shrink them so the tiles read */
body.showdown-on .plate { transition: all .4s; opacity: 0.88; transform: scale(0.82); }
body.showdown-on .plate[data-rel="0"] { bottom: 8px; left: 8px; transform: scale(0.82); }
body.showdown-on .plate[data-rel="1"] { right: 8px; top: 8px; transform: scale(0.82); }
body.showdown-on .plate[data-rel="2"] { top: 8px; left: 8px; transform: scale(0.82); }
body.showdown-on .plate[data-rel="3"] { left: 8px; bottom: 60px; top: auto; transform: scale(0.82); }
body.showdown-on #mini-hand, body.showdown-on #actions { display: none; }

/* ── Discard callout ("Kang discards [tile]") ───────────────── */
#discard-callout {
  position: fixed; top: 108px; left: 50%; z-index: 22;
  transform: translateX(-50%) translateY(-6px) scale(.94);
  display: flex; align-items: center; gap: 12px;
  background: linear-gradient(180deg, rgba(14,22,15,0.96), rgba(9,14,10,0.94));
  border: 1px solid rgba(212,175,110,0.4); border-radius: 12px;
  padding: 8px 16px 8px 8px;
  box-shadow: 0 0 30px rgba(212,175,110,0.12), 0 12px 34px rgba(0,0,0,0.55);
  opacity: 0; pointer-events: none;
  transition: opacity .18s, transform .22s cubic-bezier(.2,.9,.3,1.4);
}
#discard-callout.show { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
#discard-callout canvas { border-radius: 5px; box-shadow: 0 3px 8px rgba(0,0,0,0.5); }
/* a claimed set shows ALL its tiles — smaller each so 3-4 fit the card */
#discard-callout.multi canvas { width: 40px; height: auto; }
#discard-callout .dc-label span.act-chow { color: #7ac6ff; }
#discard-callout .dc-label span.act-pung { color: #ffd782; }
#discard-callout .dc-label span.act-kong { color: #d78bff; }
#discard-callout .dc-label { display: flex; flex-direction: column; gap: 1px; }
#discard-callout .dc-label b { font-size: 14px; color: var(--ink); }
#discard-callout .dc-label span {
  font-size: 9px; color: var(--ink-dim); letter-spacing: 2.5px; text-transform: uppercase;
}

/* ── Actions / claim bar ────────────────────────────────────── */
#actions {
  /* clears the mini-hand strip at its extra-large default (48px × 1.6 tile
     + padding ≈ 105px from the bottom edge) */
  position: fixed; bottom: 126px; left: 50%; transform: translateX(-50%);
  z-index: 25; display: none; gap: 10px;
}
.act-btn {
  background: linear-gradient(180deg, rgba(16,26,18,0.97), rgba(10,17,12,0.97));
  border: 1px solid var(--line-hi); border-radius: 11px;
  color: #d5e4d3; padding: 11px 20px; font-size: 15px; font-weight: 700;
  cursor: pointer; letter-spacing: 0.6px; font-family: var(--font-ui);
  box-shadow: 0 1px 0 rgba(255,255,255,0.06) inset, 0 10px 26px rgba(0,0,0,0.55);
  transition: border-color .15s, filter .15s, transform .08s;
  animation: act-in .22s cubic-bezier(.2,.9,.3,1.3);
}
@keyframes act-in { from { opacity: 0; transform: translateY(10px); } }
.act-btn small { display: block; font-size: 10px; font-weight: 400; color: var(--ink-dim); }
.act-btn:hover { filter: brightness(1.2); }
.act-btn:active { transform: scale(.96); }
.act-btn.win {
  border-color: var(--gold); color: var(--gold-hi);
  background: linear-gradient(180deg, #3a2f16, #241c0c);
  box-shadow: 0 0 24px rgba(212,175,110,0.25), 0 10px 26px rgba(0,0,0,0.55);
}
.act-btn.pass { color: #7e8f82; }
.act-btn.hint { color: #9db8e8; border-color: #33465e; }
#claim-timer {
  position: fixed; bottom: 116px; left: 50%; transform: translateX(-50%);
  height: 3px; width: 180px; border-radius: 2px;
  background: linear-gradient(90deg, var(--gold), var(--gold-hi));
  box-shadow: 0 0 10px rgba(212,175,110,0.5);
  z-index: 25; display: none;
}

/* ── Mini hand strip ────────────────────────────────────────── */
#mini-hand {
  position: fixed; bottom: 12px; left: 50%; transform: translateX(-50%);
  z-index: 20; display: flex; gap: 5px; padding: 8px 10px;
  background: linear-gradient(180deg, rgba(10,15,11,0.75), rgba(6,10,7,0.85));
  border: 1px solid rgba(36,53,42,0.8);
  border-radius: 13px;
  box-shadow: 0 1px 0 rgba(240,217,168,0.05) inset, 0 10px 30px rgba(0,0,0,0.5);
  max-width: 96vw; overflow-x: auto;
  scrollbar-width: none;       /* Firefox */
  -ms-overflow-style: none;    /* legacy Edge */
}
#mini-hand::-webkit-scrollbar { display: none; }  /* Chrome/Safari/Edge */
.mini-tile {
  /* --tile-scale is set on <html> from the "Tile size" setting (default
     Large, 1.3 — kinder to older eyes); the strip already scrolls
     horizontally, so bigger tiles just scroll a little more */
  width: calc(36px * var(--tile-scale, 1.6)); height: calc(48px * var(--tile-scale, 1.6)); border-radius: 5px; cursor: grab;
  border: 1px solid rgba(0,0,0,0.5);
  box-shadow: 0 2px 5px rgba(0,0,0,0.4);
  transition: transform .13s, box-shadow .13s;
  /* must be set here, not via JS after a hold timer — the browser's native
     scroll-gesture recognizer (since #mini-hand is horizontally scrollable)
     decides within the first couple of touchmove samples, well under the
     old 160ms "arm" delay, and cancels the whole pointer sequence
     (pointercancel) once it claims the touch as a scroll. That raced the
     JS-driven touchAction='none' and silently killed real device drags. */
  touch-action: none;
}
.mini-tile:hover { transform: translateY(-5px); }
.mini-tile.sel {
  transform: translateY(-9px);
  box-shadow: 0 0 0 1px var(--gold), 0 0 16px rgba(212,175,110,0.55), 0 6px 12px rgba(0,0,0,0.5);
}
.mini-tile.dragging {
  cursor: grabbing; transition: none; z-index: 6;
  box-shadow: 0 0 0 1px var(--gold), 0 16px 30px rgba(0,0,0,0.6);
}
.mini-tile.toss-ready {
  box-shadow: 0 0 0 1px #ff8a6b, 0 0 22px rgba(255,138,107,0.55), 0 16px 30px rgba(0,0,0,0.6);
}
/* claim window: the tiles forming each claimable set glow in the set's
   color (matching its button) and lift — tap the set to claim it */
.mini-tile.claim-hl {
  transform: translateY(-7px);
  animation: claim-pulse 1.1s ease-in-out infinite;
}
.mini-tile.claim-pung { box-shadow: 0 0 0 2px #ffd782, 0 0 16px rgba(255,215,130,0.6), 0 6px 12px rgba(0,0,0,0.5); }
.mini-tile.claim-kong { box-shadow: 0 0 0 2px #d78bff, 0 0 16px rgba(215,139,255,0.6), 0 6px 12px rgba(0,0,0,0.5); }
.mini-tile.claim-chow { box-shadow: 0 0 0 2px #7ac6ff, 0 0 16px rgba(122,198,255,0.6), 0 6px 12px rgba(0,0,0,0.5); }
@keyframes claim-pulse { 50% { transform: translateY(-3px); } }

/* the tile just drawn this turn — a cool glow distinct from the warm
   "about to discard" selection, visible even when also selected */
.mini-tile.drawn:not(.sel) {
  transform: translateY(-6px);
  box-shadow: 0 0 0 1px rgba(122,180,232,0.6), 0 0 13px rgba(122,180,232,0.45), 0 4px 10px rgba(0,0,0,0.4);
}

/* ── Dice ceremony ──────────────────────────────────────────── */
#dice-ceremony {
  position: fixed; inset: 0; z-index: 40;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
  background: radial-gradient(ellipse 70% 60% at 50% 45%, rgba(10,16,11,0.55), rgba(3,5,4,0.82));
  pointer-events: none;
}
/* it's the human's throw — the overlay takes input and invites the fling.
   user-select: none everywhere in the ceremony — without it the drag was
   sweeping a text selection across the whole page */
#dice-ceremony, #dice-ceremony * { user-select: none; -webkit-user-select: none; }
#dice-ceremony.throwable { pointer-events: auto; cursor: grab; touch-action: none; }
#dice-ceremony.throwable:active { cursor: grabbing; }
#dice-ceremony.throwable .dc-caption { color: var(--gold-hi); animation: dc-invite 2.2s ease-in-out infinite; }
@keyframes dc-invite { 50% { opacity: 0.55; } }
.dc-dice { display: flex; gap: 16px; }
.dc-dice .die {
  font-size: 56px; line-height: 1; color: var(--gold-hi);
  text-shadow: 0 0 24px rgba(212,175,110,0.4), 0 6px 16px rgba(0,0,0,0.6);
  animation: die-pop .18s ease;
}
@keyframes die-pop { from { transform: scale(0.7) rotate(-8deg); opacity: 0.4; } }
.dc-caption {
  font-family: var(--font-display); font-size: 19px; letter-spacing: 1px;
  color: var(--ink); text-shadow: 0 2px 14px rgba(0,0,0,0.8);
  text-align: center; max-width: 80vw;
}

/* ── Shuffle mode ───────────────────────────────────────────── */
#shuffle-ui { position: fixed; inset: 0; z-index: 30; pointer-events: none; }
.shuffle-hint {
  position: absolute; top: 26px; left: 50%; transform: translateX(-50%);
  font-family: var(--font-display); font-size: 15px; letter-spacing: 2px;
  color: var(--gold-hi); opacity: 0.85;
  text-shadow: 0 2px 12px rgba(0,0,0,0.8);
  animation: hint-float 3s ease-in-out infinite;
}
@keyframes hint-float { 50% { transform: translateX(-50%) translateY(4px); opacity: 0.6; } }
#btn-shuffle-done {
  position: absolute; bottom: 34px; left: 50%; transform: translateX(-50%);
  pointer-events: auto;
}
body.shuffle-on #hud, body.shuffle-on .plate, body.shuffle-on #mini-hand,
body.shuffle-on #actions, body.shuffle-on #discard-callout,
body.shuffle-on #drag-layer { display: none !important; }

/* a currently-dragged/tossed tile floats here (re-parented out of
   #mini-hand for the gesture's duration) — above the gameplay HUD/actions
   so it's never clipped, but below toast/modal so those still read on top */
#drag-layer { position: fixed; inset: 0; z-index: 27; pointer-events: none; }
#drag-layer .mini-tile { pointer-events: auto; }

/* ── Toast / modal ──────────────────────────────────────────── */
#toast {
  position: fixed; top: 64px; left: 50%; transform: translateX(-50%) translateY(-8px);
  z-index: 90;
  background: linear-gradient(180deg, rgba(14,22,15,0.97), rgba(9,14,10,0.95));
  border: 1px solid var(--line-hi);
  color: var(--ink); border-radius: 10px; padding: 10px 20px; font-size: 13px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.55);
  opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

#modal {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(3,5,4,0.72);
  display: flex; align-items: center; justify-content: center;
}
.modal-card { width: 410px; }
.modal-card h2 { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.modal-card h2 em {
  font-style: normal; font-family: var(--font-ui); font-size: 13px;
  color: var(--gold); letter-spacing: 1px;
  border: 1px solid rgba(212,175,110,0.4); border-radius: 999px; padding: 2px 10px;
}
.modal-card p { font-size: 13px; line-height: 1.55; color: #aebcb0; }
.modal-card .dim { color: var(--ink-dim); font-size: 12px; }
#modal-buttons { display: flex; gap: 10px; margin-top: 8px; flex-wrap: wrap; }

/* showdown: dock the card to the side, keep the revealed table visible */
#modal.side-mode {
  background: none; pointer-events: none;
  align-items: flex-start; justify-content: flex-end;
  padding: 84px 26px 0 0;
}
#modal.side-mode .modal-card {
  pointer-events: auto; width: 330px;
  box-shadow: 0 1px 0 rgba(240,217,168,0.07) inset, 0 0 0 1px rgba(0,0,0,0.55),
    0 24px 60px rgba(0,0,0,0.65), 0 0 40px rgba(212,175,110,0.07);
}

.fan-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.fan-table td { padding: 6px 4px; border-bottom: 1px solid rgba(26,38,29,0.9); color: #b9c7ba; }
.fan-table td:last-child { text-align: right; color: var(--gold); font-family: monospace; }
.fan-table tr.total td {
  font-weight: 700; color: var(--gold-hi); border-bottom: none;
  font-family: var(--font-display); letter-spacing: 0.5px;
}
.share-box {
  background: #0a0f0b; border: 1px dashed rgba(212,175,110,0.35); border-radius: 9px;
  padding: 11px 14px; font-size: 12px; color: #b9c9a9; font-family: monospace;
  margin: 8px 0;
}

/* ── Small screens ──────────────────────────────────────────── */
@media (max-width: 760px) {
  .plate[data-rel="1"], .plate[data-rel="3"] { display: none; }
  /* the 2-row strip is ~150-172px tall (two 68-72px tile rows + gaps +
     padding + its 12px bottom offset) — everything stacked above it must
     clear the WORST case or it hides behind the strip: strip → your plate
     → the action bar, bottom-up */
  .plate[data-rel="0"] { bottom: 184px; left: 8px; padding: 6px 12px 6px 7px; }
  /* opponent plate must clear the HUD pill below it — see #hud stacking below */
  .plate[data-rel="2"] { top: 76px; }

  /* exposed melds/flowers row: aligned with the phone plate's raised spot;
     per-tile width is set inline by renderMyExposed (it knows the count,
     so the row fills the space beside the plate at any meld count) */
  #my-exposed { bottom: 186px; gap: 2px; }
  #my-exposed canvas { border-radius: 2px; }
  #my-exposed canvas.gap { margin-left: 6px; }

  /* stacked (2-line) AND left-anchored instead of viewport-centered: a
     centered pill overlaps #top-buttons' fixed ~140px right-side zone
     REGARDLESS of how narrow it is (centering math alone can't avoid it —
     confirmed via getBoundingClientRect on a 390px-wide viewport, not just
     eyeballed), since #top-buttons' left edge sits well inside the right
     half of the screen. */
  #hud {
    left: 12px; transform: none; max-width: 58vw;
    padding: 6px 16px; gap: 1px;
    flex-direction: column; align-items: flex-start; text-align: left;
  }
  #hud-round { font-size: 11px; line-height: 1.3; }
  #hud-wall { font-size: 10px; }

  /* was directly under the HUD's old (wider, shorter) footprint; now clears
     the stacked HUD AND the repositioned plate[data-rel="2"] below it */
  #discard-callout { top: 128px; }

  /* showdown corner-parking: the top-left corner belongs to the (left-
     anchored) mobile HUD, so the across-seat plate tucks under it instead */
  body.showdown-on .plate[data-rel="2"] { top: 72px; left: 8px; transform: scale(0.78); }

  #actions {
    bottom: 234px; width: 94vw; flex-wrap: wrap; justify-content: center; gap: 8px;
  }
  /* larger touch targets — the old 36px-tall buttons were under the ~44px
     minimum comfortable tap size */
  .act-btn { padding: 12px 16px; font-size: 13px; min-height: 44px; }
  #claim-timer { bottom: 222px; }

  /* on a phone the hand wraps into TWO rows of seven, so the whole hand is
     visible at once with no scrolling — and each tile is actually BIGGER
     than the old single scrolling row allowed. The grid must stay
     row-major and left-anchored (flex-start): the drag math derives slot
     positions from a fixed origin, so centered rows would break it. */
  /* tight padding and gaps — every pixel saved goes straight into tile
     size for older eyes. The row math keeps real slack (−36px covers the
     6px×2 padding + six 3px gaps + a rounding margin): tiles sized to
     EXACTLY fill the row let sub-pixel rounding push the 7th tile onto a
     third row — the hand must never exceed two rows. */
  #mini-hand {
    flex-wrap: wrap; gap: 3px; row-gap: 4px; padding: 6px;
    width: 96vw; overflow-x: hidden;
    justify-content: flex-start;
  }
  .mini-tile {
    width: min(calc(33px * var(--tile-scale, 1.6)), calc((96vw - 36px) / 7));
    height: auto; aspect-ratio: 3 / 4;
  }

  #top-buttons button { width: 42px; height: 42px; }

  /* the result card becomes a BOTTOM SHEET on phones: the portrait
     showdown pans the table to the top of the screen, leaving the lower
     band empty — a right-docked card just floated over the reveal while
     that space went unused. Sits above the corner-parked "You" plate. */
  #modal.side-mode {
    align-items: flex-end; justify-content: center;
    padding: 0 8px 60px;
  }
  #modal.side-mode .modal-card { width: 94vw; max-width: 430px; }
  /* winning-hand tiles: 8 per row max on the bottom-sheet card */
  .win-hand .wh-tile { width: min(34px, calc((94vw - 90px) / 8)); }
}

/* ── Very small screens (compact phones, e.g. iPhone SE) ───────── */
@media (max-width: 380px) {
  #hud { max-width: 46vw; padding: 5px 12px; }
  #hud-round { font-size: 10px; }
  #hud-wall { font-size: 9px; }
  .plate .p-name { max-width: 70px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mini-tile {
    width: min(calc(29px * var(--tile-scale, 1.6)), calc((96vw - 36px) / 7));
    height: auto; aspect-ratio: 3 / 4;
  }
  /* on the narrowest common width (iPhone SE, 320px) the HUD's right edge
     and #top-buttons' left edge land exactly adjacent with zero gap —
     shrink the button cluster a touch so there's visible breathing room */
  #top-buttons { gap: 6px; }
  #top-buttons button { width: 36px; height: 36px; font-size: 13px; }
}

/* ══ Lobby v2 — modern, minimal (round 35) ═══════════════════════════════
   Scoped to #lobby so the in-game modals/HUD keep their gold-lacquer look.
   Neutral graphite panel, Inter type, a single emerald accent, and one
   quiet nod to the game: a minimalist ivory tile with a red one-dot. */
#lobby {
  background:
    radial-gradient(1100px 700px at 72% -12%, #14201b 0%, rgba(11,13,15,0) 60%),
    #0b0d0f;
}
#lobby-fx .fx-blob { position: absolute; border-radius: 50%; pointer-events: none; will-change: transform; }
#lobby-fx .b1 {
  width: 560px; height: 560px; left: -160px; top: -180px;
  background: radial-gradient(circle at 38% 38%, rgba(16,185,129,0.12), transparent 65%);
  animation: blob-drift 26s ease-in-out infinite alternate;
}
#lobby-fx .b2 {
  width: 680px; height: 680px; right: -220px; top: 20%;
  background: radial-gradient(circle at 60% 42%, rgba(56,189,248,0.06), transparent 65%);
  animation: blob-drift 34s ease-in-out infinite alternate-reverse;
}
#lobby-fx .b3 {
  width: 480px; height: 480px; left: 26%; bottom: -240px;
  background: radial-gradient(circle at 50% 50%, rgba(16,185,129,0.07), transparent 60%);
  animation: blob-drift 40s ease-in-out infinite alternate;
}
@keyframes blob-drift { from { transform: translate(0, 0); } to { transform: translate(48px, -36px); } }
@media (prefers-reduced-motion: reduce) { #lobby-fx .fx-blob { animation: none; } }

#lobby .panel {
  background: #111416;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 18px;
  box-shadow: 0 24px 64px rgba(0,0,0,0.55);
}
/* the crest becomes a minimalist ivory tile with a red one-dot */
#lobby-main .crest {
  width: 54px; height: 68px;
  border: none; border-radius: 12px;
  background: linear-gradient(165deg, #f7f4ea 0%, #e6e1d2 78%, #cfc9b6 100%);
  box-shadow: 0 6px 16px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.7);
  position: relative;
  animation: none;
}
#lobby-main .crest span { display: none; } /* the 雀 glyph retires */
#lobby-main .crest::after {
  content: ''; position: absolute; inset: 0; margin: auto;
  width: 16px; height: 16px; border-radius: 50%;
  background: radial-gradient(circle at 38% 34%, #d6403c, #a91f1c 70%);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.35);
}
#lobby-main h1 {
  font-family: 'Inter', -apple-system, sans-serif;
  font-weight: 700; letter-spacing: -0.4px;
  color: #f1f4f2; text-shadow: none;
}
#lobby-main .tagline { color: #77817c; letter-spacing: 2.5px; }

#lobby input, #lobby select {
  background: #191d1f;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  color: #e6e9e7;
}
#lobby input:focus, #lobby select:focus {
  border-color: rgba(16,185,129,0.55);
  outline: none;
  box-shadow: 0 0 0 3px rgba(16,185,129,0.12);
}
#lobby label { color: #7d8783; }
#lobby .check-row { color: #aeb6b1; }

#lobby .btn {
  border-radius: 12px;
  border: 1px solid rgba(255,255,255,0.1);
  background: #1a1f21;
  color: #e6e9e7;
  font-weight: 600;
  letter-spacing: 0.2px;
  text-shadow: none;
}
#lobby .btn:hover { background: #21272a; border-color: rgba(255,255,255,0.16); }
#lobby .btn.primary {
  background: linear-gradient(170deg, #12b981, #0d9668);
  border: none; color: #052e21;
  box-shadow: 0 8px 22px rgba(16,185,129,0.22);
  animation: none; /* the old "breathing" pulse retires */
}
#lobby .btn.primary:hover { background: linear-gradient(170deg, #17c98d, #0fa371); }
#lobby .btn.gold {
  background: transparent;
  border: 1px solid rgba(233,196,124,0.35);
  color: #e9c47c;
  box-shadow: none;
}
#lobby .btn.gold:hover { background: rgba(233,196,124,0.08); border-color: rgba(233,196,124,0.55); }

#lobby .divider { color: #5d6663; letter-spacing: 3px; }
#lobby .divider::before, #lobby .divider::after { background: rgba(255,255,255,0.08); }
#lobby #stats-line { color: #77817c; }
#lobby .link-btn { color: #8b9590; }
#lobby .link-btn:hover { color: #c9d1cd; }
#lobby .credit { color: #565f5b; }
#lobby .credit b { color: #8b9590; }
#lobby #room-players li { border-color: rgba(255,255,255,0.07); }
#lobby .panel::before { display: none; } /* the gold hairline crown retires in the lobby */

/* lobby v2, desktop layout: the 360px single column wasted a widescreen —
   two columns (play | settings + friends) in one wide panel. Phones keep
   the stacked flow: .lob-hero and .lob-side are plain columns there. */
.lob-hero, .lob-side { display: flex; flex-direction: column; gap: 13px; min-width: 0; }
@media (min-width: 880px) {
  #lobby-main {
    width: 820px; max-width: 94vw;
    flex-direction: row; align-items: stretch; gap: 0;
    padding: 36px 40px 30px;
  }
  #lobby-main .lob-hero { flex: 1.04; padding-right: 38px; justify-content: center; }
  #lobby-main .lob-side {
    flex: 1; padding-left: 38px; justify-content: center;
    border-left: 1px solid rgba(255,255,255,0.06);
  }
  #lobby-main h1 { font-size: 34px; }
  #lobby-main .crest { width: 60px; height: 76px; }
}

/* lobby v2.1: mode cards + settings page (round 36) */
#lobby .mode-btn {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 12px 18px;
}
#lobby .mode-btn b { font-size: 15px; font-weight: 600; }
#lobby .mode-sub { font-size: 11px; font-weight: 400; color: #7d8783; letter-spacing: 0.2px; }
#lobby .btn.primary .mode-sub { color: rgba(5,46,33,0.72); }
#lobby .btn.gold .mode-sub { color: rgba(233,196,124,0.62); }
.lob-foot { display: flex; flex-direction: column; align-items: center; gap: 7px; margin-top: 4px; }
.lob-links { display: flex; gap: 20px; justify-content: center; }
@media (min-width: 880px) {
  #lobby-main { flex-wrap: wrap; row-gap: 10px; }
  #lobby-main .lob-foot { flex-basis: 100%; margin-top: 12px; }
}
#settings-panel h2 { text-align: center; font-family: 'Inter', sans-serif; font-weight: 700; color: #f1f4f2; }
