/* Mahjong preview (admin playground). Ivory tiles with jade backs on a lantern-lit night table:
   tiles are heavy, tactile objects; moves are short and weighted, and only the win bounces. */
:root { --mj-blue: #1f4fa8; --mj-green: #147352; --mj-red: #c42d3b; --mj-wind: #1d2b4a; }
.mj-stage {
  --mj-ivory-hi: #fffdf6; --mj-ivory: #f5ecd7; --mj-ivory-lo: #e4d6b8;
  --mj-side: #d8c9a6; --mj-side-lo: #c2ae86;
  --mj-jade: #2f9d81; --mj-jade-lo: #1f735f; --mj-jade-deep: #123f36;
  --mj-felt-hi: #1a4a50; --mj-felt: #0d282d; --mj-felt-lo: #050f12;
  --mj-lantern: #ffc56b; --mj-select: #5ce6c4; --mj-ink-soft: #66573a; --mj-seat-ink: #9fb2d4;
  --mj-press: 90ms; --mj-lift: 160ms; --mj-clear: 420ms; --mj-deal: 520ms;
  position: relative; display: grid; gap: var(--s4); min-width: 0; container-type: inline-size;
}
.mj-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Tabs, HUD and tools follow the shared game look: uppercase labels over tabular values, pill tools. */
.mj-tabs, .mj-segment { display: inline-flex; flex-wrap: wrap; gap: var(--s1); padding: var(--s1); border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); justify-self: start; }
.mj-tabs button, .mj-segment button {
  min-height: 2.5rem; padding: 0 var(--s4); border: 0; border-radius: var(--pill); background: transparent; color: var(--muted);
  font: var(--weight-label) var(--text-sm) / 1 var(--font); cursor: pointer; transition: background var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease), transform var(--mj-press) var(--ease);
}
.mj-tabs button:active, .mj-segment button:active { transform: scale(.97); }
.mj-tabs [aria-selected="true"], .mj-segment [aria-checked="true"] { background: var(--accent); color: var(--on-accent); }
.mj-hud { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s3) var(--s6); }
.mj-stats { display: flex; gap: var(--s6); margin: 0; }
.mj-stats div { display: grid; gap: var(--s1); }
.mj-stats dt { font-size: var(--text-xs); font-weight: var(--weight-label); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--muted); }
.mj-stats dd { margin: 0; font-size: var(--text-xl); font-weight: var(--weight-title); font-variant-numeric: tabular-nums; line-height: 1; }
.mj-stats .mj-warn { color: var(--error); }
.mj-tools { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); }
.mj-tool {
  display: inline-flex; align-items: center; gap: var(--s2); min-height: 2.75rem; padding: 0 var(--s4);
  border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); color: var(--ink);
  font: var(--weight-label) var(--text-sm) / 1 var(--font); cursor: pointer;
  transition: transform var(--mj-press) var(--ease), border-color var(--motion-fast) var(--ease), opacity var(--motion-fast) var(--ease);
}
.mj-tool:hover:not(:disabled) { border-color: var(--sea); }
.mj-tool:active:not(:disabled) { transform: scale(.97); }
.mj-tool:disabled { opacity: .45; cursor: default; }
.mj-options { justify-content: center; }

@media (max-width: 420px) {
  .mj-tools { gap: .25rem; }
  .mj-tool {
    min-height: 2.1rem;
    padding: 0 .6rem;
    font-size: var(--text-xs);
  }
}

@media (max-height: 430px) {
  .mj-stage { gap: .5rem; }
}

/* Phones: every spare point goes to the board. MahjongLayouts.PhoneWidth/PhoneHeight is the room this leaves
   on an iPhone SE, and the layouts are built so tiles stay tappable inside it; change both together. */
