:root {
  color-scheme: dark;
  font-family: "Microsoft YaHei", "PingFang SC", system-ui, sans-serif;
  /* User-locked visual master. Runtime state may change tile content and
   * counts, but all table geometry stays on this one coordinate plane. */
  --master-width: 1488;
  --master-height: 805;
  --master-aspect: 1488 / 805;
  --felt-deep: #075044;
  --felt: #0a7463;
  --felt-light: #12937b;
  --gold: #d7aa55;
  --gold-soft: #f5d995;
  --wood: #59331d;
  --cream: #f6f1e5;
  --ink: #18231e;
  --red: #b93225;
  --green: #157347;
  --tile-width: clamp(46px, 5.9vw, 100px);
  --tile-height: calc(var(--tile-width) * 1.34);
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
}

* {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
  background:
    radial-gradient(circle at 50% 20%, #24362d 0, #0b1713 50%, #050a08 100%);
}

button {
  font: inherit;
}

.runtime-error {
  position: fixed;
  z-index: 9999;
  top: 12px;
  right: 12px;
  max-width: min(760px, 90vw);
  max-height: 45vh;
  margin: 0;
  padding: 14px 18px;
  overflow: auto;
  border: 1px solid #ff8f7c;
  border-radius: 10px;
  color: #ffeae6;
  background: rgb(75 17 12 / 94%);
  box-shadow: 0 12px 32px rgb(0 0 0 / 48%);
  font: 13px/1.5 Consolas, monospace;
  white-space: pre-wrap;
}

.app-shell {
  display: grid;
  width: 100%;
  height: 100%;
  place-items: center;
  padding: 0;
}

/* Real mobile browsers do not all honor ScreenOrientation.lock().  When a
 * game route is still reported as portrait, render the accepted landscape
 * table on a landscape-sized coordinate plane and rotate that plane into the
 * physical viewport.  This is game-page-only; the portrait account/room
 * portal uses mobile.css and is intentionally unaffected. */
html.mobile-landscape-fallback,
html.mobile-landscape-fallback body {
  width: 100dvw;
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
}

html.mobile-landscape-fallback .app-shell {
  position: fixed;
  top: 0;
  left: 0;
  width: var(--forced-landscape-width) !important;
  height: var(--forced-landscape-height) !important;
  min-width: 0 !important;
  min-height: 0 !important;
  transform: translateX(var(--forced-landscape-height)) rotate(90deg);
  transform-origin: top left;
}

html.mobile-landscape-fallback .game-table {
  width: 100% !important;
  height: 100% !important;
  min-width: 0 !important;
  min-height: 0 !important;
  aspect-ratio: auto !important;
}

html.mobile-landscape-fallback .mobile-rotate-hint {
  display: none !important;
}

/* Deterministic 1488×805 visual QA surface. This is query-gated by
 * `qaViewport=mobile-landscape` and never changes a real device viewport. */
html.qa-mobile-landscape,
html.qa-mobile-landscape body,
html.qa-mobile-landscape .app-shell,
html.qa-mobile-landscape .game-table {
  width: 1488px;
  height: 805px;
}

html.qa-mobile-landscape .game-table {
  width: 1488px !important;
  height: 805px !important;
  flex: 0 0 1488px;
  aspect-ratio: 1488 / 805;
}

.game-table {
  position: relative;
  width: min(100vw, calc(100vh * var(--master-width) / var(--master-height)));
  height: min(100vh, calc(100vw * var(--master-height) / var(--master-width)));
  aspect-ratio: var(--master-aspect);
  container-type: size;
  overflow: hidden;
  border-radius: 0;
  background: #14231d;
  box-shadow:
    0 28px 80px rgb(0 0 0 / 55%),
    inset 0 0 0 1px rgb(255 255 255 / 8%);
  isolation: isolate;
  user-select: none;
}

.scene-canvas {
  position: absolute;
  z-index: 2;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  outline: none;
  pointer-events: none;
}

.visual-master {
  display: none;
}

.game-table.has-webgl {
  background:
    radial-gradient(circle at 12% 5%, rgb(112 79 40 / 24%), transparent 26%),
    radial-gradient(circle at 88% 7%, rgb(79 93 61 / 18%), transparent 24%),
    linear-gradient(180deg, #17130e 0%, #0a1511 30%, #050c0a 100%);
  box-shadow: none;
}

.game-table.has-webgl .wood-frame,
.game-table.has-webgl .felt-surface,
.game-table.has-webgl .opponent-rack,
.game-table.has-webgl .tile-wall,
.game-table.has-webgl .discard-zone,
.game-table.has-webgl .meld-zone {
  display: none;
}

.game-table.production-3d-mode .scene-canvas {
  image-rendering: auto;
}

.game-table.has-webgl .top-bar {
  top: calc(18 / 805 * 100%);
  right: calc(18 / 1488 * 100%);
  left: calc(18 / 1488 * 100%);
}

.game-table.has-webgl .top-actions {
  grid-column: 3;
}

.game-table.has-webgl .brand-lockup p,
.game-table.has-webgl .history-drawer {
  display: none;
}

.game-table.has-webgl .brand-lockup h1 {
  font-size: calc(42 * 100cqw / 1488);
  letter-spacing: 0.025em;
  text-shadow: 0 3px 8px #160b04, 0 0 1px #000;
}

.game-table.has-webgl .brand-seal {
  width: calc(64 * 100cqw / 1488);
  border-width: 2px;
  background: rgb(25 20 13 / 72%);
  color: transparent;
  font-size: 0;
}

.game-table.has-webgl .brand-lockup::after {
  align-self: flex-start;
  margin-top: 0.2em;
  padding: 0.16em 0.24em;
  border-radius: 5px;
  color: #f8e4b4;
  background: #a91e17;
  box-shadow: 0 2px 6px rgb(0 0 0 / 40%);
  content: "雅乐";
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(8px, 0.72vw, 12px);
  line-height: 1.05;
  writing-mode: vertical-rl;
}

.game-table.has-webgl #helpButton,
.game-table.has-webgl #soundButton {
  font-size: 0;
}

.game-table.has-webgl #helpButton::before {
  content: "⚙";
  font-size: clamp(20px, 2.1vw, 34px);
}

.game-table.has-webgl #soundButton::before {
  content: "◖))";
  font-size: clamp(14px, 1.45vw, 24px);
}

.game-table.has-webgl .top-stats,
.game-table.has-webgl .stage-banner,
.game-table.has-webgl .message-panel {
  display: none;
}

.game-table.has-webgl .player-top {
  top: 8.6%;
  left: 20.8%;
  transform: none;
}

.game-table.has-webgl .player-left {
  top: 48.2%;
  left: 1.2%;
}

.game-table.has-webgl .player-right {
  top: 23.7%;
  right: 3.1%;
}

.game-table.has-webgl .player-self {
  top: 48.5%;
  right: 3.1%;
  bottom: auto;
  left: auto;
}

.game-table.has-webgl .player-card {
  min-width: 0;
  padding: 0;
  gap: 0;
  border: 0;
  background: none;
  box-shadow: none;
  backdrop-filter: none;
}

.game-table.has-webgl .avatar {
  width: clamp(46px, 5vw, 80px);
  border-width: 3px;
  overflow: hidden;
  background-position: center;
  background-size: cover;
  color: transparent;
  font-size: 0;
  box-shadow: inset 0 0 0 1px rgb(255 245 212 / 45%), 0 5px 14px rgb(0 0 0 / 38%);
}

.game-table.has-webgl [data-player-index="0"] .avatar {
  background-image: url("./assets/avatars/bamboo.webp");
}

.game-table.has-webgl [data-player-index="1"] .avatar {
  background-image: url("./assets/avatars/panda.webp");
}

.game-table.has-webgl [data-player-index="2"] .avatar {
  background-image: url("./assets/avatars/teapot.webp");
}

.game-table.has-webgl [data-player-index="3"] .avatar {
  background-image: url("./assets/avatars/gaiwan.webp");
}

.game-table.has-webgl .player-copy strong {
  font-size: clamp(12px, 1.1vw, 18px);
}

.game-table.has-webgl .player-copy small {
  font-size: clamp(12px, 1.08vw, 18px);
}

.game-table.has-webgl .player-copy {
  min-width: clamp(112px, 9.5vw, 156px);
  margin-left: clamp(-12px, -0.65vw, -7px);
  padding: clamp(6px, 0.52vw, 9px) clamp(10px, 0.85vw, 14px) clamp(6px, 0.52vw, 9px) clamp(28px, 2.25vw, 37px);
  border: 1px solid rgb(215 168 82 / 72%);
  border-left: 0;
  border-radius: 0 16px 16px 0;
  background: linear-gradient(90deg, rgb(10 29 24 / 90%), rgb(13 38 31 / 72%));
  box-shadow: 0 7px 18px rgb(0 0 0 / 24%);
}

.game-table.has-webgl .missing-badge {
  position: absolute;
  bottom: -2%;
  left: clamp(40px, 4.3vw, 69px);
  display: grid;
  width: clamp(25px, 2.15vw, 35px);
  aspect-ratio: 1;
  margin: 0;
  padding: 0;
  place-items: center;
  border: 2px solid #c99d4e;
  border-radius: 50%;
  color: transparent;
  background: #8d5b1f;
  font-size: 0;
  box-shadow: 0 3px 8px rgb(0 0 0 / 34%);
}

.game-table.has-webgl .missing-badge::after {
  color: #fff0c2;
  content: "简";
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(14px, 1.15vw, 19px);
  font-weight: 800;
}

.game-table.has-webgl .center-console {
  top: 47.1%;
  left: 50.8%;
  width: clamp(190px, 15.4vw, 310px);
  aspect-ratio: 972 / 706;
  transform: translate(-50%, -50%);
  border: 0;
  border-radius: 0;
  background: url("./assets/ui/center-console-frame-v2.webp") center / 100% 100% no-repeat;
  box-shadow: none;
  filter: none;
}

.game-table.has-webgl .center-console > *,
.game-table.has-webgl .center-value {
  transform: none;
}

.game-table.has-webgl .wind-ring {
  display: none;
}

.game-table.has-webgl .wind-ring span:nth-child(1) {
  top: 45%;
  left: 10%;
}

.game-table.has-webgl .wind-ring span:nth-child(2) {
  top: 8%;
  right: auto;
  left: 50%;
  display: grid;
  width: clamp(30px, 2.55vw, 42px);
  aspect-ratio: 1;
  place-items: center;
  transform: translateX(-50%);
  border-radius: 50%;
  color: #fff7cf;
  background: #187a48;
  box-shadow: 0 0 0 2px rgb(255 227 156 / 18%), 0 5px 12px rgb(0 0 0 / 28%);
  font-size: clamp(18px, 1.55vw, 26px);
}

.game-table.has-webgl .wind-ring span:nth-child(3) {
  display: none;
}

.game-table.has-webgl .wind-ring span:nth-child(4) {
  top: 45%;
  right: 10%;
  left: auto;
}

.game-table.has-webgl .center-value {
  position: absolute;
  top: 48.5%;
  left: 50%;
  display: flex;
  align-items: baseline;
  gap: 0.28em;
  margin: 0;
  transform: translateX(-50%);
  white-space: nowrap;
}

.game-table.has-webgl .center-value small {
  color: #f4ead1;
  font-size: clamp(11px, 0.98vw, 17px);
}

.game-table.has-webgl .center-value strong {
  color: #f7f0d2;
  font-size: clamp(16px, 1.25vw, 22px);
  line-height: 1;
}

.game-table.has-webgl .turn-timer {
  top: 64%;
  right: auto;
  bottom: auto;
  left: 50%;
  width: auto;
  aspect-ratio: auto;
  transform: translateX(-50%);
  color: #e8a23b;
  background: none;
  text-shadow: 0 2px 4px #000;
  font-size: clamp(25px, 2.15vw, 38px);
}

.game-table.has-webgl .human-hand {
  --tile-width: clamp(48px, 6.25vw, 106px);
  right: 6.2%;
  bottom: 10.2%;
  left: 6.2%;
}

.game-table.has-webgl .action-panel {
  right: 7.7%;
  bottom: 21.2%;
  gap: clamp(12px, 1.55vw, 26px);
}

.game-table.has-webgl .game-button {
  min-width: clamp(92px, 9.6vw, 158px);
  padding: clamp(9px, 0.8vw, 14px) clamp(18px, 1.5vw, 26px);
  border: 2px solid rgb(235 187 89 / 82%);
  font-size: clamp(21px, 2vw, 34px);
  box-shadow:
    0 4px 0 rgb(48 27 11 / 78%),
    0 9px 18px rgb(0 0 0 / 30%),
    inset 0 2px 0 rgb(255 255 255 / 34%),
    inset 0 0 18px rgb(255 222 137 / 12%);
}

.game-table.has-webgl .game-button.primary {
  min-width: clamp(150px, 14vw, 230px);
  font-size: clamp(14px, 1.25vw, 21px);
}

.game-table.has-webgl.stage-playing #hintButton,
.game-table.has-webgl.stage-playing #primaryButton {
  display: none;
}

.game-table.has-webgl.stage-playing .disabled-feature,
.game-table.has-webgl.stage-playing #huButton {
  filter: none;
  opacity: 1;
}

/* Playing controls are contextual.  A disabled Peng/Gang/Hu is not a muted
 * ornament on the table: it is absent until the rules engine says the action
 * is legal. */
.game-table.has-webgl.stage-playing .action-panel .game-button:disabled {
  display: none;
}

/* A legal win is a decision, not a passive status. Keep the button above the
 * local rack, name self-draw separately, and provide a short source cue. */
.game-table.has-webgl.stage-playing.has-win-prompt .action-panel {
  z-index: 72;
  right: max(var(--safe-right), 6.5%);
  bottom: max(var(--safe-bottom), 26%);
}

.game-table.has-webgl.stage-playing #huButton:not(:disabled) {
  position: relative;
  display: block;
  min-width: clamp(112px, 10.8vw, 176px);
  color: #fff8dd;
  background: linear-gradient(180deg, #dc4d39 0%, #a92018 62%, #72120f 100%);
  box-shadow:
    0 4px 0 rgb(69 12 9 / 88%),
    0 0 0 3px rgb(255 213 105 / 26%),
    0 10px 24px rgb(0 0 0 / 36%),
    inset 0 2px 0 rgb(255 255 255 / 34%);
  animation: win-action-breathe 1.15s ease-in-out infinite alternate;
}

/* A legal gang is an explicit player decision.  Use the same contextual
 * visibility rule as Hu, but a distinct gold treatment so 补杠/暗杠 cannot be
 * mistaken for a disabled decorative control on a small phone. */
.game-table.has-webgl.stage-playing #gangButton.is-action-prompt:not(:disabled) {
  position: relative;
  display: block;
  color: #fff5cf;
  background: linear-gradient(180deg, #d7a53e 0%, #9a641e 60%, #673a10 100%);
  box-shadow:
    0 3px 0 rgb(72 38 10 / 88%),
    0 0 0 3px rgb(255 218 119 / 22%),
    0 9px 22px rgb(0 0 0 / 34%),
    inset 0 2px 0 rgb(255 255 255 / 34%);
  animation: gang-action-breathe 1.15s ease-in-out infinite alternate;
}

@keyframes gang-action-breathe {
  from {
    filter: brightness(0.98);
    transform: translateY(0) scale(1);
  }
  to {
    filter: brightness(1.12);
    transform: translateY(-1px) scale(1.035);
  }
}

.game-table.has-webgl.stage-playing #huButton[data-win-kind="self-draw"]:not(:disabled) {
  background: linear-gradient(180deg, #d59a2c 0%, #a55a13 62%, #70330b 100%);
}

.game-table.has-webgl.stage-playing #huButton[data-win-kind="kong-bloom"]:not(:disabled) {
  min-width: clamp(132px, 12.5vw, 196px);
  background: linear-gradient(180deg, #ca7d56 0%, #9b3d41 58%, #5d2635 100%);
  box-shadow:
    0 4px 0 rgb(61 22 30 / 90%),
    0 0 0 3px rgb(255 220 130 / 30%),
    0 10px 26px rgb(0 0 0 / 38%),
    inset 0 2px 0 rgb(255 255 255 / 34%);
}

.game-table.has-webgl.stage-playing #huButton:not(:disabled)::after {
  position: absolute;
  right: 50%;
  bottom: calc(100% + 8px);
  padding: 5px 11px;
  border: 1px solid rgb(235 187 89 / 72%);
  border-radius: 999px;
  color: #fff3cc;
  background: rgb(7 38 31 / 92%);
  box-shadow: 0 5px 14px rgb(0 0 0 / 28%);
  content: attr(data-win-cue);
  font-family: "Microsoft YaHei", sans-serif;
  font-size: clamp(11px, 0.92vw, 15px);
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  transform: translateX(50%);
}

@keyframes win-action-breathe {
  from { filter: brightness(1); transform: translateY(0) scale(1); }
  to { filter: brightness(1.09); transform: translateY(-1px) scale(1.025); }
}