@media (max-width: 480px) {
  .shell:has(.game-page.mj-stage) main { padding-top: var(--s2); }
  .game-page.mj-stage { gap: var(--s2); }
  .game-page.mj-stage .mj-felt { padding: 4px; border-radius: var(--radius); }
}
/* The board's shape name is a nicety; the HUD title column on a phone fits the pack, date or rank only. */
@media (max-width: 440px) { .game-page.mj-stage .mj-shape { display: none; } }
.mj-eyebrow-lore { display: none; }
@media (max-width: 480px) and (max-height: 720px) {
  .game-page.mj-stage .game-hud-title .eyebrow:has(.mj-eyebrow-lore) > :not(.mj-eyebrow-lore) { display: none; }
  .game-page.mj-stage .mj-eyebrow-lore {
    display: block; max-width: 100%; min-height: 0; padding: 0; border: 0; background: none; color: var(--hud-eyebrow, var(--muted));
    font: inherit; text-align: left; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor: pointer;
    animation: mj-ticker-in 260ms var(--ease) both;
  }
  .game-page.mj-stage .mj-eyebrow-lore.is-set { color: #e9a83a; }
  .game-page.mj-stage .mj-eyebrow-lore .mj-ticker-han { margin-left: .25rem; font-size: 1.05em; }
  .game-page.mj-stage .mj-ticker { display: none; }
  .game-page.mj-stage .game-hud-track { display: none; }
}

/* The felt: a deep teal cloth lit by one warm lantern off to the upper right. */
.mj-felt, .mj-table {
  position: relative; z-index: 0; isolation: isolate; overflow: hidden; border-radius: var(--radius-lg); color: var(--game-ink); color-scheme: dark;
  background:
    radial-gradient(60% 50% at 82% 0%, color-mix(in srgb, var(--mj-lantern) 16%, transparent), transparent 70%),
    radial-gradient(120% 95% at 50% 10%, var(--mj-felt-hi) 0%, var(--mj-felt) 55%, var(--mj-felt-lo) 100%);
  box-shadow: inset 0 0 0 1px #ffffff12, inset 0 2px 40px #000a, var(--shadow);
}
.mj-felt::before, .mj-table::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .09; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.mj-felt { padding: clamp(var(--s2), 2.5cqi, var(--s6)); }

/* Board geometry: positions are half-tile units; each layer steps straight up, its edge showing below.
   Never shift layers sideways: a raised tile would then overhang its free neighbor and look pinned.
   A layer rises more than its edge is thick, so a strip of every tile underneath stays visible. */
/* A long press on a tile must not start a text selection or the iOS callout. */
.mj-board { position: relative; width: 100%; margin-inline: auto; container-type: inline-size;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
/* The board takes the height app.js measures above the tools (--fit-h), so tiles grow to fill short phones too. */
:root[data-focus] .mj-board { max-width: min(100%, calc(var(--fit-h, 60dvh) * var(--board-ratio))) !important; }
.mj-field {
  position: absolute; inset: 0;
  --tw: calc(100cqi / var(--cols)); --th: calc(var(--tw) * 1.32);
  --lift: calc(var(--tw) * .24); --dp: calc(var(--tw) * .026);
  --pad-x: calc(var(--tw) * (.45 + var(--layers) * .06)); --pad-y: calc(var(--tw) * (.14 + (var(--layers) - 1) * .24));
}
.mj-tile {
  position: absolute; min-height: 0; padding: 0; margin: 0; border: 0; cursor: pointer; appearance: none;
  left: calc(var(--x) * var(--tw) / 2 + var(--pad-x));
  top: calc(var(--y) * var(--th) / 2 - var(--z) * var(--lift) + var(--pad-y));
  width: calc(var(--tw) - 1px); height: calc(var(--th) - 1px);
  border-radius: calc(var(--tw) * .13);
  /* One opaque gradient: the faint jade sheen is pre-mixed into the ivory rather than layered over it. */
  background: linear-gradient(155deg,
    color-mix(in srgb, var(--mj-select) 8%, var(--mj-ivory-hi)) 0%,
    color-mix(in srgb, var(--mj-ivory) 81%, var(--mj-ivory-hi)) 42%,
    var(--mj-ivory) 52%, var(--mj-ivory-lo) 100%);
  box-shadow:
    inset 0 1px 0 #fff, inset 0 -1px 2px #0000001a,
    0 var(--dp) 0 var(--mj-side),
    0 calc(var(--dp) * 2) 0 var(--mj-side-lo),
    0 calc(var(--dp) * 3) 0 var(--mj-jade),
    0 calc(var(--dp) * 4) 0 var(--mj-jade-lo),
    0 calc(var(--dp) * 5) 0 var(--mj-jade-deep),
    0 calc(var(--dp) * (9 + var(--z) * 1.6)) calc(var(--dp) * (8 + var(--z) * 2.1)) calc(var(--dp) * -3) #000000b0,
    0 0 0 1px color-mix(in srgb, var(--mj-select) 18%, transparent);
  /* Transitioning filter repaints every tile's shadow stack on iOS; opacity carries the same change. */
  transition: transform var(--mj-lift) var(--ease), opacity var(--motion-fast) var(--ease);
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.mj-tile::before, .mj-tile::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; transition: opacity var(--motion-normal) var(--ease); }
.mj-tile::before { background: linear-gradient(160deg, #0f2a2c, #061215); opacity: 0; }
.mj-tile::after {
  opacity: 0;
  background: linear-gradient(160deg, color-mix(in srgb, var(--mj-select) 22%, transparent), transparent 60%);
  box-shadow: 0 0 0 2px var(--mj-select), 0 0 calc(var(--tw) * .4) color-mix(in srgb, var(--mj-select) 55%, transparent);
}
.mj-art { position: absolute; left: 8%; top: 6%; width: 84%; height: 88%; pointer-events: none; }
.mj-corner { position: absolute; top: 4%; left: 8%; font: 700 calc(var(--tw) * .16) / 1 var(--font); color: var(--mj-ink-soft); pointer-events: none; }
.no-corners .mj-corner { display: none; }
.mj-tile.blocked::before, .dim-blocked .mj-tile.blocked::before { opacity: .32; }
.mj-tile.blocked { cursor: not-allowed; opacity: .58; filter: saturate(.72) brightness(.86); }
.mj-tile:not(.blocked) { filter: saturate(1.05) brightness(1.03); }
.mj-tile:focus-visible { outline: none; }
.mj-tile:focus-visible::after { opacity: 1; }
@media (hover: hover) and (pointer: fine) {
  .mj-tile:not(.blocked):not(.selected):hover { transform: translate(calc(var(--tw) * .015), calc(var(--tw) * -.03)); }
}
.mj-tile:not(.blocked):active { transform: scale(.97); transition-duration: var(--mj-press); }
.mj-tile.selected { transform: translate(calc(var(--tw) * .03), calc(var(--tw) * -.07)); }
.mj-tile.selected::after { opacity: 1; }
.mj-tile.hinted { transform: translateY(calc(var(--tw) * -.06)); }
.mj-tile.hinted::after { opacity: 1; box-shadow: 0 0 0 3px var(--mj-lantern), 0 0 calc(var(--tw) * .7) color-mix(in srgb, var(--mj-lantern) 85%, transparent); background: color-mix(in srgb, var(--mj-lantern) 18%, transparent); animation: mj-hint 1100ms var(--ease) infinite; }
.mj-tile.shake { animation: mj-shake 260ms var(--ease-move); }
.mj-tile.leaving { pointer-events: none; animation: mj-leave var(--mj-clear) var(--ease-move) forwards; }
.mj-tile.leaving::after { opacity: 1; }
.mj-tile.returning { animation: mj-return 340ms var(--ease-enter); }
.dealing { pointer-events: none; }
.dealing .mj-tile { animation: mj-deal var(--mj-deal) var(--ease-enter) both; animation-delay: calc(var(--z) * 110ms + var(--i) * 3ms); }
.shuffling .mj-tile { animation: mj-flip 460ms var(--ease-move); }

.mj-spark {
  position: absolute; z-index: 100; pointer-events: none; aspect-ratio: 1; border-radius: 50%; translate: -50% -50%;
  left: calc(var(--x) * var(--tw) / 2 + var(--z) * var(--lift) + var(--tw) * .9);
  top: calc(var(--y) * var(--th) / 2 - var(--z) * var(--lift) + var(--layers) * var(--lift) + var(--tw) * .08 + var(--th) / 2);
  width: calc(var(--tw) * 1.9);
  background: radial-gradient(circle, #fffbea 0 6%, color-mix(in srgb, var(--mj-lantern) 55%, transparent) 18%, transparent 62%);
  animation: mj-spark 640ms var(--ease-enter) 160ms both;
}
.mj-spark::after { content: ""; position: absolute; inset: 18%; border-radius: 50%; border: 2px solid var(--mj-lantern); opacity: .8; }

.mj-stuck {
  position: absolute; left: 50%; bottom: var(--s4); translate: -50% 0;
  /* Above every tile: tiles stack their z-index by layer, row and column. */
  z-index: 1000;
  display: grid; justify-items: center; gap: var(--s1);
  width: min(26rem, calc(100% - 2 * var(--s4))); padding: var(--s3) var(--s4); border-radius: var(--radius);
  background: var(--game-card); color: var(--game-ink); box-shadow: 0 1rem 2.5rem #000a, inset 0 0 0 1px #ffffff14;
  animation: mj-rise 320ms var(--ease-enter);
}
.mj-tile.buried { outline: calc(var(--dp) * 3) solid #f6c453; outline-offset: calc(var(--dp) * 1.5); filter: none; opacity: 1; }
.mj-stuck p { margin: 0; font-size: var(--text-sm); }
.mj-stuck p + p { color: var(--game-muted); }
.mj-stuck-actions { display: flex; gap: var(--s2); margin-top: var(--s1); }

/* Small tiles: ponds, melds, the win card. */
.mj-small, .mj-mini {
  --t: 1.75rem; position: relative; display: inline-block; flex: none; width: var(--t); height: calc(var(--t) * 1.32);
  border-radius: calc(var(--t) * .14);
  background: linear-gradient(155deg, var(--mj-ivory-hi), var(--mj-ivory) 55%, var(--mj-ivory-lo));
  box-shadow: inset 0 1px 0 #fff, 0 1px 0 var(--mj-side), 0 2px 0 var(--mj-side-lo), 0 3px 0 var(--mj-jade), 0 4px 0 var(--mj-jade-lo), 0 6px 8px #0008;
}
.mj-small svg, .mj-mini svg { position: absolute; left: 8%; top: 6%; width: 84%; height: 88%; }
.mj-win-card { text-align: center; }
.mj-win-tiles { display: flex; justify-content: center; gap: var(--s2); margin: var(--s2) 0 var(--s4); }
.mj-mini { --t: 2.5rem; animation: mj-pop 520ms var(--ease-pop) both; animation-delay: calc(240ms + var(--k) * 70ms); }
.mj-win-actions { display: grid; gap: var(--s2); }

/* Same shape as every other hub card: one square scene centred on a lit band. */
.hub-art.mj-hub-art {
  padding: var(--s4);
  background: radial-gradient(ellipse at 50% 112%, color-mix(in srgb, var(--mj-lantern) 45%, transparent), transparent 60%),
    linear-gradient(160deg, var(--mj-felt-hi), #050b0a);
}
.mj-hub-scene {
  position: relative; height: 100%; aspect-ratio: 1; overflow: hidden; container-type: size; border-radius: 18%;
  background:
    radial-gradient(ellipse at 70% 5%, color-mix(in srgb, var(--mj-lantern) 30%, transparent), transparent 58%),
    radial-gradient(ellipse at 50% 120%, color-mix(in srgb, var(--mj-jade) 40%, transparent), transparent 58%),
    linear-gradient(150deg, var(--mj-felt-hi), var(--mj-felt-lo));
  box-shadow: 0 .4rem 1rem #0007;
}
.mj-hub-art .mj-mini {
  --t: 18cqw;
  position: absolute;
  left: calc(50% + (var(--x) - 2.5) * var(--t) * .72);
  top: calc(50% + (var(--y) - 1.6) * var(--t) * .4 - var(--z) * var(--t) * .18);
  translate: -50% -50%;
  z-index: var(--z);
}

/* The Arena table. */
.mj-invite {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4); padding: var(--s3) var(--s4);
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
}
.mj-invite-code { display: grid; gap: 2px; }
.mj-invite-code .eyebrow { margin: 0; }
.mj-invite-code strong { font: 700 var(--text-xl) / 1 var(--mono); letter-spacing: .12em; }
.mj-invite-link { font: var(--text-sm) var(--mono); color: var(--muted); min-width: 0; overflow-wrap: anywhere; }
.mj-invite .button { display: inline-flex; align-items: center; gap: var(--s2); }
.mj-invite-note { flex-basis: 100%; margin: 0; }

.mj-table {
  --t: clamp(1.1rem, calc((100cqi - 2.75rem) / 14.6), 3.25rem); --p: calc(var(--t) * .62);
  display: grid; gap: var(--s3); padding: var(--s4);
  grid-template-columns: minmax(0, auto) minmax(0, 1fr) minmax(0, auto);
  grid-template-areas: "top top top" "left center right" "you you you";
}
.mj-seat { position: relative; display: flex; flex-direction: column; align-items: center; gap: var(--s2); min-width: 0; }
.mj-seat-top { grid-area: top; }
.mj-seat-left { grid-area: left; align-self: center; }
.mj-seat-right { grid-area: right; align-self: center; }
.mj-player { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.mj-player-name { display: grid; line-height: 1.2; min-width: 0; }
.mj-player-name strong { font-size: var(--text-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mj-player-name .caption { font-size: var(--text-2xs); color: var(--game-muted); }
.mj-avatar {
  position: relative; display: grid; place-items: center; flex: none; width: 2.5rem; height: 2.5rem; border-radius: 50%;
  font-weight: var(--weight-title); color: #fff; background: linear-gradient(150deg, #4c8dff, #2a4fa8);
  box-shadow: inset 0 1px 0 #ffffff40, 0 0 0 2px #ffffff14; transition: box-shadow var(--motion-normal) var(--ease);
}
.mj-avatar.tag-bot { background: linear-gradient(150deg, #8fa3c8, #4f6185); }
.mj-avatar.tag-guest { background: linear-gradient(150deg, #b073ff, #6a3fb8); }
.mj-avatar.tag-you { background: linear-gradient(150deg, var(--mj-jade), var(--mj-jade-deep)); }
.turn .mj-avatar { box-shadow: inset 0 1px 0 #ffffff40, 0 0 0 2px var(--mj-lantern), 0 0 1.25rem color-mix(in srgb, var(--mj-lantern) 55%, transparent); }
.mj-ring { position: absolute; inset: -5px; width: calc(100% + 10px); height: calc(100% + 10px); rotate: -90deg; }
.mj-ring circle { fill: none; stroke: var(--mj-lantern); stroke-width: 2.5; stroke-linecap: round; stroke-dasharray: 113.1; animation: mj-timer var(--turn) linear forwards; }

.mj-backs { display: flex; gap: 2px; }
.mj-seat-left .mj-backs, .mj-seat-right .mj-backs { flex-direction: column; gap: 0; }
.mj-back {
  width: var(--p); height: calc(var(--p) * 1.1); border-radius: calc(var(--p) * .16);
  background: radial-gradient(70% 55% at 40% 30%, #ffffff26, transparent 70%), linear-gradient(170deg, #45b597 0%, var(--mj-jade) 35%, var(--mj-jade-lo) 100%);
  box-shadow: inset 0 1px 0 #ffffff50, inset 0 -3px 0 var(--mj-ivory-lo), 0 3px 6px #0007;
}
.mj-seat-left .mj-back, .mj-seat-right .mj-back { width: calc(var(--p) * 1.1); height: calc(var(--p) * .52); box-shadow: inset 0 1px 0 #ffffff50, inset -3px 0 0 var(--mj-ivory-lo), 0 2px 4px #0007; }
.mj-seat-right .mj-back { box-shadow: inset 0 1px 0 #ffffff50, inset 3px 0 0 var(--mj-ivory-lo), 0 2px 4px #0007; }
.mj-seat .mj-reveal { --t: var(--p); animation: mj-rise 320ms var(--ease-enter) both; }
.mj-seat-left .mj-backs:has(.mj-reveal), .mj-seat-right .mj-backs:has(.mj-reveal) { flex-direction: row; flex-wrap: wrap; max-width: calc(var(--p) * 4.5); gap: 2px; }
.mj-melds { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); }
.mj-meld { display: inline-flex; gap: 1px; }
.mj-meld .mj-small { --t: var(--p); }

.mj-center {
  grid-area: center; display: grid; align-items: center; justify-items: center; gap: var(--s2); min-width: 0; padding: var(--s2) 0;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-areas: ". ptop ." "pleft compass pright" ". pbottom .";
}
.mj-pond { display: flex; flex-wrap: wrap; gap: 2px; justify-content: center; align-content: center; min-height: calc(var(--p) * 1.32); }
.mj-pond .mj-small { --t: var(--p); animation: mj-toss 380ms var(--ease-enter) both; }
.mj-pond-top { grid-area: ptop; max-width: calc(var(--p) * 6.6); }
.mj-pond-bottom { grid-area: pbottom; max-width: calc(var(--p) * 6.6); }
.mj-pond-left { grid-area: pleft; max-width: calc(var(--p) * 3.4); justify-self: end; }
.mj-pond-right { grid-area: pright; max-width: calc(var(--p) * 3.4); justify-self: start; }
.mj-pond .mj-last { box-shadow: inset 0 1px 0 #fff, 0 0 0 2px var(--mj-lantern), 0 0 .9rem color-mix(in srgb, var(--mj-lantern) 60%, transparent), 0 4px 8px #0008; }
.mj-compass {
  grid-area: compass; position: relative; width: clamp(5.5rem, 16cqi, 6.5rem); aspect-ratio: 1; border-radius: 22%;
  background: radial-gradient(circle at 50% 35%, #173a40, #081619 75%);
  box-shadow: inset 0 0 0 1px #ffffff18, inset 0 -6px 14px #0008, 0 8px 20px #0009;
}
.mj-wind {
  position: absolute; font: 700 var(--text-sm) / 1 "Songti SC", "Noto Serif CJK SC", serif; color: var(--mj-seat-ink);
  transition: color var(--motion-normal) var(--ease), text-shadow var(--motion-normal) var(--ease);
}
.mj-wind.on { color: var(--mj-lantern); text-shadow: 0 0 .6rem var(--mj-lantern); }
.mj-wind-top { top: 8%; left: 50%; translate: -50% 0; }
.mj-wind-bottom { bottom: 8%; left: 50%; translate: -50% 0; }
.mj-wind-left { left: 9%; top: 50%; translate: 0 -50%; }
.mj-wind-right { right: 9%; top: 50%; translate: 0 -50%; }
.mj-wall { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; line-height: 1.05; }
.mj-wall strong { font-size: clamp(var(--text-md), 4.5cqi, var(--text-xl)); font-variant-numeric: tabular-nums; }
.mj-wall span { font-size: .5625rem; text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--game-muted); }

.mj-you { grid-area: you; display: grid; gap: var(--s3); justify-items: center; min-width: 0; }
.mj-you-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s2) var(--s4); width: 100%; }
.mj-log { margin: 0; font-size: var(--text-sm); color: var(--game-muted); min-height: 1.3em; text-align: center; }
.mj-hand { display: flex; justify-content: center; gap: 2px; max-width: 100%; padding-top: calc(var(--t) * .3); }
.mj-htile {
  position: relative; flex: none; width: var(--t); height: calc(var(--t) * 1.32); padding: 0; margin: 0; border: 0; appearance: none; cursor: pointer;
  border-radius: calc(var(--t) * .14);
  background: linear-gradient(170deg, var(--mj-ivory-hi), var(--mj-ivory) 55%, var(--mj-ivory-lo));
  box-shadow: inset 0 1px 0 #fff, inset 0 -2px 3px #0000001a, 0 2px 0 var(--mj-side), 0 4px 0 var(--mj-side-lo), 0 6px 0 var(--mj-jade), 0 8px 0 var(--mj-jade-lo), 0 12px 14px #000a;
  transition: transform var(--mj-lift) var(--ease), box-shadow var(--mj-lift) var(--ease);
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.mj-htile .mj-corner { font-size: calc(var(--t) * .17); }
.mj-htile:disabled { cursor: default; }
.mj-htile:not(:disabled):active { transform: scale(.97); transition-duration: var(--mj-press); }
@media (hover: hover) and (pointer: fine) { .mj-htile:not(:disabled):not(.picked):hover { transform: translateY(-8%); } }
.mj-htile.picked {
  transform: translateY(-24%);
  box-shadow: inset 0 1px 0 #fff, 0 0 0 2px var(--mj-select), 0 0 1.1rem color-mix(in srgb, var(--mj-select) 55%, transparent), 0 2px 0 var(--mj-side), 0 6px 0 var(--mj-jade), 0 18px 18px #000a;
}
.mj-htile.drawn { margin-left: calc(var(--t) * .35); animation: mj-draw 420ms var(--ease-enter) both; }
.mj-htile:focus-visible { outline: 2px solid var(--mj-select); outline-offset: 2px; }

.mj-actions { min-height: 3rem; display: grid; place-items: center; }
.mj-actions .caption { margin: 0; color: var(--game-muted); }
.mj-claim {
  position: relative; overflow: hidden; display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3);
  border-radius: var(--radius); background: var(--game-card); box-shadow: 0 .75rem 2rem #000a, inset 0 0 0 1px #ffffff14;
  animation: mj-rise 280ms var(--ease-enter);
}
.mj-claim .button { min-height: 2.75rem; }
.mj-claim-tile .mj-small { --t: 2rem; }
.mj-claim-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--mj-lantern); transform-origin: left; animation: mj-drain var(--claim) linear forwards; }
.mj-win { background: linear-gradient(150deg, var(--mj-lantern), #e2683a); color: #2a1406; border-color: transparent; }
.mj-result-hand { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); margin: var(--s2) 0; }
.mj-result-hand .mj-small { --t: clamp(1.4rem, 6vw, 2rem); }

@container (max-width: 34rem) {
  .mj-table { padding: var(--s3) var(--s2); gap: var(--s2); }
  .mj-seat-left .mj-player, .mj-seat-right .mj-player { flex-direction: column; text-align: center; }
  .mj-seat-left .mj-player-name .caption, .mj-seat-right .mj-player-name .caption { display: none; }
  .mj-avatar { width: 2.1rem; height: 2.1rem; font-size: var(--text-sm); }
  .mj-segment button { padding: 0 var(--s3); font-size: var(--text-xs); }
  .mj-stats { gap: var(--s4); }
  .mj-hand { gap: 1px; }
}

@keyframes mj-leave {
  0% { transform: translate(calc(var(--tw) * .03), calc(var(--tw) * -.07)); opacity: 1; }
  55% { transform: translate(calc(var(--dx) * var(--tw) / 2), calc(var(--dy) * var(--th) / 2)) scale(1.03); opacity: 1; }
  100% { transform: translate(calc(var(--dx) * var(--tw) / 2), calc(var(--dy) * var(--th) / 2 - var(--th) * .12)) scale(.7); opacity: 0; }
}
@keyframes mj-spark { from { transform: scale(.25); opacity: 1; } to { transform: scale(1.35); opacity: 0; } }
@keyframes mj-return { from { opacity: 0; transform: translateY(-14%) scale(1.04); } }
@keyframes mj-deal { from { opacity: 0; transform: translateY(-28%) scale(1.06); } }
@keyframes mj-flip { 0%, 100% { transform: none; } 48% { transform: scaleX(.06) translateY(-4%); } }
@keyframes mj-shake { 25% { transform: translateX(calc(var(--tw) * -.05)); } 60% { transform: translateX(calc(var(--tw) * .04)); } }
@keyframes mj-hint { 50% { opacity: .35; } }
@keyframes mj-rise { from { opacity: 0; transform: translateY(.75rem); } }
@keyframes mj-pop { from { opacity: 0; transform: translateY(.8rem) scale(.7) rotate(-6deg); } }
@keyframes mj-toss { from { opacity: 0; transform: translateY(-60%) scale(1.25) rotate(-8deg); } }
@keyframes mj-draw { from { opacity: 0; transform: translateY(-70%); } }
@keyframes mj-timer { to { stroke-dashoffset: 113.1; } }
@keyframes mj-drain { to { transform: scaleX(0); } }

@media (prefers-reduced-motion: reduce) {
  .mj-stage *, .mj-stage *::before, .mj-stage *::after { animation-duration: 1ms !important; animation-delay: 0ms !important; transition-duration: 1ms !important; }
  .mj-ring circle { animation-duration: var(--turn) !important; }
  .mj-claim-bar { animation-duration: var(--claim) !important; }
  .mj-tile.hinted::after { animation: none !important; }
}

.mj-buried-note { color: var(--ink); font-weight: 600; }
.mj-lore-toggle {
  display: inline; margin-left: var(--s1); padding: 0; border: 0; background: none; font: inherit; font-size: .85em;
  color: var(--muted); text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
/* Tile lore ticker: one line under the tools, in the caption's slot. Never over the board; tap for the tile book. */
.mj-ticker {
  --gold: #e9a83a;
  display: flex; align-items: center; gap: .5rem; width: min(100%, 32rem); min-height: 2.5rem; margin: 0 auto;
  padding: .3rem .75rem .3rem .4rem; border: 1px solid color-mix(in srgb, var(--ink) 12%, transparent); border-radius: 99px;
  background: var(--surface, #fffaf0); color: var(--ink); font: inherit; font-size: var(--text-sm); text-align: left; cursor: pointer;
  animation: mj-ticker-in 260ms cubic-bezier(.2, .9, .3, 1.2) both;
}
.mj-ticker-tiles { display: flex; gap: 2px; flex: none; padding-bottom: 3px; }
.mj-ticker .mj-mini { --t: 1.2rem; animation: none; box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--mj-jade), 0 3px 3px #0005; }
.mj-ticker-tag {
  flex: none; padding: .1rem .5rem; border-radius: 99px; font-size: .72rem; font-weight: 800; letter-spacing: .02em;
  background: color-mix(in srgb, var(--mj-jade) 16%, transparent); color: var(--mj-jade-lo);
}
.mj-ticker.is-set .mj-ticker-tag {
  background: linear-gradient(100deg, #ffe9a8, var(--gold) 45%, #ffe9a8 55%, var(--gold)); background-size: 220% 100%;
  color: #4a2c00; animation: mj-ticker-shine 1.4s ease-out 1 both;
}
.mj-ticker.is-set { border-color: color-mix(in srgb, var(--gold) 60%, transparent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 14%, transparent); }
.mj-ticker.is-new { border-color: color-mix(in srgb, var(--mj-jade) 45%, transparent); }
.mj-ticker-text { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: 600; }
.mj-ticker-han { margin-left: .35rem; font-family: "Noto Serif TC", "Songti TC", "PMingLiU", serif; font-weight: 700; color: #b8322a; }
.mj-ticker-more { flex: none; font-size: .75rem; font-weight: 800; color: var(--muted); }
@keyframes mj-ticker-in { from { opacity: 0; transform: translateY(4px) scale(.98); } }
@keyframes mj-ticker-shine { from { background-position: 100% 0; transform: scale(.85); } 40% { transform: scale(1.08); } to { background-position: 0 0; transform: none; } }
@media (prefers-reduced-motion: reduce) { .mj-ticker, .mj-ticker.is-set .mj-ticker-tag { animation: none; } }

/* Tile book: the page and the in-game sheet. */
.mj-lore-han { display: flex; align-items: baseline; gap: .45rem; margin: 0; }
.mj-lore-han span { font-family: "Noto Serif TC", "Songti TC", "PMingLiU", serif; font-size: 1.25rem; font-weight: 700; color: #b8322a; }
.mj-lore-han i { font-size: .85rem; color: var(--muted); }
.mj-book { display: grid; gap: var(--s2); }
.mj-book p { margin: 0; }
.mj-book-detail {
  display: flex; align-items: center; gap: var(--s3); min-height: 6.5rem; padding: var(--s3); border-radius: var(--radius);
  background: linear-gradient(160deg, #183f44, #0a2226); color: #f4eedd;
}
.mj-book-detail .mj-lore-han span { color: #ffb3a1; }
.mj-book-detail .mj-lore-han i { color: #cfe3dc; }
.mj-book-big { --t: 3rem; flex: none; }
.mj-book-set-tiles { display: flex; gap: 3px; flex: none; }
.mj-book-set-tiles .mj-mini { --t: 1.6rem; }
.mj-book-title { font-weight: 800; font-size: 1.05rem; }
.mj-book-about { font-size: var(--text-sm); color: #d4e4de; }
.mj-book-hint { font-size: .75rem; color: #9fd8c7; margin-top: .2rem !important; }
.mj-book-count { font-size: var(--text-sm); color: var(--muted); }
.mj-book-group { margin-top: var(--s1) !important; }
.mj-book-row { display: grid; grid-template-columns: repeat(9, minmax(0, 1fr)); gap: 4px; }
.mj-book-tile {
  aspect-ratio: 60 / 80; padding: 6% 8%; border: 0; border-radius: 12%; cursor: pointer;
  background: linear-gradient(155deg, var(--mj-ivory-hi), var(--mj-ivory) 55%, var(--mj-ivory-lo));
  box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--mj-side-lo), 0 3px 0 var(--mj-jade), 0 4px 5px #0004;
  filter: grayscale(1) opacity(.35);
}
.mj-book-tile svg { width: 100%; height: 100%; display: block; }
.mj-book-tile.learned { filter: none; }
.mj-book-tile.picked { outline: 2px solid var(--mj-jade); outline-offset: 2px; }
.mj-book-sets { display: flex; flex-wrap: wrap; gap: var(--s1); }
.mj-book-set {
  padding: .35rem .7rem; border: 1px solid color-mix(in srgb, var(--ink) 15%, transparent); border-radius: 99px;
  background: none; color: var(--muted); font: inherit; font-size: var(--text-sm); cursor: pointer;
}
.mj-book-set span { font-family: "Noto Serif TC", "Songti TC", serif; font-weight: 700; }
.mj-book-set.learned { color: var(--ink); border-color: #e9a83a; background: color-mix(in srgb, #e9a83a 12%, transparent); }
.mj-book-set.picked { outline: 2px solid var(--mj-jade); outline-offset: 1px; }
.mj-book-sheet {
  position: fixed; inset: 0; z-index: 2000; display: grid; align-items: end; justify-items: center;
  background: #0007; cursor: pointer; animation: mj-sheet-fade 180ms ease-out both;
}
.mj-book-sheet-card {
  display: grid; gap: var(--s2); width: min(100%, 34rem); max-height: 88dvh; overflow: auto; overscroll-behavior: contain;
  padding: var(--s3) var(--s3) calc(var(--s3) + env(safe-area-inset-bottom)); border-radius: 1.25rem 1.25rem 0 0;
  background: var(--surface); color: var(--ink); box-shadow: 0 -12px 32px #0005; cursor: auto; animation: mj-sheet-up 260ms cubic-bezier(.2, .9, .3, 1) both;
}
.mj-book-sheet-card .eyebrow { margin: 0; }
.mj-book-sheet-card:focus { outline: none; }
/* The way back stays in reach on a long scroll. */
.mj-book-sheet-head { position: sticky; top: calc(-1 * var(--s3)); z-index: 1; margin: calc(-1 * var(--s3)) calc(-1 * var(--s3)) 0; padding: var(--s3); background: var(--surface); }
.mj-book-toggle { margin-top: var(--s1); font-size: var(--text-sm); color: var(--ink); }
@keyframes mj-sheet-fade { from { opacity: 0; } }
@keyframes mj-sheet-up { from { transform: translateY(100%); } }
@media (prefers-reduced-motion: reduce) { .mj-book-sheet, .mj-book-sheet-card { animation: none; } }

/* How to play: the matching red dragons glow and leave; the other tiles stay. */
.coach-mj { display: flex; justify-content: center; gap: 2px; padding: var(--s2) 0 var(--s3); }
.coach-mj .mj-mini { --t: 2.6rem; animation: none; }
.coach-mj .coach-mj-pair { animation: coach-mj-pair 4s ease-in-out infinite; }
@keyframes coach-mj-pair {
  0%, 15% { transform: none; opacity: 1; outline: 0 solid transparent; }
  25%, 45% { transform: translateY(-4px); opacity: 1; outline: 3px solid var(--mj-jade, #2f8f6f); outline-offset: 2px; }
  60%, 85% { transform: translateY(-14px) scale(.9); opacity: 0; }
  100% { transform: none; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .coach-mj .coach-mj-pair { animation: none; outline: 3px solid var(--mj-jade, #2f8f6f); outline-offset: 2px; } }