@media (prefers-reduced-motion: reduce) {
  .game-table.has-webgl.stage-playing #huButton:not(:disabled) {
    animation: none;
  }
}

.game-table.has-webgl.stage-playing.has-human-reaction #primaryButton {
  display: block;
}

.game-table.has-webgl.stage-playing .disabled-feature:nth-of-type(2) {
  background: linear-gradient(180deg, #6fa735, #39751f 62%, #235116);
}

.game-table.has-webgl.stage-playing .disabled-feature:nth-of-type(3) {
  background: linear-gradient(180deg, #d79b31, #a96014 62%, #71370c);
}

.game-table.has-webgl.stage-exchange #hintButton,
.game-table.has-webgl.stage-exchange .disabled-feature,
.game-table.has-webgl.stage-exchange #huButton {
  display: none;
}

.game-table.has-webgl.stage-exchange #primaryButton:disabled {
  color: #fff0bf;
  background: linear-gradient(180deg, #c89738, #8e5518 66%, #60300d);
  cursor: default;
  filter: none;
  opacity: 1;
}

.game-table.has-webgl .mahjong-tile {
  overflow: hidden;
  border-color: #d8d5c9;
  border-radius: clamp(6px, 0.58vw, 10px);
  background:
    linear-gradient(112deg, rgb(255 255 255 / 92%) 0 7%, transparent 26%),
    linear-gradient(180deg, #fffdf6 0, #f5f2e8 38%, #ece8dd 78%, #ded9ce 100%);
  box-shadow:
    0 clamp(6px, 0.5vw, 9px) 0 #2e6847,
    0 clamp(10px, 0.88vw, 15px) clamp(7px, 0.68vw, 12px) rgb(0 0 0 / 38%),
    inset 0 0 0 1px rgb(255 255 255 / 72%),
    inset 0 -5px 8px rgb(108 98 78 / 7%);
}

.game-table.has-webgl .mahjong-tile.is-illegal {
  opacity: 1;
  filter: none;
}

.game-table.has-webgl .human-hand .mahjong-tile {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  opacity: 0;
}

/* Each transparent button follows the screen-space bounds of its own 3D tile.
 * This keeps touch ownership exact on every landscape aspect ratio instead of
 * stretching an estimated flex row over a narrower perspective rack. */
.game-table.has-webgl .human-hand.is-projected-hit-layer {
  z-index: 30;
  inset: 0 !important;
  display: block;
  width: auto;
  height: auto;
  opacity: 1 !important;
  pointer-events: none;
  perspective: none;
}

.game-table.has-webgl .human-hand.is-projected-hit-layer .mahjong-tile {
  position: absolute;
  display: block;
  min-width: 0;
  min-height: 0;
  margin: 0 !important;
  transform: none !important;
  transition: none;
  pointer-events: auto;
}

.wood-frame,
.felt-surface {
  position: absolute;
  pointer-events: none;
}

.wood-frame {
  inset: 0;
  z-index: -2;
  background:
    linear-gradient(115deg, rgb(255 255 255 / 8%), transparent 25%, rgb(0 0 0 / 18%) 80%),
    repeating-linear-gradient(8deg, #70462b 0 3px, #5c351f 4px 9px, #6b4027 10px 14px);
}

.felt-surface {
  inset: clamp(22px, 3vw, 50px);
  z-index: -1;
  border: 2px solid rgb(240 199 111 / 38%);
  border-radius: clamp(12px, 1.4vw, 25px);
  background:
    radial-gradient(circle at 50% 45%, rgb(28 166 137 / 24%), transparent 32%),
    radial-gradient(circle at 15% 85%, rgb(255 255 255 / 4%), transparent 25%),
    linear-gradient(135deg, transparent 0 42%, rgb(255 255 255 / 2%) 43% 44%, transparent 45% 100%),
    linear-gradient(160deg, var(--felt-light), var(--felt) 48%, var(--felt-deep));
  box-shadow:
    inset 0 0 65px rgb(0 0 0 / 36%),
    inset 0 0 0 7px rgb(0 0 0 / 10%),
    0 0 0 12px rgb(20 10 5 / 28%);
}

.felt-surface::before,
.felt-surface::after {
  position: absolute;
  width: 24%;
  aspect-ratio: 1;
  border: 2px solid rgb(5 70 58 / 16%);
  border-radius: 46% 54% 49% 51%;
  content: "";
  opacity: 0.5;
  transform: rotate(28deg);
}

.felt-surface::before {
  top: 12%;
  left: 10%;
  box-shadow: inset 0 0 0 11px rgb(5 70 58 / 7%);
}

.felt-surface::after {
  right: 10%;
  bottom: 12%;
  transform: rotate(-28deg);
  box-shadow: inset 0 0 0 11px rgb(5 70 58 / 7%);
}

.top-bar {
  position: absolute;
  z-index: 25;
  top: 1.6%;
  right: 2%;
  left: 2%;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  pointer-events: none;
}

.brand-lockup {
  display: flex;
  align-items: center;
  gap: calc(8 * 100cqw / 1488);
  color: var(--gold-soft);
  text-shadow: 0 2px 8px #000;
}

.brand-seal {
  display: grid;
  width: clamp(30px, 3.4vw, 54px);
  aspect-ratio: 1;
  place-items: center;
  border: 1px solid var(--gold);
  border-radius: 50%;
  background: rgb(12 30 24 / 76%);
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(15px, 1.8vw, 28px);
}

.brand-seal > img {
  width: 91%;
  height: 91%;
  object-fit: contain;
  filter: drop-shadow(0 2px 5px rgb(0 0 0 / 42%));
}

.brand-lockup h1,
.brand-lockup p {
  margin: 0;
}

.brand-lockup h1 {
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(18px, 2vw, 33px);
  letter-spacing: 0.06em;
}

.brand-lockup p {
  color: rgb(255 255 255 / 62%);
  font-size: clamp(8px, 0.72vw, 12px);
  letter-spacing: 0.15em;
}

.top-stats {
  display: flex;
  align-items: center;
  gap: clamp(5px, 0.65vw, 10px);
}

.stat-pill {
  display: flex;
  align-items: baseline;
  gap: 0.35em;
  padding: clamp(5px, 0.55vw, 9px) clamp(8px, 0.9vw, 15px);
  border: 1px solid rgb(242 207 139 / 24%);
  border-radius: 999px;
  background: rgb(7 30 25 / 70%);
  box-shadow: 0 4px 16px rgb(0 0 0 / 18%);
  backdrop-filter: blur(8px);
}

.stat-pill small {
  color: rgb(255 255 255 / 58%);
  font-size: clamp(8px, 0.66vw, 11px);
}

.stat-pill strong {
  color: var(--gold-soft);
  font-size: clamp(11px, 0.9vw, 15px);
}

.realtime-status {
  position: absolute;
  z-index: 135;
  top: 2.25%;
  left: 50%;
  display: inline-flex;
  min-width: 4.8em;
  align-items: center;
  justify-content: center;
  padding: 0.34em 0.72em;
  transform: translateX(-50%);
  border: 1px solid rgb(221 185 101 / 48%);
  border-radius: 999px;
  color: rgb(255 244 206 / 78%);
  background: rgb(6 35 27 / 72%);
  box-shadow: 0 3px 10px rgb(0 0 0 / 24%);
  font-size: clamp(8px, 0.68vw, 11px);
  letter-spacing: 0.08em;
  pointer-events: none;
}

.realtime-status[hidden] {
  display: none;
}

.realtime-status[data-status="connected"] {
  border-color: rgb(104 230 156 / 52%);
  color: #bdf7cf;
}

.realtime-status[data-status="reconnecting"],
.realtime-status[data-status="connecting"] {
  color: #ffe39b;
}

.rule-pill {
  color: rgb(255 255 255 / 78%);
  font-size: clamp(8px, 0.7vw, 12px);
}

.top-actions {
  display: flex;
  justify-content: flex-end;
  gap: clamp(6px, 0.7vw, 11px);
  pointer-events: auto;
}

.round-button {
  display: grid;
  width: clamp(30px, 3vw, 48px);
  aspect-ratio: 1;
  place-items: center;
  border: 1px solid rgb(245 217 149 / 45%);
  border-radius: 50%;
  color: var(--gold-soft);
  background: rgb(8 28 23 / 78%);
  box-shadow: 0 6px 20px rgb(0 0 0 / 22%);
  cursor: pointer;
  font-size: clamp(14px, 1.35vw, 22px);
}

.round-button:hover {
  background: rgb(23 63 51 / 90%);
}

.round-button.is-muted {
  color: rgb(255 255 255 / 38%);
}

.account-button {
  position: relative;
  padding: 2px;
}

.account-button-avatar {
  width: 100%;
  height: 100%;
  border-radius: inherit;
  background-image: url("./assets/avatars/bamboo.webp");
  background-position: center;
  background-size: cover;
}

.account-button > i {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 25%;
  min-width: 7px;
  aspect-ratio: 1;
  border: 1px solid #071c16;
  border-radius: 50%;
  background: #48d68b;
  box-shadow: 0 0 6px rgb(72 214 139 / 60%);
}

.account-button[data-account-status="offline"] > i,
.account-button[data-account-status="expired"] > i {
  background: #e78752;
  box-shadow: 0 0 6px rgb(231 135 82 / 54%);
}

.stage-banner {
  position: absolute;
  z-index: 20;
  top: 9.1%;
  left: 50%;
  min-width: 18%;
  padding: clamp(5px, 0.6vw, 10px) 1.3vw;
  transform: translateX(-50%);
  border: 1px solid rgb(255 224 157 / 22%);
  border-radius: 999px;
  color: rgb(255 255 255 / 86%);
  background: linear-gradient(180deg, rgb(7 32 26 / 78%), rgb(4 18 15 / 74%));
  box-shadow: 0 6px 18px rgb(0 0 0 / 18%);
  text-align: center;
  font-size: clamp(9px, 0.82vw, 14px);
  letter-spacing: 0.08em;
}

.player-card {
  position: absolute;
  z-index: 16;
  display: flex;
  align-items: center;
  gap: clamp(5px, 0.55vw, 9px);
  min-width: clamp(105px, 10.5vw, 170px);
  padding: clamp(5px, 0.5vw, 8px);
  border: 1px solid rgb(246 211 139 / 38%);
  border-radius: 999px;
  color: #fff;
  background: linear-gradient(90deg, rgb(5 29 24 / 92%), rgb(11 55 45 / 78%));
  box-shadow: 0 8px 22px rgb(0 0 0 / 28%);
  transition: 180ms ease;
}

.player-card.is-current {
  border-color: #ffdd83;
  box-shadow: 0 0 0 2px rgb(255 211 97 / 18%), 0 0 28px rgb(255 183 56 / 28%);
  transform: translateY(-2px);
}

.player-card.is-winner {
  border-color: #ff8c72;
  background: linear-gradient(90deg, rgb(83 29 20 / 92%), rgb(111 54 24 / 82%));
}

.player-card.is-dealer::before {
  position: absolute;
  top: -0.5em;
  left: clamp(19px, 2.1vw, 34px);
  display: grid;
  width: 1.7em;
  aspect-ratio: 1;
  place-items: center;
  border: 1px solid #ffe4a0;
  border-radius: 50%;
  color: #2b1707;
  background: linear-gradient(180deg, #ffd877, #b9751b);
  box-shadow: 0 3px 8px rgb(0 0 0 / 35%);
  content: "庄";
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(8px, 0.7vw, 12px);
  font-weight: 900;
}

.player-card.is-ready-to-discard::after {
  position: absolute;
  right: 0.8em;
  bottom: -1.7em;
  padding: 0.2em 0.7em;
  border: 1px solid rgb(255 222 145 / 62%);
  border-radius: 999px;
  color: #ffedb8;
  background: rgb(5 42 34 / 91%);
  box-shadow: 0 4px 10px rgb(0 0 0 / 25%);
  content: "14张 · 待出牌";
  font-size: clamp(7px, 0.6vw, 10px);
  white-space: nowrap;
}

.avatar {
  display: grid;
  width: clamp(28px, 3vw, 48px);
  aspect-ratio: 1;
  flex: none;
  place-items: center;
  border: 2px solid var(--gold);
  border-radius: 50%;
  color: #2c2115;
  background:
    radial-gradient(circle at 35% 28%, #fff3c7 0 16%, transparent 17%),
    linear-gradient(135deg, #f7cf78, #997041);
  box-shadow: inset 0 0 10px rgb(255 255 255 / 22%);
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(13px, 1.35vw, 22px);
}

.player-copy {
  display: grid;
  min-width: 0;
  line-height: 1.15;
}

.player-copy strong {
  overflow: hidden;
  font-size: clamp(9px, 0.85vw, 14px);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.player-copy small {
  margin-top: 0.25em;
  color: var(--gold-soft);
  font-size: clamp(8px, 0.78vw, 13px);
}

.missing-badge {
  margin-left: auto;
  padding: 0.18em 0.45em;
  border: 1px solid rgb(255 255 255 / 14%);
  border-radius: 999px;
  color: rgb(255 255 255 / 58%);
  background: rgb(0 0 0 / 16%);
  font-size: clamp(7px, 0.6vw, 10px);
}

.missing-badge.is-set {
  color: #2c2010;
  background: var(--gold-soft);
}

.player-top {
  top: 12.4%;
  left: 50%;
  transform: translateX(-50%);
}

.player-top.is-current {
  transform: translateX(-50%) translateY(-2px);
}

.player-left {
  top: 28%;
  left: 2.1%;
}

.player-right {
  top: 28%;
  right: 2.1%;
}

.player-self {
  bottom: 5.4%;
  left: 2.1%;
}

.opponent-rack,
.tile-wall,
.discard-zone,
.meld-zone {
  position: absolute;
  z-index: 5;
}

.meld-zone {
  z-index: 7;
  display: flex;
  gap: clamp(3px, 0.35vw, 6px);
  pointer-events: none;
}

.meld-group {
  display: flex;
  gap: 1px;
  padding: 2px;
  border-radius: 4px;
  background: rgb(4 43 33 / 28%);
  box-shadow: 0 3px 8px rgb(0 0 0 / 18%);
}

.melds-top {
  top: 36.2%;
  left: 50%;
  transform: translateX(-50%);
}

.melds-self {
  bottom: 20.5%;
  left: 50%;
  transform: translateX(-50%);
}

.melds-left,
.melds-right {
  top: 55%;
  flex-direction: column;
}

.melds-left {
  left: 22.5%;
  transform: translateY(-50%) rotate(90deg);
}

.melds-right {
  right: 22.5%;
  transform: translateY(-50%) rotate(-90deg);
}

.opponent-rack {
  display: flex;
  gap: clamp(1px, 0.12vw, 2px);
  opacity: 0.94;
}

.rack-top {
  top: 18.2%;
  left: 50%;
  transform: translateX(-50%);
}

.rack-left,
.rack-right {
  top: 43%;
  flex-direction: column;
  transform: translateY(-50%);
}

.rack-left {
  left: 15.8%;
}

.rack-right {
  right: 15.8%;
}

.back-tile {
  display: block;
  width: clamp(8px, 1.15vw, 18px);
  height: clamp(15px, 1.72vw, 27px);
  border: 1px solid rgb(255 255 255 / 68%);
  border-radius: 2px;
  background: linear-gradient(135deg, #26a06e, #09603e 64%, #043a28);
  box-shadow: 1px 2px 3px rgb(0 0 0 / 26%);
}

.rack-left .back-tile,
.rack-right .back-tile {
  width: clamp(15px, 1.72vw, 27px);
  height: clamp(8px, 1.15vw, 18px);
}

.winner-rack {
  padding: 0.45em 0.8em;
  border: 1px solid rgb(255 221 162 / 42%);
  border-radius: 999px;
  color: #fff1cc;
  background: rgb(122 42 29 / 82%);
  font-size: clamp(8px, 0.75vw, 12px);
}

.tile-wall {
  display: flex;
  gap: clamp(2px, 0.22vw, 4px);
  opacity: 0.9;
}

.wall-top {
  top: 23.5%;
  left: 50%;
  transform: translateX(-50%);
}

.wall-left,
.wall-right {
  top: 48%;
  flex-direction: column;
  transform: translateY(-50%);
}

.wall-self {
  right: 27%;
  bottom: 18.8%;
  left: 27%;
  justify-content: center;
}

.wall-left {
  left: 20.2%;
}

.wall-right {
  right: 20.2%;
}

.wall-stack {
  position: relative;
  display: block;
  width: clamp(14px, 1.75vw, 28px);
  height: clamp(9px, 1vw, 16px);
  border: 1px solid rgb(255 255 255 / 72%);
  border-radius: 2px;
  background: linear-gradient(180deg, #2ca676, #0a6747);
  box-shadow: 0 3px 0 #e7e2d4, 0 5px 4px rgb(0 0 0 / 24%);
}

.wall-stack.is-empty {
  visibility: hidden;
}

.wall-left .wall-stack,
.wall-right .wall-stack {
  width: clamp(9px, 1vw, 16px);
  height: clamp(14px, 1.75vw, 28px);
  box-shadow: 3px 0 0 #e7e2d4, 5px 0 4px rgb(0 0 0 / 24%);
}

.discard-zone {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(2px, 0.22vw, 4px);
  width: clamp(140px, 17vw, 280px);
  min-height: clamp(42px, 5vw, 80px);
  align-content: start;
  justify-content: center;
}

.discards-top {
  top: 28%;
  left: 50%;
  transform: translateX(-50%);
}

.discards-self {
  bottom: 28%;
  left: 50%;
  transform: translateX(-50%);
}

.discards-left,
.discards-right {
  top: 43%;
  width: clamp(90px, 10vw, 160px);
  grid-template-columns: repeat(6, minmax(0, 1fr));
}

.discards-left {
  left: 25.3%;
  transform: translateY(-50%) rotate(90deg);
}

.discards-right {
  right: 25.3%;
  transform: translateY(-50%) rotate(-90deg);
}

.center-console {
  position: absolute;
  z-index: 8;
  top: 49%;
  left: 50%;
  display: grid;
  width: clamp(105px, 11vw, 175px);
  aspect-ratio: 1;
  place-items: center;
  transform: translate(-50%, -50%) rotate(45deg);
  border: 2px solid rgb(234 192 107 / 44%);
  border-radius: 20%;
  color: #fff;
  background:
    linear-gradient(135deg, rgb(52 62 59 / 94%), rgb(11 24 21 / 96%));
  box-shadow:
    0 16px 24px rgb(0 0 0 / 28%),
    inset 0 0 25px rgb(255 255 255 / 5%);
}

.center-console > * {
  transform: rotate(-45deg);
}

.wind-ring {
  position: absolute;
  inset: 8%;
  color: rgb(255 255 255 / 45%);
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(8px, 0.75vw, 12px);
}

.wind-ring span {
  position: absolute;
}

.wind-ring span:nth-child(1) { top: 0; left: 48%; }
.wind-ring span:nth-child(2) { top: 45%; right: 0; }
.wind-ring span:nth-child(3) { right: 48%; bottom: 0; }
.wind-ring span:nth-child(4) { top: 45%; left: 0; }

.wind-ring .active-wind {
  color: #fff1b7;
  text-shadow: 0 0 10px #f7c05f;
}

.center-value {
  display: grid;
  place-items: center;
  transform: rotate(-45deg) translateY(-3%);
}

.center-value small {
  color: rgb(255 255 255 / 55%);
  font-size: clamp(8px, 0.72vw, 12px);
}

.center-value strong {
  color: #fff3c0;
  font-size: clamp(22px, 2.4vw, 38px);
  line-height: 1;
}

.turn-timer {
  position: absolute;
  right: 4%;
  bottom: 4%;
  display: grid;
  width: 25%;
  aspect-ratio: 1;
  place-items: center;
  transform: rotate(-45deg);
  border-radius: 50%;
  color: #21180b;
  background: var(--gold-soft);
  font-weight: 800;
  font-size: clamp(8px, 0.75vw, 12px);
}

.message-panel {
  position: absolute;
  z-index: 18;
  bottom: 21.7%;
  left: 50%;
  display: flex;
  min-width: 33%;
  flex-direction: column;
  align-items: center;
  gap: 0.15em;
  padding: clamp(5px, 0.5vw, 9px) clamp(14px, 1.6vw, 26px);
  transform: translateX(-50%);
  border: 1px solid rgb(249 218 151 / 18%);
  border-radius: 999px;
  color: #fff;
  background: rgb(3 25 20 / 68%);
  box-shadow: 0 7px 24px rgb(0 0 0 / 18%);
  backdrop-filter: blur(6px);
}

.message-panel strong {
  font-size: clamp(9px, 0.86vw, 14px);
}

.message-panel span {
  color: rgb(255 255 255 / 52%);
  font-size: clamp(7px, 0.62vw, 10px);
}

.human-hand {
  position: absolute;
  z-index: 30;
  right: 3.7%;
  bottom: 3.6%;
  left: 8.4%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: clamp(2px, 0.22vw, 4px);
  perspective: 900px;
}

.mahjong-tile {
  position: relative;
  display: grid;
  width: var(--tile-width);
  height: var(--tile-height);
  flex: 0 0 auto;
  place-items: center;
  padding: 0;
  border: 1px solid rgb(255 255 255 / 78%);
  border-radius: clamp(4px, 0.52vw, 9px);
  color: var(--ink);
  background:
    linear-gradient(115deg, rgb(255 255 255 / 72%), transparent 28%),
    linear-gradient(150deg, #fffdf4, #eee8d9 65%, #d6d0c3);
  box-shadow:
    0 clamp(4px, 0.42vw, 7px) 0 #1b6949,
    0 clamp(8px, 0.8vw, 13px) clamp(5px, 0.65vw, 11px) rgb(0 0 0 / 35%),
    inset 0 0 0 2px rgb(255 255 255 / 35%);
  cursor: pointer;
  transform: translateY(0) rotateX(2deg);
  transform-origin: bottom;
  transition: 140ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.mahjong-tile:hover,
.mahjong-tile.is-selected {
  transform: translateY(clamp(-10px, -1.2vw, -18px)) rotateX(0deg);
  box-shadow:
    0 clamp(4px, 0.42vw, 7px) 0 #1b6949,
    0 18px 22px rgb(0 0 0 / 34%),
    0 0 0 3px rgb(255 207 100 / 65%);
}

.mahjong-tile.is-drawn {
  margin-left: clamp(6px, 0.7vw, 12px);
}

/* Guidance is intentionally weaker than a player's selection. The rules
 * engine only nominates the rightmost tile; the player must still click it and
 * click again to discard. */
.mahjong-tile.is-system-recommended:not(.is-selected) {
  box-shadow:
    0 clamp(4px, 0.42vw, 7px) 0 #1b6949,
    0 12px 18px rgb(0 0 0 / 28%),
    0 0 0 2px rgb(242 195 92 / 34%);
}

.mahjong-tile.is-system-recommended:not(.is-selected)::after {
  position: absolute;
  z-index: 3;
  top: 3%;
  right: 5%;
  padding: 0.15em 0.42em;
  border-radius: 999px;
  color: #fff5ce;
  background: rgb(98 55 10 / 78%);
  content: "建议";
  font-family: "Microsoft YaHei", sans-serif;
  font-size: clamp(7px, 0.55vw, 10px);
  font-weight: 700;
  line-height: 1.2;
}

.mahjong-tile.is-illegal {
  opacity: 0.56;
  filter: saturate(0.45);
}

.mahjong-tile.is-exchange-selected::after {
  position: absolute;
  top: -0.8em;
  left: 50%;
  padding: 0.12em 0.42em;
  transform: translateX(-50%);
  border-radius: 999px;
  color: #1b1508;
  background: var(--gold-soft);
  content: "换";
  font-weight: 800;
  font-size: clamp(8px, 0.65vw, 11px);
}

.production-tile-face {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
}

.mini-tile {
  --tile-width: clamp(17px, 1.8vw, 29px);
  cursor: default;
  box-shadow:
    0 2px 0 #1b6949,
    0 4px 5px rgb(0 0 0 / 26%),
    inset 0 0 0 1px rgb(255 255 255 / 30%);
}

.mini-tile:hover {
  transform: none;
  box-shadow:
    0 2px 0 #1b6949,
    0 4px 5px rgb(0 0 0 / 26%);
}

.table-motion-layer {
  position: absolute;
  z-index: 72;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  perspective: 1000px;
}

.kong-bloom-fx {
  position: absolute;
  z-index: 110;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
}

.kong-bloom-fx.is-active {
  opacity: 1;
  visibility: visible;
  animation: kong-bloom-veil 2.6s ease-out both;
}

.win-result-dialog {
  position: absolute;
  z-index: 116;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  padding: max(var(--safe-top), 14px) max(var(--safe-right), 14px) max(var(--safe-bottom), 14px) max(var(--safe-left), 14px);
  background:
    radial-gradient(circle at 50% 52%, rgb(207 145 48 / 18%), transparent 31%),
    rgb(1 12 9 / 22%);
  opacity: 0;
  pointer-events: none;
}

.win-result-dialog[hidden] {
  display: none;
}

.win-result-dialog.is-active {
  opacity: 1;
  animation: win-result-veil var(--win-result-duration, 1.85s) ease-out both;
}

.win-result-card {
  display: grid;
  min-width: min(350px, 56cqw);
  max-width: min(560px, 72cqw);
  place-items: center;
  padding: clamp(15px, 1.7cqw, 26px) clamp(30px, 3.4cqw, 54px) clamp(17px, 1.9cqw, 30px);
  border: 1px solid rgb(248 207 118 / 70%);
  border-radius: clamp(18px, 1.8cqw, 30px);
  color: #fff4cf;
  text-align: center;
  background:
    radial-gradient(circle at 50% -20%, rgb(241 180 67 / 27%), transparent 52%),
    linear-gradient(150deg, rgb(19 74 55 / 98%), rgb(3 27 21 / 98%));
  box-shadow:
    0 26px 70px rgb(0 0 0 / 52%),
    0 0 0 5px rgb(236 183 78 / 9%),
    inset 0 1px 0 rgb(255 255 255 / 15%);
  animation: win-result-card-in var(--win-result-duration, 1.85s) cubic-bezier(.17,.78,.2,1) both;
}

.win-result-dialog.is-kong-bloom .win-result-card,
.win-result-dialog.is-special .win-result-card {
  background:
    radial-gradient(circle at 28% 0, rgb(243 169 182 / 25%), transparent 46%),
    radial-gradient(circle at 78% 4%, rgb(255 207 104 / 20%), transparent 42%),
    linear-gradient(150deg, rgb(86 44 45 / 98%), rgb(9 47 36 / 98%));
}

.win-result-seal {
  display: grid;
  width: clamp(48px, 4.5cqw, 70px);
  aspect-ratio: 1;
  margin-bottom: 5px;
  place-items: center;
  border: 2px solid #e8bf65;
  border-radius: 50%;
  color: #fff1b8;
  background: radial-gradient(circle at 35% 27%, #e0a33d, #944719 72%);
  box-shadow: 0 7px 20px rgb(0 0 0 / 34%), inset 0 1px 0 rgb(255 255 255 / 30%);
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(25px, 2.5cqw, 39px);
  font-weight: 900;
}

.win-result-kicker {
  margin: 0 0 2px;
  color: #e1b75f;
  font-size: clamp(8px, 0.68cqw, 11px);
  font-weight: 900;
  letter-spacing: 0.22em;
}

.win-result-title {
  color: #ffe6a0;
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(34px, 3.7cqw, 60px);
  letter-spacing: 0.1em;
  line-height: 1.08;
  text-shadow: 0 4px 12px rgb(0 0 0 / 42%);
}

.win-result-detail {
  margin: 8px 0 0;
  color: rgb(255 247 219 / 88%);
  font-size: clamp(12px, 1.08cqw, 18px);
  font-weight: 800;
  letter-spacing: 0.06em;
}

@keyframes win-result-veil {
  0% { opacity: 0; }
  12%, 72% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes win-result-card-in {
  0% { opacity: 0; transform: translateY(14px) scale(.9); }
  18%, 72% { opacity: 1; transform: translateY(0) scale(1); }
  100% { opacity: 0; transform: translateY(-6px) scale(1.02); }
}

@media (prefers-reduced-motion: reduce) {
  .win-result-dialog.is-active,
  .win-result-card {
    animation-duration: 650ms;
  }
}

.kong-bloom-glow {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 50% 50%, rgb(255 228 145 / 34%), transparent 27%),
    radial-gradient(circle at 22% 30%, rgb(255 173 183 / 20%), transparent 23%),
    radial-gradient(circle at 80% 68%, rgb(255 207 143 / 18%), transparent 25%);
  mix-blend-mode: screen;
  animation: kong-bloom-glow 2.25s ease-out both;
}

.kong-bloom-petal {
  position: absolute;
  top: 0;
  left: var(--petal-x);
  display: block;
  width: clamp(8px, 1.05cqw, 20px);
  height: clamp(13px, 1.7cqw, 32px);
  border: 1px solid rgb(255 255 255 / 26%);
  border-radius: 82% 18% 70% 30%;
  background: linear-gradient(145deg, #fff4ee 2%, #f6a8b6 48%, #bf526c 100%);
  box-shadow: 0 3px 9px rgb(65 13 23 / 26%), inset 1px 1px 0 rgb(255 255 255 / 52%);
  opacity: 0;
  transform: translate3d(-50%, var(--petal-start-y), 0) rotate(0deg) scale(var(--petal-scale));
  animation: kong-bloom-petal-fall var(--petal-duration) cubic-bezier(.21,.63,.42,1) var(--petal-delay) both;
  will-change: transform, opacity;
}

.kong-bloom-petal.tone-1 {
  background: linear-gradient(145deg, #fff8df 2%, #f7c86e 52%, #c77a28 100%);
}

.kong-bloom-petal.tone-2 {
  background: linear-gradient(145deg, #fff7f5 2%, #eec4ca 50%, #b36c80 100%);
}

.kong-bloom-blossom {
  position: absolute;
  top: var(--blossom-y);
  left: var(--blossom-x);
  display: block;
  width: clamp(42px, 5.2cqw, 86px);
  aspect-ratio: 1;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0) rotate(-16deg);
  animation: kong-bloom-blossom-open 1.45s cubic-bezier(.16,.78,.2,1) var(--blossom-delay) both;
  filter: drop-shadow(0 8px 13px rgb(67 16 23 / 26%));
}

.kong-bloom-blossom > i {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 48%;
  height: 29%;
  border: 1px solid rgb(255 255 255 / 30%);
  border-radius: 80% 22% 74% 28%;
  background: linear-gradient(100deg, #fff8ee 0%, #f4afbc 52%, #cf6680 100%);
  box-shadow: inset 1px 1px 0 rgb(255 255 255 / 48%);
  transform-origin: 0 50%;
  transform: rotate(var(--blossom-petal-rotation)) translateX(8%);
}

.kong-bloom-blossom::after {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 21%;
  aspect-ratio: 1;
  border: 1px solid rgb(255 247 183 / 66%);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 32%, #fff5ae, #d78a27 72%);
  box-shadow: 0 0 12px rgb(255 213 89 / 48%);
  content: '';
  transform: translate(-50%, -50%);
}

.kong-bloom-title {
  position: absolute;
  top: 50%;
  left: 50%;
  display: grid;
  min-width: min(470px, 52cqw);
  padding: clamp(16px, 1.8cqw, 28px) clamp(30px, 3.4cqw, 58px);
  place-items: center;
  border: 1px solid rgb(255 224 144 / 75%);
  border-radius: 999px;
  color: #fff8d8;
  background:
    radial-gradient(circle at 50% 0, rgb(255 220 129 / 24%), transparent 48%),
    linear-gradient(150deg, rgb(111 41 34 / 93%), rgb(38 68 45 / 94%));
  box-shadow:
    0 22px 58px rgb(0 0 0 / 48%),
    0 0 0 6px rgb(255 214 119 / 10%),
    inset 0 1px 0 rgb(255 255 255 / 24%);
  opacity: 0;
  transform: translate(-50%, -50%) scale(.76);
  animation: kong-bloom-title-in 2.45s cubic-bezier(.16,.78,.2,1) 120ms both;
}

.kong-bloom-title strong {
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(38px, 5.5cqw, 86px);
  font-weight: 900;
  letter-spacing: .16em;
  line-height: 1;
  text-indent: .16em;
  text-shadow: 0 4px 12px rgb(36 9 5 / 58%), 0 0 18px rgb(255 217 118 / 22%);
}

.kong-bloom-title small {
  margin-top: .7em;
  color: rgb(255 238 190 / 78%);
  font-size: clamp(10px, .92cqw, 15px);
  font-weight: 800;
  letter-spacing: .22em;
}

@keyframes kong-bloom-veil {
  0% { opacity: 0; }
  10%, 76% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes kong-bloom-glow {
  0% { opacity: 0; transform: scale(.86); }
  24% { opacity: 1; transform: scale(1.04); }
  100% { opacity: 0; transform: scale(1.16); }
}

@keyframes kong-bloom-petal-fall {
  0% {
    opacity: 0;
    transform: translate3d(-50%, var(--petal-start-y), 0) rotate(0deg) scale(var(--petal-scale));
  }
  14%, 76% { opacity: .94; }
  100% {
    opacity: 0;
    transform: translate3d(calc(-50% + var(--petal-drift)), 112vh, 0) rotate(var(--petal-rotate)) scale(var(--petal-scale));
  }
}

@keyframes kong-bloom-blossom-open {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0) rotate(-20deg); }
  34% { opacity: .94; transform: translate(-50%, -50%) scale(var(--blossom-open-scale)) rotate(5deg); }
  72% { opacity: .84; transform: translate(-50%, -50%) scale(var(--blossom-scale)) rotate(0deg); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(var(--blossom-end-scale)) rotate(8deg); }
}

@keyframes kong-bloom-title-in {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.76); filter: blur(4px); }
  18%, 72% { opacity: 1; transform: translate(-50%, -50%) scale(1); filter: blur(0); }
  100% { opacity: 0; transform: translate(-50%, -54%) scale(1.04); filter: blur(1px); }
}

@media (prefers-reduced-motion: reduce) {
  .kong-bloom-fx.is-active {
    animation-duration: 650ms;
  }

  .kong-bloom-petal,
  .kong-bloom-blossom {
    display: none;
  }

  .kong-bloom-title {
    animation: kong-bloom-title-in 650ms ease-out both;
  }
}

.motion-tile {
  position: absolute;
  display: grid;
  min-width: 18px;
  min-height: 25px;
  place-items: center;
  transform-origin: top left;
  will-change: transform, opacity;
  filter: drop-shadow(0 9px 8px rgb(0 0 0 / 42%));
}

.motion-tile.is-face-up {
  aspect-ratio: 360 / 500;
}

.motion-tile .production-tile-face {
  width: 100%;
  height: 100%;
}

.motion-tile.is-face-down {
  display: block;
}

.motion-tile-back {
  position: absolute;
  inset: 0;
  display: block;
  transform: translate(
    calc(var(--packet-index) * 13%),
    calc(var(--packet-index) * -4%)
  );
  border-radius: 3px;
  background: url("./assets/tiles/tile-back-v1.webp") center / 100% 100% no-repeat;
}

.motion-tile.seat-2 .motion-tile-back,
.motion-tile.seat-3 .motion-tile-back {
  transform: translate(
    calc(var(--packet-index) * 4%),
    calc(var(--packet-index) * 10%)
  ) rotate(90deg);
}

.motion-callout {
  position: absolute;
  z-index: 95;
  display: grid;
  width: clamp(58px, 6.2vw, 108px);
  aspect-ratio: 1;
  place-items: center;
  border: 2px solid rgb(255 230 166 / 88%);
  border-radius: 50%;
  color: #fff5d0;
  background:
    radial-gradient(circle at 42% 34%, rgb(255 255 255 / 24%), transparent 25%),
    linear-gradient(145deg, #b9802e, #633510);
  box-shadow:
    0 0 0 4px rgb(34 13 2 / 38%),
    0 10px 26px rgb(0 0 0 / 46%),
    inset 0 0 18px rgb(255 215 124 / 28%);
  font-family: "STKaiti", "KaiTi", serif;
  font-size: clamp(28px, 3.2vw, 58px);
  font-weight: 900;
  text-shadow: 0 3px 3px rgb(45 17 2 / 78%);
  pointer-events: none;
}

.motion-callout.tone-green {
  background: linear-gradient(145deg, #589b28, #174b22);
}

.motion-callout.tone-red {
  background: linear-gradient(145deg, #d24d32, #761c1c);
  box-shadow:
    0 0 0 4px rgb(34 4 2 / 38%),
    0 0 30px rgb(255 91 54 / 38%),
    inset 0 0 18px rgb(255 214 159 / 25%);
}

.concealed-tile-back {
  position: absolute;
  inset: 0;
  display: block;
  background: url("./assets/tiles/tile-back-v1.webp") center / 100% 100% no-repeat;
}

.opponent-rack.is-revealed-winner {
  z-index: 18;
  gap: 1px;
  filter: drop-shadow(0 6px 8px rgb(0 0 0 / 38%));
}

.game-table.sprite-tile-mode .opponent-rack.is-revealed-winner .mini-tile {
  --tile-width: clamp(18px, 1.82vw, 37px);
  width: var(--tile-width);
  height: calc(var(--tile-width) * 1.3889);
}

.game-table.sprite-tile-mode .rack-left.is-revealed-winner,
.game-table.sprite-tile-mode .rack-right.is-revealed-winner {
  flex-direction: column;
}

.collection-chip {
  position: absolute;
  display: block;
  min-width: 8px;
  min-height: 11px;
  border-radius: 2px;
  background-position: center;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  filter: drop-shadow(0 4px 4px rgb(0 0 0 / 38%));
  will-change: transform, opacity;
}

.game-table.is-collecting .overlay,
.game-table.is-collecting .message-panel,
.game-table.is-collecting .action-panel {
  opacity: 0;
  pointer-events: none;
}

.game-table.is-dealing .stage-banner {
  border-color: rgb(246 208 119 / 48%);
  box-shadow: 0 0 22px rgb(224 165 62 / 16%);
}

.game-table.is-dealing .human-hand,
.game-table.is-dealing .opponent-rack,
.game-table.is-dealing .tile-wall {
  transition: none;
}

.game-table.is-action-moving .human-hand,
.game-table.is-action-moving .opponent-rack,
.game-table.is-action-moving .discard-zone {
  pointer-events: none;
}

.action-panel {
  position: absolute;
  z-index: 36;
  right: 4.2%;
  bottom: 18.4%;
  display: flex;
  gap: clamp(5px, 0.55vw, 9px);
  align-items: center;
}

.game-button {
  min-width: clamp(48px, 5vw, 82px);
  padding: clamp(7px, 0.72vw, 12px) clamp(9px, 1vw, 16px);
  border: 1px solid rgb(255 255 255 / 22%);
  border-radius: 999px;
  color: #fff7dc;
  background: linear-gradient(180deg, #9b6d2d, #5e3b18);
  box-shadow:
    0 5px 0 rgb(48 27 11 / 66%),
    0 8px 16px rgb(0 0 0 / 22%),
    inset 0 1px 0 rgb(255 255 255 / 22%);
  cursor: pointer;
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(11px, 1.15vw, 19px);
  font-weight: 800;
  transition: 120ms ease;
}

.game-button:hover:not(:disabled) {
  filter: brightness(1.12);
  transform: translateY(-2px);
}

.game-button:active:not(:disabled) {
  box-shadow: 0 2px 0 rgb(48 27 11 / 66%);
  transform: translateY(3px);
}

.game-button:disabled {
  cursor: not-allowed;
  filter: grayscale(0.55);
  opacity: 0.4;
}

.game-button.secondary {
  background: linear-gradient(180deg, #357b63, #174a39);
}

.game-button.win {
  background: linear-gradient(180deg, #d2573c, #892516);
}

.game-button.primary {
  min-width: clamp(82px, 8.5vw, 138px);
  color: #211705;
  background: linear-gradient(180deg, #ffe287, #d59d3f);
}

.disabled-feature {
  position: relative;
}

.history-drawer {
  position: absolute;
  z-index: 45;
  top: 13%;
  right: 1.1%;
  width: clamp(150px, 16vw, 255px);
  transform: translateX(calc(100% - clamp(24px, 2vw, 34px)));
  transition: 180ms ease;
}

.history-drawer.is-open {
  transform: translateX(0);
}

.history-toggle {
  position: absolute;
  top: 0;
  left: 0;
  width: clamp(24px, 2vw, 34px);
  padding: 0.7em 0.35em;
  border: 1px solid rgb(255 255 255 / 14%);
  border-radius: 8px 0 0 8px;
  color: rgb(255 255 255 / 68%);
  background: rgb(5 25 20 / 82%);
  cursor: pointer;
  font-size: clamp(7px, 0.62vw, 10px);
  line-height: 1.15;
  writing-mode: vertical-rl;
}

.history-list {
  min-height: 160px;
  max-height: 38vh;
  margin: 0 0 0 clamp(24px, 2vw, 34px);
  padding: clamp(8px, 0.8vw, 13px) clamp(10px, 1vw, 16px) clamp(8px, 0.8vw, 13px) 2em;
  overflow: auto;
  border: 1px solid rgb(255 255 255 / 12%);
  border-radius: 0 0 0 10px;
  color: rgb(255 255 255 / 66%);
  background: rgb(5 25 20 / 88%);
  backdrop-filter: blur(8px);
  font-size: clamp(7px, 0.65vw, 11px);
}

.history-list li + li {
  margin-top: 0.55em;
}

.toast {
  position: absolute;
  z-index: 90;
  top: 18%;
  left: 50%;
  max-width: 55%;
  padding: clamp(7px, 0.75vw, 12px) clamp(14px, 1.5vw, 24px);
  transform: translate(-50%, -12px);
  border: 1px solid rgb(255 227 168 / 28%);
  border-radius: 999px;
  color: #fff5d2;
  background: rgb(19 32 26 / 90%);
  box-shadow: 0 12px 35px rgb(0 0 0 / 28%);
  font-size: clamp(9px, 0.82vw, 14px);
  opacity: 0;
  pointer-events: none;
  transition: 180ms ease;
}

.toast.is-visible {
  transform: translate(-50%, 0);
  opacity: 1;
}

.overlay {
  position: absolute;
  z-index: 100;
  inset: 0;
  display: grid;
  place-items: center;
  padding:
    max(var(--safe-top), 12px)
    max(var(--safe-right), 12px)
    max(var(--safe-bottom), 12px)
    max(var(--safe-left), 12px);
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  background:
    radial-gradient(circle at 50% 43%, rgb(15 78 63 / 30%), transparent 35%),
    rgb(3 11 9 / 72%);
  backdrop-filter: blur(7px);
}

.overlay.is-hidden {
  display: none;
}

.win-prompt-dialog {
  position: absolute;
  z-index: 112;
  inset: 0;
  display: grid;
  place-items: center;
  padding: max(var(--safe-top), 18px) max(var(--safe-right), 18px) max(var(--safe-bottom), 18px) max(var(--safe-left), 18px);
  background:
    radial-gradient(circle at 50% 55%, rgb(22 115 80 / 22%), transparent 38%),
    rgb(1 13 10 / 38%);
  backdrop-filter: blur(1.5px);
}

.win-prompt-dialog[hidden] {
  display: none;
}

.win-prompt-card {
  width: min(500px, 48cqw);
  min-width: min(330px, 86cqw);
  padding: clamp(20px, 2.2cqw, 34px) clamp(24px, 2.8cqw, 44px) clamp(24px, 2.5cqw, 38px);
  border: 1px solid rgb(244 205 126 / 58%);
  border-radius: clamp(18px, 1.7cqw, 28px);
  color: #fff8df;
  text-align: center;
  background:
    radial-gradient(circle at 50% 0, rgb(177 120 33 / 24%), transparent 44%),
    linear-gradient(150deg, rgb(10 65 49 / 98%), rgb(3 29 22 / 99%));
  box-shadow:
    0 28px 72px rgb(0 0 0 / 52%),
    0 0 0 5px rgb(215 170 85 / 8%),
    inset 0 1px 0 rgb(255 255 255 / 13%);
  animation: self-draw-dialog-in 180ms ease-out both;
}

.win-prompt-dialog.is-kong-bloom .win-prompt-card {
  border-color: rgb(255 211 139 / 72%);
  background:
    radial-gradient(circle at 22% 18%, rgb(246 167 180 / 22%), transparent 35%),
    radial-gradient(circle at 82% 8%, rgb(255 215 112 / 20%), transparent 34%),
    linear-gradient(150deg, rgb(78 44 43 / 98%), rgb(12 51 39 / 99%));
  box-shadow:
    0 28px 72px rgb(0 0 0 / 54%),
    0 0 0 5px rgb(236 174 111 / 10%),
    inset 0 1px 0 rgb(255 255 255 / 16%);
}

.win-prompt-seal {
  display: grid;
  width: clamp(54px, 5.2cqw, 76px);
  aspect-ratio: 1;
  margin: 0 auto 8px;
  place-items: center;
  border: 2px solid #e0b85e;
  border-radius: 50%;
  color: #fff0b7;
  background: radial-gradient(circle at 35% 28%, #d99b35, #8f4516 72%);
  box-shadow: 0 8px 20px rgb(0 0 0 / 34%), inset 0 1px 0 rgb(255 255 255 / 28%);
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(28px, 2.8cqw, 42px);
  font-weight: 900;
}

.win-prompt-dialog.is-kong-bloom .win-prompt-seal {
  color: #fff5cf;
  background:
    radial-gradient(circle at 34% 28%, #f4c072, #a54b54 54%, #592733 100%);
  box-shadow:
    0 8px 20px rgb(0 0 0 / 36%),
    0 0 22px rgb(245 170 181 / 22%),
    inset 0 1px 0 rgb(255 255 255 / 32%);
}

.win-prompt-kicker {
  margin: 0 0 5px;
  color: #d9ae55;
  font-size: clamp(9px, 0.72cqw, 12px);
  font-weight: 900;
  letter-spacing: 0.2em;
}

.win-prompt-card h2 {
  margin: 0;
  color: #ffe5a0;
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(28px, 3cqw, 46px);
  letter-spacing: 0.08em;
  text-shadow: 0 3px 10px rgb(0 0 0 / 34%);
}

.win-prompt-card > p:not(.win-prompt-kicker) {
  max-width: 35em;
  margin: 10px auto 18px;
  color: rgb(247 239 215 / 78%);
  font-size: clamp(11px, 0.9cqw, 15px);
  line-height: 1.65;
}

.win-prompt-actions {
  display: flex;
  justify-content: center;
  gap: clamp(12px, 1.3cqw, 20px);
}

.win-prompt-button {
  min-width: clamp(118px, 11cqw, 168px);
  padding: 0.72em 1.4em;
  border: 1px solid rgb(255 226 155 / 54%);
  border-radius: 999px;
  color: #fff8dc;
  background: linear-gradient(180deg, #47806e, #1d4e3e 66%, #12372b);
  box-shadow: 0 5px 0 #0d2b22, 0 12px 24px rgb(0 0 0 / 28%), inset 0 1px 0 rgb(255 255 255 / 24%);
  cursor: pointer;
  font-size: clamp(15px, 1.25cqw, 20px);
  font-weight: 900;
}

.win-prompt-button.confirm {
  color: #fff6d5;
  background: linear-gradient(180deg, #d99a35, #a95816 64%, #70300d);
  box-shadow: 0 5px 0 #4d2109, 0 12px 25px rgb(0 0 0 / 34%), inset 0 1px 0 rgb(255 255 255 / 32%);
}

.win-prompt-button:disabled {
  cursor: wait;
  filter: grayscale(0.35);
  opacity: 0.72;
}

@keyframes self-draw-dialog-in {
  from { opacity: 0; transform: translateY(10px) scale(0.96); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

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

.modal-card {
  width: min(78%, 720px);
  max-height: calc(100dvh - var(--safe-top) - var(--safe-bottom) - 24px);
  padding: clamp(20px, 2.8vw, 44px);
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-width: thin;
  border: 1px solid rgb(244 205 126 / 38%);
  border-radius: clamp(18px, 2vw, 30px);
  color: #fff;
  background:
    linear-gradient(145deg, rgb(18 62 50 / 96%), rgb(5 25 20 / 98%));
  box-shadow:
    0 35px 80px rgb(0 0 0 / 48%),
    inset 0 1px 0 rgb(255 255 255 / 9%);
  text-align: center;
}

.account-card {
  width: min(82%, 760px);
  padding: clamp(14px, 1.8vw, 26px);
  text-align: left;
}

.account-card-heading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 1.2vw, 18px);
  text-align: left;
}

.account-card-heading > img {
  width: clamp(48px, 5.2vw, 74px);
  aspect-ratio: 1;
  border: 2px solid #d6aa57;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 8px 18px rgb(0 0 0 / 30%);
}

.account-card-heading span {
  color: #d6aa57;
  font-size: clamp(8px, 0.68vw, 11px);
  font-weight: 800;
  letter-spacing: 0.18em;
}

.account-card-heading h2 {
  font-size: clamp(22px, 2.6vw, 40px);
}

.account-card .account-notice {
  margin-block: 0.55em;
  color: #bdf7cf;
  text-align: center;
}

.account-summary {
  display: grid;
  grid-template-columns: 1.35fr 0.55fr 1.1fr;
  gap: clamp(7px, 0.8vw, 12px);
  margin: clamp(10px, 1.1vw, 16px) 0;
}

.account-summary > span {
  display: grid;
  min-width: 0;
  padding: clamp(7px, 0.65vw, 10px) clamp(9px, 0.85vw, 13px);
  border: 1px solid rgb(255 230 175 / 14%);
  border-radius: 12px;
  background: rgb(0 13 10 / 34%);
}

.account-summary small,
.account-field > span,
.account-avatar-picker legend {
  color: rgb(255 241 205 / 55%);
  font-size: clamp(9px, 0.72vw, 12px);
}

.account-summary strong {
  overflow: hidden;
  margin-top: 0.25em;
  color: #fff4d6;
  font-size: clamp(10px, 0.82vw, 14px);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-field {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  align-items: center;
  gap: 12px;
}

.account-field input {
  width: 100%;
  padding: 0.68em 0.9em;
  border: 1px solid rgb(255 230 175 / 28%);
  border-radius: 11px;
  outline: none;
  color: #fff7df;
  background: rgb(0 16 12 / 64%);
  font: inherit;
}

.account-field input:focus {
  border-color: #e8bd65;
  box-shadow: 0 0 0 2px rgb(232 189 101 / 15%);
}

.account-avatar-picker {
  margin: clamp(9px, 1vw, 15px) 0 0;
  padding: 0;
  border: 0;
}

.account-avatar-picker > div {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(7px, 0.8vw, 12px);
  margin-top: 6px;
}

.account-avatar-option {
  display: flex;
  min-width: 0;
  align-items: center;
  justify-content: center;
  gap: clamp(6px, 0.65vw, 10px);
  padding: clamp(5px, 0.55vw, 8px);
  border: 1px solid rgb(255 230 175 / 16%);
  border-radius: 12px;
  color: rgb(255 255 255 / 70%);
  background: rgb(255 255 255 / 4%);
  cursor: pointer;
}

.account-avatar-option img {
  width: clamp(30px, 3vw, 45px);
  aspect-ratio: 1;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
}

.account-avatar-option span {
  overflow: hidden;
  font-size: clamp(9px, 0.76vw, 12px);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-avatar-option.is-selected {
  border-color: #e9bc5c;
  color: #fff2c6;
  background: rgb(187 123 35 / 22%);
  box-shadow: inset 0 0 0 1px rgb(255 226 157 / 12%);
}

.account-card .account-footnote {
  margin: 0.75em 0 0;
  color: rgb(255 255 255 / 46%);
  font-size: clamp(8px, 0.68vw, 11px);
  line-height: 1.5;
  text-align: center;
}

.account-security {
  margin-top: clamp(9px, 1vw, 14px);
  border: 1px solid rgb(255 230 175 / 16%);
  border-radius: 12px;
  background: rgb(0 13 10 / 28%);
}

.account-security > summary,
.account-security-subsection > summary {
  padding: 0.7em 0.9em;
  color: #ffe5a8;
  font-size: clamp(10px, 0.82vw, 14px);
  font-weight: 800;
  cursor: pointer;
}

.account-security-body {
  display: grid;
  gap: 8px;
  padding: 0 10px 10px;
}

.account-security-body > p {
  margin: 0;
  color: rgb(255 255 255 / 55%);
  font-size: clamp(9px, 0.72vw, 12px);
  text-align: center;
}

.account-security-status {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 6px 16px;
  color: rgb(255 255 255 / 62%);
  font-size: clamp(9px, 0.72vw, 12px);
}

.account-security-status strong {
  color: #c5f6d1;
}

.account-security-subsection {
  border-top: 1px solid rgb(255 230 175 / 12%);
}

.account-credential-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) max-content;
  align-items: end;
  gap: 8px;
  padding: 0 2px 8px;
}

.account-recovery-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr)) max-content;
}

.account-credential-grid label {
  display: grid;
  gap: 4px;
  min-width: 0;
}

.account-credential-grid label > span {
  color: rgb(255 241 205 / 55%);
  font-size: clamp(8px, 0.66vw, 11px);
}

.account-credential-grid input {
  min-width: 0;
  width: 100%;
  padding: 0.62em 0.72em;
  border: 1px solid rgb(255 230 175 / 24%);
  border-radius: 9px;
  outline: none;
  color: #fff7df;
  background: rgb(0 16 12 / 68%);
  font: inherit;
  font-size: clamp(9px, 0.74vw, 12px);
}

.account-credential-grid input:focus {
  border-color: #e8bd65;
}

.account-inline-button,
.account-recovery-output button {
  min-height: 2.4em;
  padding: 0.55em 0.9em;
  border: 1px solid rgb(236 194 103 / 55%);
  border-radius: 999px;
  color: #fff1c8;
  background: linear-gradient(180deg, rgb(173 113 32 / 82%), rgb(112 67 19 / 90%));
  font: inherit;
  font-size: clamp(9px, 0.72vw, 12px);
  font-weight: 800;
  cursor: pointer;
}

.account-inline-button:disabled {
  opacity: 0.45;
  cursor: wait;
}

.account-inline-button.secondary {
  border-color: rgb(152 215 178 / 38%);
  color: #d5f3df;
  background: linear-gradient(180deg, rgb(45 112 79 / 75%), rgb(23 69 48 / 86%));
}

.account-email-grid,
.account-points-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr)) repeat(2, max-content);
}

.account-security-body > h3 {
  margin: 4px 0 0;
  color: #ffe5a8;
  font-size: clamp(9px, 0.74vw, 12px);
}

.account-preference-list label {
  display: flex;
  align-items: center;
  gap: 8px;
  color: rgb(255 255 255 / 68%);
  font-size: clamp(9px, 0.74vw, 12px);
}

.account-preference-list input {
  width: 1.05em;
  height: 1.05em;
  accent-color: #d9a741;
}

.account-recipient-preview {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 9px;
  border: 1px solid rgb(117 211 157 / 24%);
  border-radius: 10px;
  background: rgb(29 95 64 / 20%);
}

.account-recipient-preview img {
  width: 34px;
  aspect-ratio: 1;
  border-radius: 50%;
  object-fit: cover;
}

.account-recipient-preview span {
  display: grid;
  gap: 2px;
}

.account-recipient-preview strong {
  color: #effff3;
  font-size: clamp(10px, 0.8vw, 13px);
}

.account-recipient-preview small,
.account-point-entry small,
.account-empty-state {
  color: rgb(255 255 255 / 48%);
  font-size: clamp(8px, 0.64vw, 10px);
}

.account-point-ledger {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 5px;
}

.account-point-entry {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr) max-content;
  align-items: center;
  gap: 7px;
  padding: 6px 8px;
  border-radius: 8px;
  background: rgb(255 255 255 / 4%);
}

.account-point-entry > span {
  min-width: 3.2em;
  font-weight: 900;
}

.account-point-entry .is-incoming {
  color: #77e5a5;
}

.account-point-entry .is-outgoing {
  color: #f1c16a;
}

.account-point-entry .is-neutral {
  color: rgb(255 255 255 / 56%);
}

.account-point-entry strong {
  overflow: hidden;
  color: rgb(255 255 255 / 72%);
  font-size: clamp(8px, 0.7vw, 11px);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-recovery-output {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr) max-content;
  align-items: center;
  gap: 10px;
  margin: 8px 0;
  padding: 8px 10px;
  border: 1px solid rgb(248 202 100 / 45%);
  border-radius: 12px;
  color: #ffe7a7;
  background: rgb(84 48 9 / 58%);
  font-size: clamp(9px, 0.76vw, 13px);
}

.account-recovery-output strong {
  overflow-wrap: anywhere;
  color: #fff;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  letter-spacing: 0.08em;
  text-align: center;
}

.account-card .modal-actions {
  margin-top: clamp(9px, 1vw, 15px);
}

@media (orientation: landscape) and (max-height: 620px) and (min-width: 1px),
  (orientation: portrait) and (pointer: coarse) {
  .account-card {
    width: min(90%, 760px);
    max-height: calc(100dvh - var(--safe-top) - var(--safe-bottom) - 12px);
    padding: 10px 14px;
  }

  .account-card-heading > img {
    width: clamp(38px, 10cqh, 48px);
  }

  .account-card-heading h2 {
    font-size: clamp(20px, 6cqh, 28px);
  }

  .account-summary {
    margin-block: 7px;
  }

  .account-summary > span {
    padding: 5px 8px;
  }

  .account-avatar-option img {
    width: clamp(27px, 8cqh, 35px);
  }

  .account-card .modal-button {
    min-width: 108px;
    padding-block: 0.55em;
  }

  .account-security > summary,
  .account-security-subsection > summary {
    padding-block: 0.45em;
  }

  .account-security-body {
    gap: 5px;
    padding-bottom: 6px;
  }

  .account-credential-grid {
    gap: 5px;
    padding-bottom: 5px;
  }

  .account-point-ledger {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 720px) {
  .account-credential-grid,
  .account-recovery-grid,
  .account-email-grid,
  .account-points-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .account-credential-grid .account-inline-button {
    grid-column: 1 / -1;
  }

  .account-recovery-output {
    grid-template-columns: 1fr;
    gap: 5px;
    text-align: center;
  }
}

.modal-seal {
  display: grid;
  width: clamp(52px, 6vw, 88px);
  aspect-ratio: 1;
  margin: 0 auto 0.7em;
  place-items: center;
  border: 2px solid var(--gold);
  border-radius: 50%;
  color: var(--gold-soft);
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(24px, 3vw, 46px);
}

.modal-card h2 {
  margin: 0;
  color: #ffe4a3;
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(24px, 3.2vw, 52px);
  letter-spacing: 0.08em;
}

.modal-card > p {
  max-width: 50em;
  margin: 0.7em auto 1.2em;
  color: rgb(255 255 255 / 66%);
  font-size: clamp(10px, 0.95vw, 16px);
  line-height: 1.7;
}

.feature-chips,
.missing-options,
.modal-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(7px, 0.75vw, 12px);
}

.feature-chip {
  padding: 0.45em 0.9em;
  border: 1px solid rgb(255 255 255 / 13%);
  border-radius: 999px;
  color: rgb(255 255 255 / 72%);
  background: rgb(255 255 255 / 5%);
  font-size: clamp(8px, 0.72vw, 12px);
}

.modal-actions {
  margin-top: 1.5em;
}

.modal-button,
.missing-option {
  min-width: clamp(105px, 12vw, 190px);
  padding: 0.75em 1.35em;
  border: 1px solid rgb(255 230 175 / 38%);
  border-radius: 999px;
  color: #201708;
  background: linear-gradient(180deg, #ffe3a0, #cf9537);
  box-shadow: 0 5px 0 #704817, 0 12px 24px rgb(0 0 0 / 24%);
  cursor: pointer;
  font-weight: 800;
  font-size: clamp(11px, 1vw, 17px);
}

.modal-button.secondary {
  color: #fff;
  background: linear-gradient(180deg, #3f7666, #214d40);
  box-shadow: 0 5px 0 #123228, 0 12px 24px rgb(0 0 0 / 24%);
}

.modal-button:disabled {
  filter: grayscale(0.72);
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.room-join-row {
  display: flex;
  flex: 1 1 100%;
  justify-content: center;
  gap: clamp(7px, 0.75vw, 12px);
  margin-top: 0.15em;
}

.room-join-row input {
  width: min(25em, 48vw);
  min-width: 12em;
  padding: 0.72em 1em;
  border: 1px solid rgb(255 230 175 / 30%);
  border-radius: 999px;
  outline: none;
  color: #fff7df;
  background: rgb(0 16 12 / 64%);
  font: inherit;
}

.room-join-row input:focus {
  border-color: var(--gold-soft);
  box-shadow: 0 0 0 2px rgb(244 205 126 / 16%);
}

.overlay.is-table-room-lobby {
  display: block;
  padding: 0;
  overflow: visible;
  background: transparent;
  backdrop-filter: none;
  pointer-events: none;
}

.table-room-lobby {
  position: absolute;
  z-index: 48;
  inset: 0;
  color: #fff1bd;
  pointer-events: none;
}

.room-edge-handle {
  position: absolute;
  top: 50%;
  right: max(var(--safe-right), 0px);
  width: clamp(14px, 1.25vw, 20px);
  height: clamp(82px, 18vh, 126px);
  padding: 0;
  transform: translateY(-50%);
  border: 1px solid rgb(255 229 163 / 26%);
  border-right: 0;
  border-radius: 14px 0 0 14px;
  color: rgb(255 239 194 / 38%);
  background: linear-gradient(180deg, rgb(8 74 56 / 34%), rgb(2 35 27 / 48%));
  box-shadow:
    inset 1px 0 0 rgb(255 255 255 / 7%),
    0 6px 20px rgb(0 0 0 / 16%);
  opacity: 0.28;
  pointer-events: auto;
  cursor: pointer;
  transition:
    opacity 180ms ease,
    transform 180ms ease;
  -webkit-tap-highlight-color: transparent;
}

.room-edge-handle:hover,
.room-edge-handle:focus-visible {
  opacity: 0.72;
  transform: translateY(-50%) translateX(-1px);
}

.room-edge-handle span {
  display: block;
  font: 900 20px/1 system-ui, sans-serif;
}

.room-drawer-backdrop {
  position: absolute;
  inset: 0;
  padding: 0;
  border: 0;
  background: rgb(0 18 13 / 14%);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 180ms ease;
}

.room-action-drawer {
  position: absolute;
  top: 50%;
  right: max(var(--safe-right), 8px);
  width: clamp(246px, 24vw, 330px);
  padding: 14px;
  transform: translate(calc(100% + 32px), -50%);
  border: 1px solid rgb(231 188 96 / 58%);
  border-radius: 18px 0 0 18px;
  color: #fff1bd;
  background: linear-gradient(145deg, rgb(8 72 55 / 97%), rgb(2 35 27 / 98%));
  box-shadow:
    inset 0 1px 0 rgb(255 244 204 / 8%),
    0 18px 42px rgb(0 0 0 / 34%);
  backdrop-filter: blur(16px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    transform 220ms ease,
    opacity 180ms ease,
    visibility 180ms ease;
}

.table-room-lobby.is-open .room-action-drawer {
  transform: translate(0, -50%);
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.table-room-lobby.is-open .room-drawer-backdrop {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.table-room-lobby.is-open .room-edge-handle {
  opacity: 0;
  pointer-events: none;
}

.room-drawer-header {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgb(255 231 168 / 14%);
}

.room-drawer-room {
  display: flex;
  min-width: 0;
  align-items: baseline;
  gap: 8px;
}

.room-drawer-room small {
  color: rgb(255 245 216 / 58%);
  font: 700 10px/1 system-ui, sans-serif;
  letter-spacing: 0.16em;
}

.room-drawer-room strong {
  user-select: all;
  color: #ffe09a;
  font: 900 18px/1 system-ui, sans-serif;
  letter-spacing: 0.12em;
}

.room-drawer-close {
  display: grid;
  width: 28px;
  aspect-ratio: 1;
  padding: 0;
  place-items: center;
  border: 1px solid rgb(255 231 168 / 24%);
  border-radius: 50%;
  color: #f8e9bd;
  background: rgb(255 255 255 / 6%);
  font: 500 20px/1 system-ui, sans-serif;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.table-room-count {
  display: grid;
  min-width: 38px;
  min-height: 26px;
  place-items: center;
  border-radius: 999px;
  color: rgb(255 242 202 / 82%);
  background: rgb(255 255 255 / 8%);
  font: 800 11px/1 system-ui, sans-serif;
}

.table-room-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-top: 12px;
}

.table-room-button {
  min-width: 0;
  min-height: 40px;
  padding: 7px 10px;
  border: 1px solid rgb(255 226 151 / 42%);
  border-radius: 999px;
  color: #2e2105;
  background: linear-gradient(180deg, #f8d671, #d89a28);
  font: 800 12px/1 system-ui, sans-serif;
  box-shadow: 0 2px 0 #764913;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.table-room-button.secondary {
  color: #f8e9bd;
  background: linear-gradient(180deg, rgb(49 110 87 / 96%), rgb(17 62 48 / 96%));
  box-shadow: 0 2px 0 #0a2b21;
}

.table-room-button.danger {
  color: #ffd9c7;
  border-color: rgb(255 150 114 / 38%);
  background: linear-gradient(180deg, rgb(126 56 35 / 96%), rgb(76 29 19 / 96%));
}

.table-room-button:disabled {
  opacity: 0.5;
  cursor: default;
}

.room-host-wait {
  grid-column: 1 / -1;
  display: grid;
  min-height: 38px;
  padding-inline: 10px;
  place-items: center;
  border-radius: 12px;
  color: rgb(255 255 255 / 62%);
  background: rgb(255 255 255 / 5%);
  font: 700 11px/1.25 system-ui, sans-serif;
}

.room-waiting-card {
  width: min(84%, 780px);
  padding-block: clamp(14px, 2vw, 30px);
}

.room-waiting-pulse {
  display: flex;
  justify-content: center;
  gap: 0.5em;
  margin: 1em auto;
}

.room-waiting-pulse i {
  width: 0.6em;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--gold-soft);
  animation: room-waiting-pulse 1.1s ease-in-out infinite alternate;
}

.room-waiting-pulse i:nth-child(2) {
  animation-delay: 0.18s;
}

.room-waiting-pulse i:nth-child(3) {
  animation-delay: 0.36s;
}

@keyframes room-waiting-pulse {
  to {
    opacity: 0.25;
    transform: translateY(-0.25em);
  }
}

@media (max-width: 760px) {
  .room-join-row {
    flex-wrap: wrap;
  }
}

@media (orientation: landscape) and (max-height: 620px),
  (orientation: portrait) and (pointer: coarse) {
  .overlay {
    place-items: center;
    padding:
      max(var(--safe-top), 6px)
      max(var(--safe-right), 8px)
      max(var(--safe-bottom), 6px)
      max(var(--safe-left), 8px);
  }

  .room-action-drawer {
    right: max(var(--safe-right), 4px);
    width: min(286px, 72vw);
    padding: 10px;
    border-radius: 14px 0 0 14px;
  }

  .room-edge-handle {
    right: max(var(--safe-right), 0px);
    width: 14px;
    height: min(104px, 28vh);
  }

  .room-drawer-header {
    gap: 7px;
    padding-bottom: 9px;
  }

  .room-drawer-room small,
  .table-room-count,
  .room-host-wait {
    font-size: 10px;
  }

  .room-drawer-room strong {
    font-size: 15px;
  }

  .table-room-button {
    min-width: 0;
    min-height: 34px;
    padding: 6px 8px;
    font-size: 11px;
  }

  .room-host-wait {
    min-height: 34px;
    padding-inline: 7px;
  }
}

/* Compact player identity V1
 *
 * The permanent table HUD contains only the physical seat identity (avatar)
 * and the missing-suit marker. Nickname and score are disclosed on demand so
 * they never cover a wall, river, meld or exposed winning hand. */
.player-card,
.game-table.has-webgl .player-card {
  width: max-content;
  min-width: 0;
  height: auto;
  padding: 0;
  gap: 0;
  overflow: visible;
  border: 0;
  background: none;
  box-shadow: none;
  backdrop-filter: none;
}

.player-avatar-button {
  position: relative;
  display: grid;
  width: max-content;
  margin: 0;
  padding: 0;
  place-items: center;
  border: 0;
  border-radius: 50%;
  color: inherit;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.player-avatar-button:focus-visible {
  outline: 3px solid rgb(255 219 132 / 88%);
  outline-offset: 3px;
}

.player-card.is-current .player-avatar-button .avatar {
  border-color: #ffe08b;
  box-shadow:
    inset 0 0 0 1px rgb(255 248 219 / 52%),
    0 0 0 3px rgb(255 200 82 / 22%),
    0 0 18px rgb(255 183 56 / 42%);
}

.player-card.is-winner .player-avatar-button .avatar {
  border-color: #ff9d7c;
  box-shadow:
    inset 0 0 0 1px rgb(255 247 226 / 48%),
    0 0 0 3px rgb(255 108 77 / 18%),
    0 0 20px rgb(255 92 61 / 40%);
}

.player-card.is-vacant .player-avatar-button {
  cursor: default;
}

.player-card.is-vacant .player-avatar-button .avatar {
  border: 1px dashed rgb(232 194 106 / 72%);
  color: #f3d98f;
  background: rgb(4 50 39 / 68%);
  box-shadow:
    inset 0 0 0 1px rgb(255 239 190 / 7%),
    0 4px 12px rgb(0 0 0 / 16%);
  font-family: system-ui, sans-serif;
  font-size: clamp(17px, 1.7vw, 27px);
  font-weight: 300;
  opacity: 0.78;
}

.player-card .missing-badge,
.game-table.has-webgl .player-card .missing-badge {
  position: absolute;
  right: -12%;
  bottom: -8%;
  left: auto;
  display: grid;
  width: clamp(28px, 2.6vw, 42px);
  aspect-ratio: 1;
  margin: 0;
  padding: 0;
  place-items: center;
  border: 2px solid #c99d4e;
  border-radius: 50%;
  color: transparent;
  background: #8d5b1f;
  font-size: 0;
  box-shadow: 0 3px 8px rgb(0 0 0 / 34%);
  pointer-events: none;
}

.player-card .missing-badge::after,
.game-table.has-webgl .player-card .missing-badge::after {
  color: #fff0c2;
  content: attr(data-short-label);
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(16px, 1.45vw, 23px);
  font-weight: 900;
  line-height: 1;
  text-shadow: 0 1px 2px rgb(42 22 4 / 55%);
}

.player-card .missing-badge.is-set {
  color: transparent;
  background: linear-gradient(180deg, #a87026, #744313);
}

.player-card .missing-badge[hidden],
.game-table.has-webgl .player-card .missing-badge[hidden] {
  display: none !important;
}

.player-detail-popover {
  position: absolute;
  z-index: 2;
  min-width: clamp(112px, 9.5vw, 156px);
  border-radius: 14px;
  filter: drop-shadow(0 8px 14px rgb(0 0 0 / 32%));
}

.player-detail-popover[hidden] {
  display: none !important;
}

.player-detail-popover .player-copy,
.game-table.has-webgl .player-detail-popover .player-copy,
.game-table.adult-visual-master-v1 .player-detail-popover .player-copy {
  display: grid;
  min-width: clamp(112px, 9.5vw, 156px);
  margin: 0;
  padding: clamp(7px, 0.58vw, 10px) clamp(11px, 0.9vw, 15px);
  border: 1px solid rgb(215 168 82 / 74%);
  border-radius: 14px;
  color: #f0e6ce;
  background: linear-gradient(180deg, rgb(8 35 28 / 96%), rgb(5 24 20 / 94%));
  box-shadow:
    inset 0 1px 0 rgb(255 242 199 / 10%),
    0 7px 18px rgb(0 0 0 / 24%);
}

.player-top .player-detail-popover {
  top: calc(100% + 9px);
  left: 50%;
  transform: translateX(-50%);
}

.player-left .player-detail-popover {
  top: 50%;
  left: calc(100% + 9px);
  transform: translateY(-50%);
}

.player-right .player-detail-popover,
.player-self .player-detail-popover {
  top: 50%;
  right: calc(100% + 9px);
  transform: translateY(-50%);
}

.player-card.is-detail-open {
  z-index: 98;
}

.player-card.is-ready-to-discard::after {
  display: none;
}

.player-card.is-detail-open.is-ready-to-discard::after {
  display: block;
}

@media (orientation: landscape) and (max-height: 620px),
  (orientation: portrait) and (pointer: coarse) {
  .game-table.mobile-full-bleed-v2 .player-card,
  .game-table.mobile-full-bleed-v2 .player-avatar-button {
    width: max-content;
    min-width: 0;
    height: auto;
  }

  .game-table.mobile-full-bleed-v2 .player-card .missing-badge {
    right: -12%;
    bottom: -10%;
    left: auto;
    display: grid;
    width: clamp(28px, 7.4cqh, 38px);
  }

  .game-table.mobile-full-bleed-v2 .player-detail-popover {
    min-width: clamp(82px, 17vw, 112px);
  }

  .game-table.mobile-full-bleed-v2 .player-detail-popover .player-copy,
  .game-table.mobile-full-bleed-v2 .player-self .player-detail-popover .player-copy {
    display: grid;
    min-width: clamp(82px, 17vw, 112px);
    margin: 0;
    padding: 5px 8px;
    border-radius: 10px;
  }

  .game-table.mobile-full-bleed-v2 .player-detail-popover .player-copy strong,
  .game-table.mobile-full-bleed-v2 .player-detail-popover .player-copy small {
    font-size: clamp(9px, 2.8cqh, 12px);
  }
}

.missing-options {
  margin: 1.4em 0 0.5em;
}

.missing-option {
  min-width: clamp(80px, 8vw, 130px);
  color: #fff7df;
  background: linear-gradient(180deg, #2e7f67, #154837);
  box-shadow: 0 5px 0 #0b2c21, 0 12px 24px rgb(0 0 0 / 24%);
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(18px, 2vw, 32px);
}

.missing-option.is-recommended {
  outline: 2px solid var(--gold-soft);
  outline-offset: 3px;
}

.result-list,
.rule-list {
  display: grid;
  gap: 0.55em;
  max-width: 34em;
  margin: 1.1em auto;
  padding: 0;
  list-style: none;
  text-align: left;
}

.result-list li,
.rule-list li {
  display: flex;
  justify-content: space-between;
  gap: 1em;
  padding: 0.62em 0.85em;
  border: 1px solid rgb(255 255 255 / 9%);
  border-radius: 10px;
  color: rgb(255 255 255 / 72%);
  background: rgb(255 255 255 / 4%);
  font-size: clamp(9px, 0.82vw, 14px);
}

.settlement-ledger {
  max-width: 34em;
  margin: 0.65em auto 1em;
  color: rgb(255 228 163 / 88%);
  text-align: left;
}

.settlement-ledger summary {
  padding: 0.6em 0.85em;
  border: 1px solid rgb(244 205 126 / 22%);
  border-radius: 10px;
  background: rgb(244 205 126 / 7%);
  cursor: pointer;
  font-size: clamp(9px, 0.82vw, 14px);
}

.settlement-ledger-list {
  max-height: min(28dvh, 240px);
  margin-top: 0.55em;
  overflow-y: auto;
}

/*
 * Asset-driven 2.5D tile system.
 * The blank ceramic front and jade back are project-owned raster assets
 * derived from the locked visual master. Game state and markings remain live.
 */
.game-table.sprite-tile-mode .scene-canvas {
  display: none;
}

.game-table.sprite-tile-mode .opponent-rack {
  z-index: 9;
  display: flex;
  opacity: 1;
}

.game-table.sprite-tile-mode .opponent-rack .back-tile {
  border: 0;
  border-radius: 0;
  background: url("./assets/tiles/tile-back-v1.webp") center / 100% 100% no-repeat;
  box-shadow: none;
  filter: drop-shadow(0 3px 3px rgb(0 0 0 / 30%));
}

.game-table.sprite-tile-mode .rack-top {
  top: 8.8%;
  left: 57.3%;
  gap: 0;
}

.game-table.sprite-tile-mode .rack-top .back-tile {
  width: clamp(21px, 1.86vw, 38px);
  height: clamp(33px, 2.95vw, 60px);
}

.game-table.sprite-tile-mode .rack-left,
.game-table.sprite-tile-mode .rack-right {
  top: 42.5%;
  gap: 0;
}

.game-table.sprite-tile-mode .rack-left {
  left: 10.5%;
  transform: translateY(-50%) rotate(18.5deg);
  transform-origin: 50% 50%;
}

.game-table.sprite-tile-mode .rack-right {
  right: 10.5%;
  transform: translateY(-50%) rotate(-18.5deg);
  transform-origin: 50% 50%;
}

.game-table.sprite-tile-mode .rack-left .back-tile,
.game-table.sprite-tile-mode .rack-right .back-tile {
  width: clamp(31px, 2.8vw, 57px);
  height: clamp(20px, 1.8vw, 37px);
}

.game-table.sprite-tile-mode .rack-left .back-tile {
  transform: rotate(90deg);
}

.game-table.sprite-tile-mode .rack-right .back-tile {
  transform: rotate(-90deg);
}

.game-table.sprite-tile-mode .tile-wall,
.game-table.sprite-tile-mode .discard-zone {
  display: flex;
}

.game-table.sprite-tile-mode .human-hand {
  --tile-width: clamp(48px, 6.08vw, 124px);
  right: 2.9%;
  bottom: 5.1%;
  left: 6.3%;
  /* The production PNG keeps transparent antialiasing around the ceramic body.
   * Pull adjacent boxes together so the visible tile edges actually touch. */
  gap: 0;
  align-items: flex-end;
}

.game-table.sprite-tile-mode .human-hand .mahjong-tile + .mahjong-tile {
  /* Compensate only for the transparent canvas around the approved PNG. The
   * visible ceramic bodies remain separate and meet on a one-pixel dark seam. */
  margin-left: calc(var(--tile-width) * -0.09);
}

.game-table.sprite-tile-mode .mahjong-tile {
  width: var(--tile-width);
  height: calc(var(--tile-width) * 1.3889);
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  filter: drop-shadow(0 clamp(4px, 0.45vw, 8px) clamp(3px, 0.34vw, 6px) rgb(0 0 0 / 38%));
  transform: translateY(0);
}

.game-table.sprite-tile-mode .human-hand .mahjong-tile {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  opacity: 1;
}

.game-table.sprite-tile-mode .human-hand .mahjong-tile::before {
  position: absolute;
  z-index: 0;
  top: 6.2%;
  right: 4.55%;
  bottom: 10.5%;
  left: 4.55%;
  border-radius: 7% 7% 2.4% 2.4% / 4.4% 4.4% 1.6% 1.6%;
  background:
    linear-gradient(90deg, rgb(125 111 84 / 22%) 0 1px, transparent 1px calc(100% - 1px), rgb(76 63 43 / 28%) calc(100% - 1px)),
    linear-gradient(180deg, #eee5d4 0%, #e9dfcd 58%, #e2d6c0 100%);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 48%),
    0 1px 1px rgb(37 27 16 / 18%);
  content: "";
  pointer-events: none;
}

.game-table.sprite-tile-mode .human-hand .production-tile-face {
  position: relative;
  z-index: 1;
}

/* Rigid-body mold geometry: the locked artwork is mechanically separated from
 * its old tapered shell and composited on one shared physical mold. This
 * removes the CSS infill entirely, so adjacent hard tiles meet on a clean,
 * narrow contact seam without overlap or a rectangular white frame. */
.game-table.sprite-tile-mode.rigid-tile-body-v2 .human-hand .mahjong-tile + .mahjong-tile {
  margin-left: calc(var(--tile-width) * -0.1);
}

.game-table.sprite-tile-mode.rigid-tile-body-v2 .human-hand .mahjong-tile::before {
  content: none;
}

.game-table.sprite-tile-mode.rigid-tile-body-v2 .human-hand .mahjong-tile {
  filter: drop-shadow(0 clamp(4px, 0.42vw, 7px) clamp(3px, 0.3vw, 5px) rgb(0 0 0 / 34%));
}

/* The locked V3 production assets retain the accepted mold and seam geometry.
 * Material refinement and the Wan two-zone grid are baked into the PNGs, so CSS must not
 * introduce any extra shift, scale or spacing difference. */
.game-table.sprite-tile-mode.rigid-tile-body-v3 .human-hand .mahjong-tile {
  image-rendering: auto;
}

.game-table.sprite-tile-mode .mahjong-tile:hover,
.game-table.sprite-tile-mode .mahjong-tile.is-selected {
  box-shadow: none;
  filter:
    drop-shadow(0 clamp(7px, 0.7vw, 12px) clamp(5px, 0.5vw, 9px) rgb(0 0 0 / 45%))
    drop-shadow(0 0 clamp(3px, 0.3vw, 6px) rgb(246 196 95 / 82%));
  transform: translateY(clamp(-10px, -1.1vw, -17px));
}

.game-table.sprite-tile-mode .mahjong-tile.is-illegal {
  filter: drop-shadow(0 clamp(4px, 0.45vw, 8px) clamp(3px, 0.34vw, 6px) rgb(0 0 0 / 38%));
  opacity: 1;
}

.game-table.sprite-tile-mode .wall-top {
  top: 15.2%;
  left: 50%;
  display: grid;
  gap: clamp(0px, 0.05vw, 1px);
  width: 38%;
  grid-template-columns: repeat(var(--wall-stack-count, 14), minmax(0, 1fr));
  justify-content: center;
  transform: translateX(-50%);
  opacity: 1;
}

.game-table.sprite-tile-mode .wall-self {
  right: 27%;
  bottom: 20.4%;
  left: 27%;
  display: grid;
  gap: clamp(0px, 0.05vw, 1px);
  grid-template-columns: repeat(var(--wall-stack-count, 14), minmax(0, 1fr));
  opacity: 1;
}

.game-table.sprite-tile-mode .wall-self .wall-stack {
  width: 100%;
  height: clamp(20px, 1.72vw, 35px);
  border: 0;
  border-radius: 0;
  background: url("./assets/tiles/wall-flat-master-v1.png") center / 100% 100% no-repeat;
  box-shadow: none;
  filter: drop-shadow(0 3px 3px rgb(0 0 0 / 22%));
}

.game-table.sprite-tile-mode .wall-top .wall-stack {
  width: 100%;
  height: clamp(20px, 1.72vw, 35px);
  flex: 0 0 auto;
  border: 0;
  border: 0;
  border-radius: 0;
  background: url("./assets/tiles/wall-flat-master-v1.png") center / 100% 100% no-repeat;
  box-shadow: none;
  filter: drop-shadow(0 3px 3px rgb(0 0 0 / 22%));
}

.game-table.sprite-tile-mode .wall-top .wall-stack::before {
  content: none;
}

.game-table.sprite-tile-mode .wall-top .wall-stack.is-single {
  background-image: url("./assets/tiles/wall-upright-master-v1.png");
}

.game-table.sprite-tile-mode .wall-left,
.game-table.sprite-tile-mode .wall-right {
  top: 45.4%;
  display: flex;
  flex-direction: column;
  gap: 0;
  opacity: 1;
}

.game-table.sprite-tile-mode .wall-left .wall-stack + .wall-stack,
.game-table.sprite-tile-mode .wall-right .wall-stack + .wall-stack {
  margin-top: -0.58vw;
}

.game-table.sprite-tile-mode .wall-left {
  left: 17.6%;
  transform: translateY(-50%) rotate(18.5deg);
  transform-origin: 50% 50%;
}

.game-table.sprite-tile-mode .wall-right {
  right: 17.6%;
  transform: translateY(-50%) rotate(-18.5deg);
  transform-origin: 50% 50%;
}

.game-table.sprite-tile-mode .wall-left .wall-stack,
.game-table.sprite-tile-mode .wall-right .wall-stack {
  width: clamp(28px, 2.76vw, 56px);
  height: clamp(22px, 2.22vw, 46px);
  flex: 0 0 auto;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  filter: drop-shadow(2px 3px 2px rgb(0 0 0 / 25%));
}

.game-table.sprite-tile-mode .wall-left .wall-stack {
  background: url("./assets/tiles/wall-left-master-v1.png") center / 100% 100% no-repeat;
  transform: none;
}

.game-table.sprite-tile-mode .wall-right .wall-stack {
  background: url("./assets/tiles/wall-right-master-v1.png") center / 100% 100% no-repeat;
  transform: none;
}

.game-table.sprite-tile-mode .wall-left .wall-stack:nth-child(n + 15),
.game-table.sprite-tile-mode .wall-right .wall-stack:nth-child(n + 15) {
  display: none;
}

.game-table.sprite-tile-mode .discard-zone {
  z-index: 14;
  width: auto;
  min-height: 0;
  gap: clamp(2px, 0.2vw, 4px);
}

.game-table.sprite-tile-mode .discard-zone .mini-tile {
  --tile-width: clamp(22px, 2.32vw, 46px);
  width: var(--tile-width);
  height: calc(var(--tile-width) * 1.3889);
}

.game-table.sprite-tile-mode .discards-top,
.game-table.sprite-tile-mode .discards-self {
  left: 50.8%;
  display: grid;
  grid-template-columns: repeat(6, auto);
  transform: translateX(-50%);
}

.game-table.sprite-tile-mode .discards-top {
  top: 29.4%;
}

.game-table.sprite-tile-mode .discards-self {
  bottom: 36.8%;
}

.game-table.sprite-tile-mode .discards-left,
.game-table.sprite-tile-mode .discards-right {
  top: 43%;
  display: grid;
  width: auto;
  grid-template-columns: repeat(6, auto);
}

.game-table.sprite-tile-mode .discards-left {
  left: 35.4%;
  transform: translateY(-50%) rotate(90deg);
}

.game-table.sprite-tile-mode .discards-right {
  right: 34.8%;
  transform: translateY(-50%) rotate(-90deg);
}

@media (max-aspect-ratio: 4 / 3) {
  .app-shell {
    place-items: start center;
    overflow: auto;
  }

  .game-table {
    width: 100vw;
    min-width: 860px;
  }
}

@media (max-height: 560px) {
  :root {
    --tile-width: clamp(31px, 4.1vw, 58px);
  }

  .history-drawer,
  .rule-pill {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* Formal WebGL is the single source of truth for all physical tiles.  These
 * selectors intentionally live at the end of the cascade: midgame and sprite
 * laboratory rules below the original WebGL block used to turn the legacy DOM
 * wall and river back on, which looked like a cached/ghost table over the 3D
 * scene. */
.game-table.production-3d-mode .opponent-rack,
.game-table.production-3d-mode .tile-wall,
.game-table.production-3d-mode .discard-zone,
.game-table.production-3d-mode .meld-zone {
  display: none !important;
}

/* Adult visual master V1 keeps 1488 x 805 as its optical QA frame.  Production
 * WebGL uses the full phone viewport; the canonical frame is centred inside it
 * only for overlay coordinates and touch targets. */
body {
  background:
    radial-gradient(circle at 50% 16%, rgb(66 52 35 / 34%), transparent 36%),
    radial-gradient(circle at 12% 52%, rgb(33 71 57 / 18%), transparent 28%),
    linear-gradient(180deg, #15130f 0%, #08120f 52%, #030806 100%);
}

.game-table.production-3d-mode.adult-visual-master-v1 {
  background:
    radial-gradient(circle at 50% 18%, rgb(74 51 28 / 24%), transparent 34%),
    radial-gradient(circle at 88% 12%, rgb(54 79 58 / 16%), transparent 28%),
    linear-gradient(180deg, #17130e 0%, #091410 34%, #040b09 100%);
  box-shadow:
    0 22px 64px rgb(0 0 0 / 48%),
    inset 0 0 0 1px rgb(246 216 151 / 8%);
}

/* A phone shows one continuous mahjong tabletop.  Transparent WebGL pixels
 * beyond a cropped decorative rail continue as felt instead of revealing a
 * black stage band, so safe-area differences never create empty strips. */
.game-table.production-3d-mode.adult-visual-master-v1.mobile-full-bleed-v2 {
  --screen-edge-rail: clamp(7px, 1.15vmin, 13px);
  background:
    radial-gradient(ellipse at 50% 48%, rgb(32 151 124 / 46%), transparent 48%),
    radial-gradient(ellipse at 10% 94%, rgb(255 255 255 / 4%), transparent 30%),
    linear-gradient(155deg, #0d7b67 0%, #075b4e 48%, #043f37 100%);
  box-shadow: none;
}

/* The phone is the cropped window of one physical table.  Four narrow wooden
 * edge bands preserve that fact without spending playable pixels on the old
 * deep decorative frame.  Because this trim is screen-space, every supported
 * phone ratio receives the same physical-looking edge and the WebGL table
 * geometry never has to stretch. */
.game-table.production-3d-mode.adult-visual-master-v1.mobile-full-bleed-v2.mobile-felt-active-v1::before {
  position: absolute;
  z-index: 4;
  inset: 0;
  background:
    linear-gradient(180deg, #b56b37 0%, #74401f 36%, #351a0d 82%, #1b0c06 100%)
      top / 100% var(--screen-edge-rail) no-repeat,
    linear-gradient(0deg, #b56b37 0%, #74401f 36%, #351a0d 82%, #1b0c06 100%)
      bottom / 100% var(--screen-edge-rail) no-repeat,
    linear-gradient(90deg, #a85e30 0%, #673719 42%, #2b140a 82%, #180a05 100%)
      left / var(--screen-edge-rail) 100% no-repeat,
    linear-gradient(270deg, #a85e30 0%, #673719 42%, #2b140a 82%, #180a05 100%)
      right / var(--screen-edge-rail) 100% no-repeat;
  content: "";
  pointer-events: none;
  filter: saturate(0.88) brightness(0.92);
  box-shadow:
    inset 0 0 0 1px rgb(244 200 119 / 16%),
    inset 0 0 calc(var(--screen-edge-rail) * 1.4) rgb(0 0 0 / 12%);
}

.game-table.production-3d-mode.adult-visual-master-v1::after {
  position: absolute;
  z-index: 3;
  inset: 0;
  border: 1px solid rgb(219 177 96 / 10%);
  background:
    radial-gradient(ellipse at 50% 53%, transparent 58%, rgb(0 10 7 / 13%) 100%),
    linear-gradient(180deg, rgb(255 233 184 / 2%), transparent 20% 82%, rgb(0 0 0 / 8%));
  content: "";
  pointer-events: none;
}

.game-table.adult-visual-master-v1 .brand-lockup h1 {
  color: #ead39a;
  text-shadow: 0 2px 7px rgb(15 7 2 / 78%);
}

.game-table.adult-visual-master-v1 .brand-seal,
.game-table.adult-visual-master-v1 .round-button {
  border-color: rgb(205 161 77 / 78%);
  background-color: rgb(8 24 19 / 78%);
  box-shadow:
    inset 0 0 0 1px rgb(255 238 188 / 10%),
    0 5px 13px rgb(0 0 0 / 24%);
}

.game-table.adult-visual-master-v1 .player-copy {
  border-color: rgb(199 155 74 / 64%);
  color: #f0e6ce;
  background: linear-gradient(90deg, rgb(7 27 22 / 92%), rgb(10 34 27 / 76%));
  box-shadow: 0 6px 14px rgb(0 0 0 / 20%);
}

.game-table.adult-visual-master-v1 .player-copy small {
  color: #e4b85f;
}

.game-table.adult-visual-master-v1 .player-top {
  left: 18.6%;
}

.game-table.adult-visual-master-v1 .center-console {
  top: var(--center-console-y);
  width: var(--center-console-width);
  box-shadow: none;
  filter: none;
}

/* The production renderer owns the physical wind console at the table-world
 * origin.  Keep the live DOM copy for semantics only; painting both would
 * create a drifting second console that can overlap the river. */
.game-table.production-3d-mode.has-webgl .center-console {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  pointer-events: none;
  opacity: 0;
}

.game-table.adult-visual-master-v1 .center-value small {
  color: #ddd4c1;
}

.game-table.adult-visual-master-v1 .center-value strong {
  color: #f0e4bf;
}

.game-table.adult-visual-master-v1 .turn-timer {
  color: #d39232;
  text-shadow: 0 1px 3px rgb(0 0 0 / 78%);
}

.game-table.adult-visual-master-v1 .action-panel {
  right: 24%;
  bottom: 28.6%;
  gap: calc(14 * var(--master-scale));
}

.game-table.adult-visual-master-v1 .game-button {
  min-width: calc(120 * var(--master-scale));
  padding: calc(10 * var(--master-scale)) calc(16 * var(--master-scale));
  font-size: calc(27 * var(--master-scale));
  border-color: rgb(206 163 78 / 76%);
  color: #f2e6c7;
  background: linear-gradient(180deg, #55652f 0%, #3c4927 58%, #27351f 100%);
  box-shadow:
    0 3px 0 rgb(39 23 11 / 72%),
    0 7px 15px rgb(0 0 0 / 22%),
    inset 0 1px 0 rgb(255 244 207 / 20%);
}

.game-table.adult-visual-master-v1.stage-playing .disabled-feature:nth-of-type(2) {
  background: linear-gradient(180deg, #547c37, #365c2b 64%, #24431f);
}

.game-table.adult-visual-master-v1.stage-playing .disabled-feature:nth-of-type(3) {
  background: linear-gradient(180deg, #b57b2d, #814b1b 64%, #5b3014);
}

.game-table.adult-visual-master-v1 .game-button.win {
  background: linear-gradient(180deg, #b74732, #8f2f25 64%, #5f1d19);
}

/* Local-hand near-read layer. The visible tiles remain shared 3D models; this
 * transparent DOM rail only mirrors their optical footprint for accurate
 * mouse and touch selection. */
.game-table.production-3d-mode.player-view-hand-v2 .human-hand {
  --tile-width: calc(96 * var(--master-scale));
  --tile-height: calc(132 * var(--master-scale));
  right: max(var(--safe-right), var(--human-hand-side-inset));
  bottom: calc(226 * var(--master-scale));
  left: max(var(--safe-left), var(--human-hand-side-inset));
  gap: 0;
}

.game-table.production-3d-mode.player-view-hand-v2 .human-hand .mahjong-tile.is-drawn {
  margin-left: calc(14 * var(--master-scale));
}

@media (max-aspect-ratio: 4 / 3) {
  .app-shell {
    place-items: center;
    overflow: hidden;
  }

  .game-table.production-3d-mode.adult-visual-master-v1 {
    width: min(100vw, calc(100vh * var(--master-width) / var(--master-height)));
    min-width: 0;
    height: min(100vh, calc(100vw * var(--master-height) / var(--master-width)));
    aspect-ratio: var(--master-aspect);
  }
}

/* Mobile landscape production frame.  The table and WebGL canvas fill every
 * available CSS pixel, while the optical overlay keeps the locked master scale
 * and centres itself through --master-offset-x/y. */
.game-table.production-3d-mode.adult-visual-master-v1 {
  width: 100vw;
  width: 100dvw;
  min-width: 0;
  height: 100vh;
  height: 100dvh;
  aspect-ratio: auto;
  touch-action: manipulation;
}

.game-table.production-3d-mode .top-bar {
  top: max(var(--safe-top), calc(var(--master-offset-y) + 18 * var(--master-scale)));
  right: max(var(--safe-right), calc(var(--master-offset-x) + 18 * var(--master-scale)));
  left: max(var(--safe-left), calc(var(--master-offset-x) + 18 * var(--master-scale)));
}

.game-table.production-3d-mode .brand-lockup h1 {
  font-size: calc(42 * var(--master-scale));
}

.game-table.production-3d-mode .brand-seal {
  width: calc(64 * var(--master-scale));
}


@media (orientation: portrait) {
  .game-table.production-3d-mode.adult-visual-master-v1 {
    min-width: 100dvw;
  }
}

.mobile-rotate-hint {
  position: fixed;
  z-index: 12100;
  top: 50%;
  left: 50%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px;
  border: 1px solid rgb(230 190 101 / 70%);
  border-radius: 999px;
  color: #f7e7b9;
  background: rgb(5 35 27 / 94%);
  box-shadow: 0 16px 42px rgb(0 0 0 / 42%);
  font-size: 18px;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.mobile-rotate-hint[hidden] {
  display: none;
}

.mobile-rotate-hint span {
  color: #e1b251;
  font-size: 28px;
}

html.mobile-game-shell,
html.mobile-game-shell body,
html.mobile-game-shell .app-shell,
html.mobile-game-shell .game-table {
  width: 100vw;
  width: 100dvw;
  height: 100vh;
  height: 100dvh;
  overscroll-behavior: none;
}

/* Cinematic seat laboratory: the WebGL world establishes all four seats,
 * while the local rack is rendered by an independent presentation camera. */
.cinematic-skip {
  position: absolute;
  z-index: 80;
  bottom: max(var(--safe-bottom), 3.2%);
  left: 50%;
  padding: 0.48em 1.12em;
  transform: translateX(-50%);
  border: 1px solid rgb(220 177 90 / 72%);
  border-radius: 999px;
  color: #f4e4bd;
  background: rgb(7 24 20 / 82%);
  box-shadow: 0 6px 18px rgb(0 0 0 / 28%);
  font-size: clamp(11px, 1.05vw, 16px);
  backdrop-filter: blur(6px);
  cursor: pointer;
}

.cinematic-skip[hidden] {
  display: none;
}


/* Mobile full-bleed V2
 *
 * The playable felt covers the real landscape viewport.  The long-lens WebGL
 * camera may crop decorative rail corners, while all walls, racks, rivers and
 * melds remain inside the screen.  Persistent UI stays in narrow edge-safe
 * strips and contextual actions sit above, never on top of, the local rack. */
@media (orientation: landscape) and (max-height: 620px),
  (orientation: portrait) and (pointer: coarse) {
  .game-table.mobile-full-bleed-v2 {
    background:
      radial-gradient(ellipse at 50% 42%, rgb(30 147 122 / 38%), transparent 45%),
      radial-gradient(ellipse at 10% 92%, rgb(255 255 255 / 4%), transparent 30%),
      linear-gradient(155deg, #0d7b67 0%, #075b4e 48%, #043f37 100%);
    box-shadow: none;
  }

  .game-table.mobile-full-bleed-v2::after {
    border: 0;
    background:
      radial-gradient(ellipse at 50% 50%, transparent 73%, rgb(0 27 22 / 9%) 100%),
      linear-gradient(180deg, rgb(255 244 210 / 1.5%), transparent 18% 88%, rgb(0 20 15 / 4%));
  }

  .game-table.mobile-full-bleed-v2 .top-bar {
    top: max(var(--safe-top), 6px);
    right: max(var(--safe-right), 8px);
    left: max(var(--safe-left), 8px);
    gap: 6px;
  }

  .game-table.mobile-full-bleed-v2 .brand-lockup {
    gap: 0;
  }

  .game-table.mobile-full-bleed-v2 .brand-lockup h1,
  .game-table.mobile-full-bleed-v2 .brand-lockup p,
  .game-table.mobile-full-bleed-v2 .brand-lockup::after {
    display: none;
  }

  .game-table.mobile-full-bleed-v2 .brand-seal {
    width: clamp(28px, 8cqh, 34px);
    border-width: 1px;
  }

  .game-table.mobile-full-bleed-v2 .top-actions {
    gap: 5px;
  }

  .game-table.mobile-full-bleed-v2 .round-button {
    width: clamp(28px, 8cqh, 34px);
    min-width: 0;
    border-width: 1px;
  }

  .game-table.mobile-full-bleed-v2 #helpButton::before {
    font-size: clamp(17px, 5cqh, 22px);
  }

  .game-table.mobile-full-bleed-v2 #soundButton::before {
    font-size: clamp(12px, 3.6cqh, 16px);
  }

  .game-table.mobile-full-bleed-v2 .realtime-status {
    display: none;
  }

  .game-table.mobile-full-bleed-v2 .toast {
    top: auto;
    bottom: max(var(--safe-bottom), 31%);
    max-width: 38%;
    padding: 5px 12px;
    font-size: clamp(9px, 2.6cqh, 12px);
    transform: translate(-50%, 10px);
  }

  .game-table.mobile-full-bleed-v2 .toast.is-visible {
    transform: translate(-50%, 0);
  }

  .game-table.mobile-full-bleed-v2 .player-card {
    height: clamp(32px, 9.5cqh, 40px);
  }

  .game-table.mobile-full-bleed-v2 .avatar {
    width: clamp(32px, 9.5cqh, 40px);
    border-width: 2px;
  }

  .game-table.mobile-full-bleed-v2 .player-copy {
    min-width: clamp(76px, 16vw, 108px);
    margin-left: -6px;
    padding: 4px 8px 4px 17px;
    border-radius: 0 11px 11px 0;
  }

  .game-table.mobile-full-bleed-v2 .player-copy strong,
  .game-table.mobile-full-bleed-v2 .player-copy small {
    font-size: clamp(9px, 2.8cqh, 12px);
    line-height: 1.08;
  }

  .game-table.mobile-full-bleed-v2 .missing-badge {
    right: -12%;
    bottom: -10%;
    left: auto;
    width: clamp(28px, 7.4cqh, 38px);
    border-width: 2px;
  }

  .game-table.mobile-full-bleed-v2 .missing-badge::after {
    font-size: clamp(16px, 4.6cqh, 22px);
  }

  .game-table.mobile-full-bleed-v2 .player-top {
    top: max(var(--safe-top), 4px) !important;
    left: max(var(--safe-left), 48px) !important;
    transform: none !important;
  }

  .game-table.mobile-full-bleed-v2 .player-left {
    top: 43% !important;
    left: max(var(--safe-left), 2px) !important;
  }

  .game-table.mobile-full-bleed-v2 .player-right {
    top: 22% !important;
    right: max(var(--safe-right), 2px) !important;
  }

  .game-table.mobile-full-bleed-v2 .player-self {
    top: auto !important;
    right: auto !important;
    bottom: max(var(--safe-bottom), 12%) !important;
    left: max(var(--safe-left), 3px) !important;
  }

  .game-table.mobile-full-bleed-v2 .player-self .player-copy,
  .game-table.mobile-full-bleed-v2 .player-self .missing-badge {
    display: none;
  }

  .game-table.mobile-full-bleed-v2.player-view-hand-v2 .human-hand {
    --tile-width: calc(96 * var(--master-scale));
    --tile-height: calc(132 * var(--master-scale));
    right: 7.5%;
    bottom: max(var(--safe-bottom), 2.5%);
    left: 7.5%;
  }

  .game-table.mobile-full-bleed-v2 .action-panel,
  .game-table.mobile-full-bleed-v2.stage-playing.has-win-prompt .action-panel {
    z-index: 95;
    right: max(var(--safe-right), 8px) !important;
    bottom: max(var(--safe-bottom), 33%) !important;
    left: auto !important;
    max-width: calc(100% - max(var(--safe-left), 150px) - max(var(--safe-right), 8px));
    gap: 6px !important;
  }

  .game-table.mobile-full-bleed-v2 .game-button,
  .game-table.mobile-full-bleed-v2.stage-playing #huButton:not(:disabled) {
    min-width: clamp(58px, 9.6vw, 82px);
    min-height: 32px;
    padding: 5px 12px;
    border-width: 1px;
    font-size: clamp(15px, 4.2cqh, 19px);
    line-height: 1;
    box-shadow:
      0 2px 0 rgb(48 27 11 / 76%),
      0 5px 12px rgb(0 0 0 / 30%),
      inset 0 1px 0 rgb(255 255 255 / 28%);
  }

  .game-table.mobile-full-bleed-v2 .game-button.primary {
    min-width: clamp(96px, 15vw, 126px);
    font-family: "Microsoft YaHei", sans-serif;
    font-size: clamp(12px, 3.35cqh, 15px);
  }

  .game-table.mobile-full-bleed-v2.stage-exchange #primaryButton:disabled {
    display: none;
  }

  .game-table.mobile-full-bleed-v2 .action-panel .game-button:disabled,
  .game-table.mobile-full-bleed-v2.stage-exchange #hintButton,
  .game-table.mobile-full-bleed-v2.stage-exchange #pengButton,
  .game-table.mobile-full-bleed-v2.stage-exchange #gangButton,
  .game-table.mobile-full-bleed-v2.stage-exchange #huButton {
    display: none;
  }

  .game-table.mobile-full-bleed-v2.stage-exchange #primaryButton:not(:disabled) {
    display: block;
  }

  .game-table.mobile-full-bleed-v2.stage-playing #huButton:not(:disabled)::after {
    right: 0;
    bottom: calc(100% + 5px);
    padding: 3px 8px;
    font-size: 10px;
    transform: none;
  }

  /* The local seat follows the same compact identity rule as the three
   * opponents: its missing-suit marker stays visible, while copy remains in
   * the click-only popover. */
  .game-table.mobile-full-bleed-v2 .player-self .missing-badge {
    display: grid;
  }
}

/* Product shell V1
 * A compact original lobby around the existing account and room services.
 * It is present only before a round; the live table remains free of persistent
 * navigation, support copy or promotional panels. */
.product-shell-card {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  width: min(92%, 980px);
  height: min(86%, 650px);
  max-height: calc(100dvh - var(--safe-top) - var(--safe-bottom) - 24px);
  padding: 0;
  overflow: hidden;
  border-color: rgb(237 193 99 / 42%);
  background:
    radial-gradient(circle at 76% 12%, rgb(219 166 70 / 15%), transparent 30%),
    linear-gradient(145deg, rgb(10 68 54 / 98%), rgb(3 28 22 / 99%));
  text-align: left;
}

.product-shell-header {
  display: flex;
  min-height: 66px;
  padding: 12px 18px;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  border-bottom: 1px solid rgb(255 225 155 / 11%);
  background: rgb(0 19 14 / 28%);
}

.product-shell-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #ffe1a0;
}

.product-shell-brand > img {
  width: 40px;
  aspect-ratio: 1;
  object-fit: contain;
  filter: drop-shadow(0 3px 6px rgb(0 0 0 / 45%));
}

.product-shell-brand > strong {
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(20px, 2vw, 30px);
  letter-spacing: 0.08em;
  white-space: nowrap;
}

.product-shell-account {
  display: flex;
  min-width: 174px;
  padding: 6px 9px;
  align-items: center;
  gap: 8px;
  border: 1px solid rgb(239 195 105 / 22%);
  border-radius: 999px;
  color: #fff3d6;
  background: rgb(0 24 18 / 52%);
  cursor: pointer;
  text-align: left;
}

.product-shell-account > img {
  width: 36px;
  aspect-ratio: 1;
  object-fit: cover;
  border: 1px solid #d9a84d;
  border-radius: 50%;
}

.product-shell-account > span {
  display: grid;
  min-width: 0;
  flex: 1;
}

.product-shell-account strong,
.product-shell-account small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.product-shell-account strong {
  font-size: 13px;
}

.product-shell-account small {
  color: rgb(255 255 255 / 52%);
  font-size: 9px;
}

.product-shell-account > i {
  color: #e4b75f;
  font-size: 22px;
  font-style: normal;
}

.product-shell-content {
  min-height: 0;
  padding: clamp(14px, 2vw, 28px);
  overflow: auto;
  overscroll-behavior: contain;
}

.product-shell-hero {
  display: flex;
  min-height: 132px;
  padding: clamp(18px, 2vw, 28px);
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  border: 1px solid rgb(244 205 126 / 20%);
  border-radius: 20px;
  background:
    radial-gradient(circle at 82% 20%, rgb(244 188 84 / 20%), transparent 38%),
    linear-gradient(128deg, rgb(36 111 85 / 78%), rgb(8 51 39 / 64%));
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 8%);
}

.product-shell-hero > div > span,
.product-shell-section > header span,
.product-game-card small {
  color: #d8a94d;
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.18em;
}

.product-shell-hero h2,
.product-shell-section > header h2 {
  margin: 3px 0 0;
  color: #ffe6ad;
  font-family: STKaiti, KaiTi, serif;
  font-size: clamp(28px, 3.2vw, 46px);
  letter-spacing: 0.08em;
}

.product-shell-hero p,
.product-shell-section > header p,
.product-game-card p,
.product-room-actions p,
.product-shell-empty p,
.product-support details p {
  margin: 5px 0 0;
  color: rgb(255 255 255 / 60%);
  font-size: 12px;
  line-height: 1.5;
}

.product-shell-continue {
  min-width: 148px;
  padding: 13px 18px;
  border: 1px solid rgb(255 224 156 / 38%);
  border-radius: 14px;
  color: #261705;
  background: linear-gradient(180deg, #ffe197, #c88b2f);
  box-shadow: 0 5px 0 #704817, 0 12px 25px rgb(0 0 0 / 25%);
  cursor: pointer;
  text-align: left;
}

.product-shell-continue small,
.product-shell-continue strong {
  display: block;
}

.product-shell-continue small {
  opacity: 0.66;
  font-size: 9px;
}

.product-shell-continue strong {
  margin-top: 2px;
  font-size: 18px;
}

.product-shell-game-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 12px;
}

.product-game-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  min-height: 112px;
  padding: 16px;
  align-items: center;
  gap: 13px;
  border: 1px solid rgb(255 255 255 / 9%);
  border-radius: 17px;
  background: rgb(255 255 255 / 4%);
}

.product-game-card.is-featured {
  border-color: rgb(235 187 91 / 25%);
  background: linear-gradient(135deg, rgb(45 122 91 / 28%), rgb(255 255 255 / 3%));
}

.product-game-card-seal,
.product-room-actions article > span,
.product-shell-empty > span {
  display: grid;
  width: 48px;
  aspect-ratio: 1;
  place-items: center;
  border: 1px solid rgb(232 185 89 / 45%);
  border-radius: 14px;
  color: #ffe3a4;
  background: rgb(0 23 17 / 40%);
  font-family: STKaiti, KaiTi, serif;
  font-size: 23px;
}

.product-game-card h3,
.product-room-actions h3,
.product-shell-empty h2 {
  margin: 3px 0 0;
  color: #fff3d5;
  font-size: 18px;
}

.product-game-card > button,
.product-room-actions button,
.product-room-join button {
  min-width: 88px;
  padding: 9px 13px;
  border: 1px solid rgb(255 226 162 / 32%);
  border-radius: 999px;
  color: #fff1cf;
  background: linear-gradient(180deg, #3f7d68, #1e5140);
  cursor: pointer;
  font-weight: 800;
}

.product-shell-section {
  max-width: 780px;
  margin: 0 auto;
}

.product-shell-section > header {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 20px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgb(255 255 255 / 9%);
}

.product-shell-section > header h2 {
  font-size: clamp(25px, 2.8vw, 38px);
}

.product-shell-section > header p {
  max-width: 34em;
  text-align: right;
}

.product-room-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin-top: 16px;
}

.product-room-actions article {
  display: grid;
  min-height: 176px;
  padding: 17px;
  align-content: start;
  justify-items: start;
  border: 1px solid rgb(255 255 255 / 9%);
  border-radius: 17px;
  background: rgb(255 255 255 / 4%);
}

.product-room-actions article > button {
  margin-top: auto;
}

.product-room-join {
  display: flex;
  width: 100%;
  gap: 7px;
  margin-top: auto;
}

.product-room-join input {
  min-width: 0;
  flex: 1;
  padding: 9px 12px;
  border: 1px solid rgb(255 255 255 / 13%);
  border-radius: 999px;
  outline: none;
  color: #fff7df;
  background: rgb(0 16 12 / 55%);
}

.product-shell-empty {
  display: grid;
  max-width: 520px;
  min-height: 100%;
  margin: auto;
  place-content: center;
  justify-items: center;
  text-align: center;
}

.product-shell-empty .modal-button {
  margin-top: 18px;
}

.product-support-grid {
  display: grid;
  gap: 8px;
  margin-top: 14px;
}

.product-support details {
  padding: 11px 14px;
  border: 1px solid rgb(255 255 255 / 9%);
  border-radius: 12px;
  background: rgb(255 255 255 / 4%);
}

.product-support summary {
  color: #fff1d0;
  cursor: pointer;
  font-size: 13px;
  font-weight: 800;
}

.product-support-actions {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 15px;
}

.product-profile > .product-shell-account {
  width: min(100%, 460px);
  margin: 18px auto 0;
}

.product-profile-facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 14px auto;
}

.product-profile-facts > span {
  display: grid;
  min-width: 0;
  padding: 12px;
  border: 1px solid rgb(255 255 255 / 8%);
  border-radius: 12px;
  background: rgb(255 255 255 / 4%);
}

.product-profile-facts small {
  color: rgb(255 255 255 / 46%);
  font-size: 9px;
}

.product-profile-facts strong {
  overflow: hidden;
  margin-top: 3px;
  color: #fff0ca;
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.product-profile > .modal-button {
  display: block;
  margin: 0 auto;
}

.product-profile-footnote {
  margin: 13px 0 0;
  color: rgb(255 255 255 / 42%);
  font-size: 10px;
  text-align: center;
}

.product-shell-nav {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  min-height: 62px;
  padding: 6px 12px max(6px, var(--safe-bottom));
  gap: 6px;
  border-top: 1px solid rgb(255 225 155 / 11%);
  background: rgb(0 17 13 / 48%);
}

.product-shell-nav-item {
  display: grid;
  grid-template-columns: auto auto;
  place-content: center;
  align-items: center;
  gap: 6px;
  border: 0;
  border-radius: 12px;
  color: rgb(255 255 255 / 48%);
  background: transparent;
  cursor: pointer;
}

.product-shell-nav-item > span {
  display: grid;
  width: 25px;
  aspect-ratio: 1;
  place-items: center;
  border: 1px solid currentColor;
  border-radius: 50%;
  font-family: STKaiti, KaiTi, serif;
  font-size: 13px;
}

.product-shell-nav-item > strong {
  font-size: 12px;
}

.product-shell-nav-item.is-active {
  color: #ffe3a1;
  background: rgb(210 157 63 / 12%);
}

@media (orientation: landscape) and (max-height: 620px),
  (orientation: portrait) and (pointer: coarse) {
  .product-shell-card {
    width: calc(100% - max(var(--safe-left), 6px) - max(var(--safe-right), 6px));
    height: calc(100dvh - max(var(--safe-top), 5px) - max(var(--safe-bottom), 5px));
    max-height: none;
    border-radius: 15px;
  }

  .product-shell-header {
    min-height: 44px;
    padding: 5px 10px;
  }

  .product-shell-brand > img {
    width: 30px;
  }

  .product-shell-brand > strong {
    font-size: 20px;
  }

  .product-shell-account {
    min-width: 145px;
    padding: 3px 7px;
  }

  .product-shell-account > img {
    width: 29px;
  }

  .product-shell-content {
    padding: 8px 10px;
  }

  .product-shell-hero {
    min-height: 76px;
    padding: 8px 14px;
    border-radius: 13px;
  }

  .product-shell-hero h2 {
    margin-top: 0;
    font-size: 26px;
    line-height: 1;
  }

  .product-shell-hero p,
  .product-shell-section > header p,
  .product-game-card p,
  .product-room-actions p,
  .product-shell-empty p,
  .product-support details p {
    margin-top: 2px;
    font-size: 9px;
    line-height: 1.3;
  }

  .product-shell-hero > div > span,
  .product-shell-section > header span,
  .product-game-card small {
    font-size: 7px;
  }

  .product-shell-continue {
    min-width: 116px;
    padding: 7px 11px;
    box-shadow: 0 3px 0 #704817, 0 7px 14px rgb(0 0 0 / 22%);
  }

  .product-shell-continue strong {
    font-size: 14px;
  }

  .product-shell-game-grid {
    gap: 8px;
    margin-top: 8px;
  }

  .product-game-card {
    min-height: 70px;
    padding: 8px 10px;
    gap: 8px;
    border-radius: 12px;
  }

  .product-game-card-seal,
  .product-room-actions article > span,
  .product-shell-empty > span {
    width: 34px;
    border-radius: 10px;
    font-size: 18px;
  }

  .product-game-card h3,
  .product-room-actions h3,
  .product-shell-empty h2 {
    margin-top: 1px;
    font-size: 14px;
  }

  .product-game-card > button,
  .product-room-actions button,
  .product-room-join button {
    min-width: 72px;
    padding: 6px 9px;
    font-size: 10px;
  }

  .product-shell-section > header {
    padding-bottom: 6px;
  }

  .product-shell-section > header h2 {
    font-size: 22px;
    line-height: 1;
  }

  .product-room-actions {
    gap: 8px;
    margin-top: 7px;
  }

  .product-room-actions article {
    min-height: 112px;
    padding: 8px 10px;
    border-radius: 11px;
  }

  .product-room-join input {
    padding: 6px 9px;
    font-size: 10px;
  }

  .product-support-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 6px;
    margin-top: 7px;
  }

  .product-support details {
    padding: 7px 9px;
  }

  .product-support summary {
    font-size: 10px;
  }

  .product-support-actions {
    margin-top: 8px;
  }

  .product-support-actions .modal-button,
  .product-profile > .modal-button {
    min-width: 112px;
    padding: 6px 10px;
    font-size: 10px;
  }

  .product-profile > .product-shell-account {
    margin-top: 8px;
  }

  .product-profile-facts {
    gap: 6px;
    margin: 7px auto;
  }

  .product-profile-facts > span {
    padding: 7px 9px;
  }

  .product-profile-footnote {
    margin-top: 7px;
    font-size: 8px;
  }

  .product-shell-nav {
    min-height: 43px;
    padding: 3px 8px max(3px, var(--safe-bottom));
  }

  .product-shell-nav-item > span {
    width: 21px;
    font-size: 11px;
  }

  .product-shell-nav-item > strong {
    font-size: 10px;
  }
}
