  [hidden]{ display:none !important; }
  /* Tile lettering fonts ship with the game (public/fonts): each file holds
     only the ~40 characters tiles actually use, so it's tiny and every
     player sees identical lettering, online or off. Yuji Syuku is the brush
     calligraphy; LXGW WenKai TC (a Kai brush face) covers the two
     characters Syuku lacks (貓, 雞) so they still read as brushwork. */
  @font-face{ font-family:"TileBrush"; src:url(/fonts/tile-syuku-400.woff2) format("woff2"); font-weight:400; font-display:block; }
  @font-face{ font-family:"TileBrushKai"; src:url(/fonts/tile-kai-700.woff2) format("woff2"); font-weight:400; font-display:block; }
  :root{
    --bg:#efe7d6; --surface:#fbf6ea; --surface-2:#f2ead9;
    --ink:#241d15; --ink-soft:#5b5041;
    --felt:#12392c; --felt-2:#0c281f; --rail:#a9784a;
    --ivory:#f6efdd; --ivory-edge:#cbb98e;
    /* A physical tile is ivory-colored ink and wood regardless of whether
       the app around it is in light or dark mode — unlike --ink/--ivory-edge
       above (which deliberately flip for the app's own UI), these never get
       redefined in the dark-mode blocks below, so tile glyphs and edges stay
       legible instead of the app's dark-mode text color (near-white)
       rendering almost invisible on the tile's always-light ivory face. */
    --tile-ink: #241d15; --tile-edge: #cbb98e;
    /* A real tile is two bonded layers: an ivory face and a coloured back.
       These are the physical materials, so like --tile-ink they never flip
       with the app theme. */
    --tile-back: #9e3027; --tile-back-hi: #bd4a3e; --tile-back-lo: #5e1712;
    --tile-ivory-side: #ddd1b3; --tile-ivory-shade: #c6b893;
    --lacquer:#b3282c; --lacquer-2:#8f1f22;
    --gold:#c9a24a; --jade:#127f8a;
    --line: rgba(36,29,21,0.14);
    --shadow: 0 8px 24px rgba(18,57,44,0.18);
    --gold-ink:#5a4319;
    color-scheme: light dark;
  }
  @media (prefers-color-scheme: dark){
    :root:not([data-theme="light"]){
      --bg:#0c1310; --surface:#141f19; --surface-2:#182922;
      --ink:#ede6d6; --ink-soft:#b9ad98;
      --felt:#0d2b21; --felt-2:#081c16; --rail:#7a5433;
      --ivory:#efe6d0; --ivory-edge:#000000;
      --lacquer:#d9484c; --lacquer-2:#b3282c;
      --gold:#d8b562; --jade:#3fc2cf;
      --line: rgba(237,230,214,0.14);
      --shadow: 0 8px 26px rgba(0,0,0,0.45);
      --gold-ink:#f0d68a;
    }
  }
  :root[data-theme="dark"]{
    --bg:#0c1310; --surface:#141f19; --surface-2:#182922;
    --ink:#ede6d6; --ink-soft:#b9ad98;
    --felt:#0d2b21; --felt-2:#081c16; --rail:#7a5433;
    --ivory:#efe6d0; --ivory-edge:#000000;
    --lacquer:#d9484c; --lacquer-2:#b3282c;
    --gold:#d8b562; --jade:#3fc2cf;
    --line: rgba(237,230,214,0.14);
    --shadow: 0 8px 26px rgba(0,0,0,0.45);
    --gold-ink:#f0d68a;
  }

  *{box-sizing:border-box;}
  html, body{ height:100%; }
  body{
    background: var(--bg);
    color: var(--ink);
    font-family: "Manrope", ui-sans-serif, system-ui, sans-serif;
    margin:0; padding:0;
    height: calc(100dvh / var(--zoom, 1));
    overflow: hidden;
  }
  h1,h2,h3, .display{
    font-family: "Fraunces", Georgia, serif;
    text-wrap: balance;
    font-weight: 600;
    margin: 0;
  }
  .tabular{ font-variant-numeric: tabular-nums; }
  button{ font-family: inherit; }
  #app{ max-width:none; margin:0; height: calc(100dvh / var(--zoom, 1)); display:flex; flex-direction:column; gap:0; }

  /* ---------- top bar (a thin edge-to-edge strip now, not a floating card) ---------- */
  .topbar{
    display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;
    background: var(--surface); border:none; border-bottom:1px solid var(--line); border-radius:0;
    padding: 7px 14px; padding-top: calc(7px + env(safe-area-inset-top,0px)); box-shadow:none;
    flex: 0 0 auto;
  }
  .topbar .title{ display:flex; align-items:baseline; gap:8px; }
  .topbar .title h1{ font-size: 1.25rem; }
  .topbar .title span.sub{ color:var(--ink-soft); font-size:.78rem; }
  .chips{ display:flex; gap:6px; flex-wrap:wrap; }
  .chip{
    display:inline-flex; align-items:center; gap:5px;
    background: var(--surface-2); border:1px solid var(--line); color: var(--ink-soft);
    border-radius:999px; padding: 4px 10px; font-size:.74rem; font-weight:700; letter-spacing:.02em;
  }
  .chip.gold{ color: var(--gold-ink); background: color-mix(in srgb, var(--gold) 28%, var(--surface-2)); border-color: color-mix(in srgb, var(--gold) 55%, transparent); }
  .icon-btn{
    border:1px solid var(--line); background: var(--surface-2); color:var(--ink);
    border-radius:10px; padding:7px 11px; font-size:.8rem; font-weight:700; cursor:pointer;
  }
  .icon-btn:hover{ border-color: var(--gold); }
  .icon-btn:focus-visible, button:focus-visible, input:focus-visible{ outline: 2px solid var(--lacquer); outline-offset:2px; }

  #stage{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; overflow:hidden; }

  /* ---------- lobby ---------- */
  .card{ background: var(--surface); border:1px solid var(--line); border-radius:16px; padding:18px; box-shadow: var(--shadow); }
  #lobbyScreen{ margin:14px; overflow-y:auto; }
  .lobby-hero{ display:flex; flex-direction:column; gap:6px; }
  .lobby-hero h2{ font-size: 1.5rem; }
  .lobby-hero p{ color: var(--ink-soft); max-width: 62ch; line-height:1.55; margin:0; }
  .seat-grid{ display:grid; grid-template-columns: repeat(auto-fit,minmax(180px,1fr)); gap:12px; margin-top:14px; }
  .seat-card{
    border:1px solid var(--line); border-radius:14px; padding:14px; background: var(--surface-2);
    display:flex; flex-direction:column; gap:8px; align-items:flex-start;
  }
  .seat-card .avatar{
    width:38px; height:38px; border-radius:50%; display:flex; align-items:center; justify-content:center;
    font-weight:800; color:#fff; font-size:.95rem; flex-shrink:0;
  }
  .seat-card .name{ font-weight:700; }
  .seat-card .role{ font-size:.72rem; color:var(--ink-soft); text-transform:uppercase; letter-spacing:.06em; }
  .seat-card button{
    margin-top:4px; width:100%; border:none; border-radius:10px; padding:9px 10px; font-weight:700; cursor:pointer;
    background: var(--lacquer); color:#fff;
  }
  .seat-card button:disabled{ background: var(--surface-2); color: var(--ink-soft); border:1px solid var(--line); cursor:default; }
  .ruleset-row{ display:flex; gap:18px; flex-wrap:wrap; margin-top:14px; }
  .rs-group{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
  .rs-label{ font-size:.72rem; color: var(--ink-soft); text-transform:uppercase; letter-spacing:.05em; margin-right:2px; }
  .rs-btn{
    border:1px solid var(--line); background: var(--surface-2); color: var(--ink-soft);
    border-radius:999px; padding:6px 13px; font-size:.8rem; font-weight:700; cursor:pointer;
  }
  .rs-btn.active{ background: var(--lacquer); color:#fff; border-color: var(--lacquer); }
  .name-row{ display:flex; gap:8px; margin-top:14px; flex-wrap:wrap; }
  .name-row input{
    flex:1; min-width:160px; padding:10px 12px; border-radius:10px; border:1px solid var(--line);
    background: var(--surface-2); color: var(--ink); font-size:.9rem;
  }
  .start-row{ margin-top:14px; display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
  .btn-primary{
    background: var(--lacquer); color:#fff; border:none; border-radius:11px; padding:11px 18px;
    font-weight:800; cursor:pointer; letter-spacing:.01em;
  }
  .btn-primary:disabled{ background: var(--surface-2); color:var(--ink-soft); cursor:default; }
  .btn-secondary{
    background: var(--surface-2); color:var(--ink); border:1px solid var(--line); border-radius:11px; padding:10px 16px;
    font-weight:700; cursor:pointer;
  }
  .hint{ font-size:.78rem; color: var(--ink-soft); }
  .solo-toggle-row{ margin-top:16px; padding-top:12px; border-top:1px dashed var(--line); display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
  .solo-check{ font-size:.82rem; color: var(--ink-soft); display:flex; align-items:center; gap:7px; cursor:pointer; }
  .solo-check input{ width:16px; height:16px; accent-color: var(--lacquer); cursor:pointer; }
  .solo-bar{
    display:flex; align-items:center; gap:8px; flex-wrap:wrap; background: color-mix(in srgb, var(--gold) 16%, var(--surface));
    border:1px solid color-mix(in srgb, var(--gold) 45%, var(--line)); border-left:none; border-right:none; border-radius:0; padding:7px 14px; margin-bottom:0;
    font-size:.8rem; color: var(--ink-soft); flex: 0 0 auto;
  }
  .solo-bar b{ color: var(--ink); }
  .solo-seat-btn{
    border:1px solid var(--line); background: var(--surface-2); color: var(--ink);
    border-radius:999px; padding:5px 12px; font-size:.78rem; font-weight:700; cursor:pointer;
  }
  .solo-seat-btn.active{ background: var(--lacquer); color:#fff; border-color: var(--lacquer); }

  /* ---------- lobby: ready / host / balance / leave ---------- */
  .seat-card .tagrow{ display:flex; gap:5px; flex-wrap:wrap; }
  .tag-host{ font-size:.64rem; font-weight:800; padding:2px 7px; border-radius:6px; background: color-mix(in srgb, var(--gold) 30%, var(--surface-2)); color:#5a4319; }
  .tag-balance{ font-size:.64rem; font-weight:800; padding:2px 7px; border-radius:6px; background: var(--surface-2); color: var(--ink-soft); border:1px solid var(--line); }
  .ready-btn{ margin-top:2px; width:100%; border:none; border-radius:10px; padding:8px 10px; font-weight:800; cursor:pointer; font-size:.82rem; }
  .ready-btn.ready{ background: var(--jade); color:#fff; }
  .ready-btn.pending{ background: color-mix(in srgb, var(--gold) 35%, var(--surface-2)); color:#5a4319; }
  .seat-actions{ display:flex; gap:6px; width:100%; }
  .seat-actions button{ flex:1; margin-top:0; }
  .btn-leave{ background: var(--surface-2) !important; color: var(--lacquer) !important; border:1px solid var(--line) !important; font-size:.78rem !important; padding:8px 8px !important; }
  .btn-kick{ background: var(--surface-2) !important; color: var(--ink-soft) !important; border:1px solid var(--line) !important; font-size:.72rem !important; padding:8px 8px !important; }
  .room-actions-row{ display:flex; justify-content:flex-end; margin-top:8px; }
  .btn-close-room{ background:none; border:1px solid var(--lacquer); color: var(--lacquer); border-radius:10px; padding:7px 12px; font-size:.78rem; font-weight:700; cursor:pointer; }

  /* ---------- table: full-bleed, no wooden picture-frame border any more ---------- */
  .table-wrap{
    background: none; border-radius:0; padding:0; box-shadow:none;
    flex: 1 1 auto; min-height:0; display:flex; overflow:hidden;
  }
  .felt{
    background:
      repeating-linear-gradient(45deg, rgba(255,255,255,.018) 0px, rgba(255,255,255,.018) 1px, transparent 1px, transparent 7px),
      radial-gradient(140% 100% at 50% 30%, color-mix(in srgb, var(--felt) 88%, white) 0%, var(--felt) 45%, var(--felt-2) 100%);
    border-radius: 0; padding: 10px;
    border: none;
    flex: 1 1 auto; min-height:0;
  }
  /* ---------- landscape table: opponent rails either side, wheel in the middle ---------- */
  .felt-landscape{
    display:grid;
    grid-template-columns: minmax(80px,140px) 1fr minmax(80px,140px);
    align-items:stretch; gap:10px; min-height:0; height:100%;
  }
  @media (max-width:560px){
    .felt-landscape{ grid-template-columns: 64px 1fr 64px; gap:6px; }
  }
  .seat-rail{
    display:flex; flex-direction:column; align-items:center; gap:6px;
    background: rgba(255,255,255,0.06); border:1px solid rgba(255,255,255,0.14); border-radius:14px;
    border-top: 3px solid color-mix(in srgb, var(--rail) 88%, black);
    padding:10px 6px; color:#f3ecd9; position:relative; overflow-y:auto; overflow-x:hidden;
    box-shadow: inset 0 3px 6px -3px rgba(0,0,0,.45);
    /* A grid item's default min-width is its content's min-content size, which
       for a long nowrap display name can blow straight past the column's
       minmax(80px,140px) cap and push the whole rail (and everything painted
       on it, like the flower-count badge) off to one side. Letting it shrink
       to 0 is what actually lets that cap — and the name's own ellipsis —
       take effect. */
    min-width:0;
  }
  .seat-rail.active{ border-color: var(--gold); box-shadow: 0 0 0 2px color-mix(in srgb, var(--gold) 55%, transparent), inset 0 0 24px rgba(201,162,74,.12); }
  .seat-rail .avatar{ width:30px; height:30px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-weight:800; color:#1c1208; font-size:.8rem; flex-shrink:0; }
  .seat-rail .nm{ font-weight:700; font-size:.76rem; text-align:center; line-height:1.2; width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* A little wooden name-plate sitting on the table in front of each seat —
     the avatar rides on top like a medallion, the name is carved into the
     wood (a dark engraved-looking text-shadow) rather than a flat text chip. */
  .name-plate{
    display:flex; flex-direction:column; align-items:center; gap:4px; width:100%;
    padding:7px 6px 6px; border-radius:10px;
    background: linear-gradient(160deg, color-mix(in srgb, var(--rail) 88%, white 10%), var(--rail) 55%, color-mix(in srgb, var(--rail) 70%, black));
    border:1px solid color-mix(in srgb, var(--rail) 45%, black);
    box-shadow: 0 3px 0 color-mix(in srgb, var(--rail) 45%, black), inset 0 1px 0 rgba(255,255,255,.35), 0 5px 9px rgba(0,0,0,.35);
  }
  .name-plate .avatar{ box-shadow: 0 0 0 2px var(--gold), 0 2px 5px rgba(0,0,0,.45); }
  .name-plate .nm{ color:#fff8ea; text-shadow: 0 1px 0 rgba(0,0,0,.5), 0 -1px 0 rgba(0,0,0,.25); }
  .name-plate.name-plate-h{
    flex-direction:row; width:auto; padding:5px 12px 5px 5px; gap:8px;
  }
  .name-plate.name-plate-h .nm{ font-size:.92rem; }
  .seat-rail .meta{ font-size:.62rem; opacity:.75; }
  .seat-rail .meta.fan-total{
    font-size:.68rem; font-weight:800; opacity:1; color:#3a2a08; background: var(--gold);
    border-radius:999px; padding:2px 8px;
  }
  .fan-chip{ color: var(--gold-ink); background: color-mix(in srgb, var(--gold) 28%, var(--surface-2)); border-color: color-mix(in srgb, var(--gold) 55%, transparent); }
  .badge-dealer{
    font-size:.62rem; font-weight:800; background: var(--gold); color:#3a2a08;
    border-radius:999px; padding:2px 7px;
  }
  .tilebacks{ display:flex; gap:2px; flex-wrap:wrap; justify-content:center; padding:3px 0; perspective:240px; }
  /* Same real-side treatment as .tile (see its comment) — margin-bottom
     reserves flow space, the ::after is the actual extruded thickness face,
     so an opponent's hidden hand reads as a row of real standing blocks
     instead of flat teal chips. */
  .tileback{
    --tside: 5px;
    width:15px; height:20px; border-radius:3px; flex-shrink:0; margin-bottom:var(--tside);
    background: linear-gradient(160deg, var(--jade), color-mix(in srgb, var(--jade) 60%, black));
    border: 1px solid rgba(255,255,255,.25);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 rgba(0,0,0,.2);
    position:relative;
  }
  .tileback::after{
    content:""; position:absolute; left:1px; right:1px; top:100%; height:var(--tside);
    background: linear-gradient(180deg, color-mix(in srgb, var(--jade) 55%, black), color-mix(in srgb, var(--jade) 20%, black));
    border-radius: 0 0 2px 2px;
    box-shadow: 0 2px 3px rgba(0,0,0,.35);
    pointer-events:none;
  }
  /* Opponents' tiles stand in a rack "facing" that player — tilted toward
     the middle of the table in 3D, mirrored per side, instead of sitting
     flat like stickers. Their flowers (already face-up, real tiles) get the
     same lean so the whole rack reads as one physical object. */
  .side-left .tilebacks, .side-left .bonus-rack{ perspective:240px; }
  .side-right .tilebacks, .side-right .bonus-rack{ perspective:240px; }
  .side-left .tileback, .side-left .bonus-rack .tile{ transform: rotateY(20deg); transform-origin:right center; }
  .side-right .tileback, .side-right .bonus-rack .tile{ transform: rotateY(-20deg); transform-origin:left center; }
  .mini-melds{ display:flex; gap:4px; flex-wrap:wrap; justify-content:center; }
  .mini-meld{ display:flex; gap:1px; }
  .mini-discards{ display:flex; flex-wrap:wrap; gap:2px; justify-content:center; margin-top:auto; padding-top:6px; }
  .void-badge{
    font-size:.6rem; font-weight:800; padding:2px 6px; border-radius:6px; display:inline-block;
    background: rgba(179,40,44,.28); color:#ffd9d9; border:1px solid rgba(179,40,44,.5);
  }

  /* ---------- center hub: wind wheel, last-tile callout, turn banner ---------- */
  .center-hub{
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px;
    padding: 8px 4px; color:#f3ecd9; position:relative;
  }
  .hub-row{ display:flex; align-items:center; justify-content:center; gap:18px; flex-wrap:wrap; }
  .wind-wheel{
    width:96px; height:96px; border-radius:50%; flex-shrink:0; position:relative;
    background: radial-gradient(circle at 50% 38%, color-mix(in srgb, var(--gold) 30%, var(--felt)) 0%, var(--felt-2) 72%);
    border:3px solid var(--gold);
    box-shadow: 0 0 18px rgba(201,162,74,.35), inset 0 0 14px rgba(0,0,0,.45);
  }
  .wind-wheel .wedge{
    position:absolute; font-size:.68rem; font-weight:800; color:rgba(243,236,217,.55);
    width:20px; text-align:center; line-height:1;
  }
  .wind-wheel .wedge.n{ top:6px; left:50%; transform:translateX(-50%); }
  .wind-wheel .wedge.s{ bottom:6px; left:50%; transform:translateX(-50%); }
  .wind-wheel .wedge.e{ right:5px; top:50%; transform:translateY(-50%); }
  .wind-wheel .wedge.w{ left:5px; top:50%; transform:translateY(-50%); }
  .wind-wheel .wedge.active{ color: var(--gold); font-size:.86rem; text-shadow:0 0 8px rgba(201,162,74,.85); }
  .wind-wheel .wedge.is-dealer::after{
    content:"莊"; position:absolute; top:-13px; left:50%; transform:translateX(-50%);
    font-size:.5rem; font-weight:800; color:#3a2a08; background: var(--gold); border-radius:999px; padding:1px 4px;
  }
  .wind-wheel .wedge.w.is-dealer::after, .wind-wheel .wedge.e.is-dealer::after{ top:50%; transform:translateY(-26px); }
  .wind-wheel .wheel-core{
    position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px;
  }
  .wind-wheel .wheel-core .rd{ font-family:"Fraunces",serif; font-size:1.35rem; color:#fff; line-height:1; }
  .wind-wheel .wheel-core .wl{ font-size:.6rem; color:rgba(243,236,217,.7); }
  .last-tile-card{ display:flex; flex-direction:column; align-items:center; gap:4px; min-width:60px; }
  .last-tile-card .lbl{ font-size:.62rem; color:rgba(243,236,217,.65); text-transform:uppercase; letter-spacing:.06em; }
  .wall-pill{
    display:flex; align-items:center; gap:8px; background: rgba(0,0,0,.22); border:1px solid rgba(255,255,255,.15);
    border-radius:999px; padding:5px 12px; font-size:.76rem; font-weight:700;
  }
  .turn-banner{ font-family:"Fraunces",serif; font-size:1rem; text-align:center; }
  .turn-banner b{ color: var(--gold); }

  /* ---------- tiles: a real bevelled 3D block, not a flat sticker ---------- */
  /* A real bevelled 3D block: a soft gloss band across the top (painted as
     a background layer so it never covers the glyph on top of it), a
     rounded ivory body, and — below it — an actual extruded side face (the
     ::after pseudo-element right after this rule), not just shadows faking
     one. `margin-bottom: var(--tside)` reserves real flow space for that
     face so it never overlaps the tile row below it when a rack wraps, and
     since it's pure CSS on the existing .tile element (no markup change),
     every tile everywhere — hand, melds, discards, bonus racks, wall/rack
     sizes, all of it — gets the same real side automatically. */
  .tile{
    --tw: 42px; --th: 57px; --tile-radius: 6px;
    --tside: calc(var(--th) * 0.24);
    width: var(--tw); height: var(--th); margin-bottom: var(--tside);
    /* Matte porcelain, not glossy plastic: one soft, wide highlight from the
       overhead light and an almost-flat ivory body. */
    background:
      radial-gradient(130% 75% at 50% 0%, rgba(255,255,255,.5), rgba(255,255,255,0) 62%),
      linear-gradient(180deg, #f8f2e3, #eee4cc);
    border-radius: var(--tile-radius) var(--tile-radius) calc(var(--tile-radius) * .35) calc(var(--tile-radius) * .35);
    border: 1px solid var(--tile-edge);
    box-shadow:
      inset 0 2px 0 rgba(255,255,255,.7),
      inset 2px 0 3px -1px rgba(255,255,255,.4),
      inset 0 -3px 3px rgba(0,0,0,.14),
      0 2px 2px rgba(0,0,0,.2);
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    color: var(--tile-ink); font-weight:800; user-select:none; flex-shrink:0; position:relative;
    font-size: 1.25rem; line-height:1;
  }
  /* The tile's actual thickness, standing below its face — same idea as the
     wall bricks' .f-front: a face you're looking at straight-on needs no
     rotateX/perspective at all (only a face you're looking down onto, like
     the wall bricks' .f-top, needs that tilt to foreshorten correctly); a
     plain darker vertical-gradient rectangle already reads as a real edge.
     Uses fixed colors (--tile-edge), not the app's dark-mode-flipping ones —
     a physical tile's edge doesn't change color when the app theme does.
     Slightly narrower than the face so the face's own rounded corners and
     border still read as the block's top edge, and a bright top seam sells
     the fold where the ivory face actually ends and the edge begins. */
  /* The side is the tile's actual construction, not a shaded smear: the
     ivory face layer on top, a hairline where the layers are bonded, then
     the teal back layer — flat bands like the real object, with one soft
     occlusion at the very bottom where it meets the table. */
  .tile::after{
    content:""; position:absolute; left:-1px; right:-1px; top:100%; height:var(--tside);
    background:
      linear-gradient(180deg, transparent 72%, rgba(0,0,0,.28) 100%),
      linear-gradient(180deg,
        var(--tile-ivory-side) 0 50%,
        rgba(0,0,0,.35) 50% calc(50% + 1px),
        var(--tile-back) calc(50% + 1px) 100%);
    border-radius: 0 0 calc(var(--tile-radius) - 1px) calc(var(--tile-radius) - 1px);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.55), 0 3px 4px rgba(0,0,0,.4);
    pointer-events: none;
  }
  /* Real tiles carry two very different kinds of type: a Western numeral
     carved boldly into the ivory, and a brush-drawn Chinese character below
     or in place of it. A UI sans-serif (the page's own body font) reads as
     flat plastic for both, so tiles get their own pairing instead — a
     serif display face for the numeral and an actual serif CJK face
     ("Noto Serif SC", loaded in index.html) for every character glyph:
     the small suit character, wind/dragon tiles, and flower/season names —
     plus a soft engraved-looking text-shadow so the glyph reads as pressed
     into the tile rather than printed flat on top of it. */
  .tile .suitnum{
    font-family: "Fraunces", Georgia, serif; font-weight:700; font-size:1.05em;
    text-shadow: 0 1px 0 rgba(255,255,255,.5), 0 -1px 0 rgba(0,0,0,.12);
  }
  .tile .suitglyph, .tile .honorglyph, .tile .bonus-label, .tile .seat-num{
    font-family: "TileBrush", "TileBrushKai", serif; font-synthesis: none;
    text-shadow: 0 1px 0 rgba(255,255,255,.45), 0 -1px 0 rgba(0,0,0,.1);
  }
  .tile .suitglyph{ font-size:.72rem; font-weight:700; margin-top:1px; opacity:.8; }
  .tile.m .suitnum{ color:#7a1f22; }
  .tile.m .suitglyph{ color:#7a1f22; }
  .tile.p .suitglyph{ color:#1f5a7a; }
  .tile.s .suitglyph{ color:#2f6b3f; }
  /* Wind/dragon glyphs are the tile's whole face — always the fixed
     --tile-ink color (never --ink, which flips to near-white in dark mode
     and made these unreadable), sized up so a single brush character
     actually fills an ivory tile the way it does on a real one. */
  .tile.wind .honorglyph{ font-size:1.85em; font-weight:400; color:#141414; }
  .tile.dragon .honorglyph{ font-size:1.85em; font-weight:400; }
  .tile.dragon .honorglyph.zd{ color:#c3261a; }
  .tile.dragon .honorglyph.fd{ color:#1c6a3a; }
  .tile.dragon .dragon-blank{ width:64%; height:56%; margin:0 auto; border:2px solid #2f5a8a; border-radius:3px; }
  /* Suit-pip and bonus-tile artwork is an <svg> with no fixed pixel size of
     its own (see circleSuitSVG/bambooSuitSVG/bonusIconSVG in client.js) —
     sizing it here in em units means it scales automatically off the tile's
     own font-size, which already varies per size class (.tiny/.small/.xl
     and their @media overrides), instead of being pasted in at one fixed
     pixel size that only looked right on the default tile. */
  .tile .suit-svg{ width:1.7em; height:2.2em; display:block; }
  .tile .bonus-svg{ width:1.95em; height:1.95em; display:block; overflow:visible; }
  .tile.flower, .tile.season, .tile.animal, .tile.joker, .tile.fei, .tile.head{ gap:0; }
  .tile .bonus-caption{ display:flex; flex-direction:column; align-items:center; line-height:1.05; margin-top:1px; }
  .tile .bonus-label{ font-size:.62em; font-weight:400; letter-spacing:0; color:#141414; }
  .tile .bonus-en{
    font-family: "Manrope", sans-serif; font-size:.34rem; font-weight:700; text-transform:uppercase;
    letter-spacing:.03em; color: color-mix(in srgb, var(--tile-ink) 70%, transparent); margin-top:1px;
  }
  /* At tiny/small sizes (win-tile recaps, meld strips, the flower rack)
     there isn't room for a three-line stack — the icon plus the Chinese
     glyph still identify the tile on their own; the English caption is a
     legibility aid for the sizes a player actually studies a bonus tile at
     (their own hand/tray at default or xl size). */
  .tile.tiny .bonus-en, .tile.small .bonus-en{ display:none; }
  .tile.tiny .bonus-svg{ width:1.4em; height:1.4em; }
  .tile.tiny .bonus-label{ font-size:.62em; margin-top:0; }
  .tile.small .bonus-svg{ width:1.7em; height:1.7em; }
  .bonus-rack{ display:flex; gap:4px; flex-wrap:wrap; justify-content:center; }
  /* Flowers/seasons/animals/jokers are always exposed, face-up on the table
     next to the wall they came from — never buried in a cramped strip. */
  .bonus-tray{
    margin-top:6px; padding:6px 7px 5px; border-radius:10px; width:100%;
    background: linear-gradient(180deg, rgba(0,0,0,.22), rgba(0,0,0,.12));
    border:1px solid rgba(201,162,74,.4); box-shadow: inset 0 1px 0 rgba(255,255,255,.06);
    display:flex; flex-direction:column; align-items:center; gap:4px;
  }
  .bonus-tray .tray-label{
    font-size:.58rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
    color: rgba(243,236,217,.7);
  }
  .my-bonus-tray{ max-width:340px; margin:0 auto 4px; }
  /* A little wood-framed rack for the fan/flower display — same wood tone as
     the name plates (--rail) instead of the plain dark-gold tray, with a
     small round count badge riding on its corner like the numbered chips
     under each player's tiles in the reference layout. */
  .bonus-tray.wood-rack{
    position:relative;
    background: linear-gradient(165deg, color-mix(in srgb, var(--rail) 82%, white 8%), color-mix(in srgb, var(--rail) 78%, black 10%));
    border:1px solid color-mix(in srgb, var(--rail) 45%, black);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 3px 7px rgba(0,0,0,.3);
  }
  .wood-rack .tray-label{ color:#fff6e2; text-shadow: 0 1px 0 rgba(0,0,0,.4); }
  .rack-count{
    position:absolute; top:-7px; right:-7px; min-width:18px; height:18px; padding:0 4px;
    border-radius:999px; display:flex; align-items:center; justify-content:center;
    font-size:.62rem; font-weight:800; color:#3a2a08;
    background: radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--gold) 60%, white), var(--gold));
    border:1px solid color-mix(in srgb, var(--gold) 60%, black);
    box-shadow: 0 2px 3px rgba(0,0,0,.4);
  }
  /* Every discard, laid out on the table — a stone-grey tray (as opposed to
     the gold-accented bonus tray) so the two read as different kinds of
     "face-up on the table" piles at a glance. */
  .discard-tray{
    margin-top:6px; padding:6px 7px 5px; border-radius:10px; width:100%;
    background: linear-gradient(180deg, rgba(0,0,0,.18), rgba(0,0,0,.08));
    border:1px solid rgba(255,255,255,.16); box-shadow: inset 0 1px 0 rgba(255,255,255,.05);
    display:flex; flex-direction:column; align-items:center; gap:4px;
  }
  .discard-tray .tray-label{
    font-size:.58rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
    color: rgba(243,236,217,.55);
  }
  .discard-rack{ display:flex; gap:3px; flex-wrap:wrap; justify-content:center; }
  .my-plate .discard-tray{ max-width:340px; margin-top:8px; }
  .wind-chip{ font-size:.66rem; font-weight:800; padding:2px 7px; border-radius:6px; margin-top:6px; display:inline-block;
    background: rgba(201,162,74,.25); color:#f3e2b0; border:1px solid rgba(201,162,74,.5); }
  .tile.small{ --tw:26px; --th:35px; font-size:.76rem; }
  .tile.tiny{ --tw:18px; --th:24px; font-size:.56rem; --tile-radius:3px; }
  .tile.xl{ --tw:56px; --th:76px; font-size:1.5rem; --tile-radius:7px; }
  .tile.selectable{ cursor:pointer; transition: transform .12s ease; }
  .tile.selectable:hover{ transform: translateY(-6px); }
  /* Not your turn: tiles stay crisp and full-colour, just not clickable. */
  .tile.disabled{ cursor:default; }
  .tile.highlight{ box-shadow: 0 0 0 2px var(--lacquer), 0 2px 0 rgba(0,0,0,.25); }
  /* A discard someone claimed (ponged/konged/chi'd/won) stays right where it
     was thrown, just greyed out — the table keeps an honest full history
     instead of the tile quietly vanishing. */
  .tile.claimed{ filter: grayscale(1) brightness(.68); box-shadow: 0 4px 8px rgba(0,0,0,.3); }
  /* The tile you just drew, glowing in your own hand — this is the ONLY
     place a fresh draw is ever shown; nobody else's screen reveals it (see
     renderTable() in client.js), so this is how you notice your new tile
     the way you would picking it up off a real wall. Fades in and settles
     into a slow pulse so it stays noticeable without being distracting,
     and disappears the moment you act (lastDraw clears server-side then). */
  .tile.just-drawn{
    animation: justDrawnPop .32s cubic-bezier(.22,.85,.3,1) both, justDrawnPulse 1.6s ease-in-out .32s infinite;
  }
  @keyframes justDrawnPop{
    /* .my-hand tiles rest tilted (rotateX(10deg)) in their rack — carry that
       same tilt through both ends of this animation so the tile doesn't
       visibly flatten out and snap back once the pop finishes. */
    0%{ transform: translateY(6px) scale(.92); box-shadow: 0 0 0 0 rgba(201,162,74,0); }
    100%{ transform: translateY(0) scale(1); }
  }
  @keyframes justDrawnPulse{
    0%, 100%{ box-shadow: 0 0 0 2px var(--gold), 0 2px 10px 1px rgba(201,162,74,.55); }
    50%{ box-shadow: 0 0 0 3px var(--gold), 0 2px 16px 4px rgba(201,162,74,.85); }
  }

  @media (max-width:520px){
    .tile{ --tw:34px; --th:46px; font-size:1rem; }
    .tile.small{ --tw:22px; --th:30px; font-size:.68rem; }
    .tile.xl{ --tw:44px; --th:60px; font-size:1.2rem; }
  }

  /* ---------- my area: sits flush against the same felt, tiles front-and-centre like a real rack ---------- */
  .my-area{
    background: linear-gradient(180deg, var(--felt-2), color-mix(in srgb, var(--felt-2) 80%, black));
    border:none; border-radius:0;
    border-top: 4px solid;
    border-image: linear-gradient(90deg, color-mix(in srgb, var(--rail) 60%, black), var(--rail), var(--gold), var(--rail), color-mix(in srgb, var(--rail) 60%, black)) 1;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom,0px));
    box-shadow: 0 -8px 18px rgba(0,0,0,.25);
    flex: 0 0 auto; color:#f3ecd9;
  }
  .my-area-landscape{
    display:grid; grid-template-columns: minmax(120px,190px) minmax(0,1fr) minmax(120px,190px);
    gap:14px; align-items:flex-end;
  }
  .my-plate{
    grid-column:1; min-width:0; padding:6px 8px; border-radius:12px;
    background: rgba(0,0,0,.14); border:1px solid rgba(255,255,255,.08);
    border-top: 3px solid color-mix(in srgb, var(--rail) 88%, black);
  }
  .my-plate .who{ color:#f3ecd9; }
  .my-hand-dock{ grid-column:2; width:100%; display:flex; flex-direction:column; gap:8px; min-width:0; align-items:center; }
  .my-head{ display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; margin-bottom:8px; min-width:0; }
  .my-head .who{ display:flex; align-items:center; gap:8px; font-weight:700; min-width:0; max-width:100%; }
  #myName{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; flex:1 1 auto; display:inline-block; }
  .my-melds{ display:flex; gap:10px; flex-wrap:wrap; margin-bottom:8px; }
  .my-meld{ display:flex; gap:2px; padding:3px; border-radius:6px; background: rgba(255,255,255,.08); }
  /* Your own rack: bigger tiles, tilted slightly toward you with real perspective
     depth, front-and-centre — the way tiles actually sit in a rack in front of
     you, not a flat row of stickers off to one side. */
  .my-hand{
    display:flex; gap:5px; flex-wrap:wrap; justify-content:center; padding:10px 2px 4px;
    min-height:80px; width:100%; perspective: 1100px;
  }
  .my-hand .tile{ --tw:52px; --th:70px; font-size:1.45rem; }
  .my-hand .tile.selectable:hover{ transform: translateY(-10px); }
  @media (max-width:700px){
    .my-hand .tile{ --tw:38px; --th:51px; font-size:1.05rem; }
  }
  @media (max-height:430px){
    .my-hand .tile{ --tw:34px; --th:46px; font-size:.95rem; }
    .my-hand{ min-height:60px; padding-top:6px; }
    .my-area{ padding:6px 10px calc(6px + env(safe-area-inset-bottom,0px)); }
    .my-area-landscape{ gap:8px; }
    .my-plate .avatar, #myAvatar .avatar{ width:20px !important; height:20px !important; font-size:.65rem !important; }
    .my-head{ margin-bottom:3px; gap:6px; }
    .my-head .who{ font-size:.82rem; gap:5px; }
    .chip{ padding:2px 7px; font-size:.66rem; }
    .my-melds{ margin-bottom:3px; gap:5px; }
    .my-melds .tile, .bonus-rack .tile{ --tw:22px; --th:30px; font-size:.62rem; }
    .bonus-rack{ margin-top:3px; max-height:32px; overflow-y:auto; }
    .my-bonus-tray{ padding:3px 5px; }
    .my-bonus-tray .tray-label{ font-size:.5rem; }
    .my-bonus-tray .tile{ --tw:24px; --th:32px; font-size:.7rem; }
    /* Opponent rails: keep the hand-rack and flower tray (the two things
       this pass added) as visible as possible, and shrink everything else
       around them so a short phone-landscape screen doesn't clip them. */
    .seat-rail{ padding:5px 4px; gap:3px; }
    .seat-rail .avatar{ width:20px; height:20px; font-size:.62rem; }
    .seat-rail .nm{ font-size:.6rem; }
    .seat-rail .meta.fan-total, .badge-dealer, .wind-chip{ font-size:.54rem; padding:1px 5px; margin-top:0; }
    .tileback{ width:10px; height:14px; border-radius:2px; --tside:3px; }
    /* At this height there's no room left for the purely-decorative
       persistent wall — hide it and keep the space for hand/flowers/discards. */
    .wall-row.live-wall{ display:none; }
    .discard-tray{ padding:3px 4px 2px; gap:2px; max-height:36px; overflow-y:auto; }
    .discard-tray .tray-label{ font-size:.48rem; }
    .discard-tray .tile{ --tw:16px; --th:22px; font-size:.5rem; }
    .bonus-tray{ padding:3px 4px 2px; gap:2px; }
    .bonus-tray .tray-label{ font-size:.48rem; }
    .bonus-tray .tile{ --tw:16px; --th:22px; font-size:.5rem; }
    .seat-rail .mini-melds{ max-height:24px; overflow:hidden; }
    .seat-rail .mini-discards{ max-height:22px; overflow:hidden; }
  }
  .action-bar{
    grid-column:3; display:flex; gap:8px; flex-wrap:wrap; align-items:center; justify-content:center;
    align-content:flex-end; max-width:190px; justify-self:end;
  }
  .action-circle{
    width:62px; height:62px; border-radius:50%; flex-shrink:0;
    border:none; cursor:pointer; color:#fff; background: var(--jade);
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    font-weight:800; font-size:.7rem; line-height:1.15; text-align:center; padding:2px;
    box-shadow: 0 3px 0 rgba(0,0,0,.28), inset 0 0 0 2px rgba(255,255,255,.15);
  }
  .action-circle .sub{ font-size:.58rem; font-weight:700; opacity:.85; }
  .action-circle:active{ transform: translateY(2px); box-shadow: inset 0 0 0 2px rgba(255,255,255,.15); }
  .action-circle.win{ background: var(--lacquer); }
  .action-circle.kong{ background: #5a4a8a; }
  .action-circle.pass{ background: var(--surface-2); color: var(--ink); border:2px solid var(--line); box-shadow:none; }
  .action-hint{ color: var(--ink-soft); font-size:.82rem; }
  .claim-timer{
    font-size:.9rem; color: var(--lacquer); font-weight:800; min-width:34px; text-align:center;
  }
  @media (max-width:560px){
    .my-area-landscape{ gap:10px; }
    .action-circle{ width:52px; height:52px; font-size:.62rem; }
  }

  /* ---------- chat ----------
     Pinned bottom-LEFT, not bottom-right: the action buttons (Draw/Win/Kong)
     live at the right edge of the my-area strip (.action-bar,
     justify-self:end), so a fixed button in that same corner would sit on
     top of them and silently swallow clicks meant for gameplay. */
  .fab{
    position: fixed; left: 18px; bottom: calc(18px + env(safe-area-inset-bottom,0px));
    width:52px; height:52px; border-radius:50%; border:none; background: var(--lacquer); color:#fff;
    font-size:1.3rem; cursor:pointer; box-shadow: var(--shadow); z-index: 40;
  }
  .fab .dot{ position:absolute; top:4px; right:4px; width:10px; height:10px; border-radius:50%; background: var(--gold); border:2px solid var(--surface); }
  .drawer{
    position: fixed; right: 14px; left:14px; bottom: calc(80px + env(safe-area-inset-bottom,0px)); margin-inline:auto; max-width: 380px;
    background: var(--surface); border:1px solid var(--line); border-radius:16px; box-shadow: var(--shadow);
    display:flex; flex-direction:column; height: min(calc(60vh / var(--zoom, 1)), 460px); z-index:41; overflow:hidden;
  }
  .drawer .dhead{ display:flex; justify-content:space-between; align-items:center; padding:10px 12px; border-bottom:1px solid var(--line); font-weight:800; }
  .drawer .dbody{ flex:1; overflow-y:auto; padding:10px 12px; display:flex; flex-direction:column; gap:8px; }
  .msg{ font-size:.85rem; line-height:1.35; }
  .msg .who{ font-weight:800; margin-right:5px; }
  .msg.log{ color: var(--ink-soft); font-style:italic; font-size:.78rem; }
  .drawer .dfoot{ display:flex; gap:6px; padding:10px; border-top:1px solid var(--line); }
  .drawer .dfoot input{ flex:1; padding:9px 10px; border-radius:9px; border:1px solid var(--line); background: var(--surface-2); color:var(--ink); }
  .drawer .dfoot button{ border:none; background: var(--lacquer); color:#fff; border-radius:9px; padding:0 14px; font-weight:800; cursor:pointer; }

  /* ---------- modal / overlay ---------- */
  .modal-backdrop{
    position: fixed; inset:0; background: rgba(10,14,12,.55); display:flex; align-items:center; justify-content:center;
    padding:20px; z-index:50;
  }
  /* ---------- on-table wall build + dice-roll + dealing ----------
     No more separate full-screen "deal scene": the walls, the dice, and the
     tile-by-tile deal all happen right inside the persistent seat rails,
     my-hand dock and center hub, so the table never cuts away to a
     different screen and back. */
  .seat-rail.dealing{ justify-content:flex-start; }
  .my-wall-dock{
    width:100%; display:flex; flex-direction:column; align-items:center; gap:6px;
    background: linear-gradient(180deg, rgba(0,0,0,.22), rgba(0,0,0,.1));
    border:1px solid rgba(201,162,74,.35); border-radius:10px; padding:8px 8px 10px;
  }
  .wall-label{ color:#f3ecd9; font-weight:800; font-size:.68rem; text-align:center; letter-spacing:.04em; text-transform:uppercase; opacity:.85; }
  .wall-row{ display:flex; flex-wrap:wrap; gap:3px 5px; align-items:flex-end; justify-content:center; max-width:100%; }
  .seat-rail .wall-row{ max-width:126px; }
  /* The persistent, on-table remainder of this seat's wall — shown all game,
     not just while dealing, and shrinking as real draws happen. Smaller than
     the dealing-phase stacks so it sits quietly above the hand-rack instead
     of dominating the rail. */
  .wall-row.live-wall{
    margin-top:4px; padding:4px 3px; border-radius:8px; max-width:118px;
    background: rgba(0,0,0,.16); border:1px solid rgba(255,255,255,.1);
    gap:2px 3px;
  }
  .my-plate .wall-row.live-wall{ max-width:170px; margin-top:8px; }
  .wall-stack.compact{ width:11px; height:22px; }
  .wall-stack.compact .brick{ width:10px; height:9px; }
  .wall-stack.compact .brick.layer-bottom{ top:13px; }
  .wall-stack.compact .brick .f-top{ height:5px; }
  .wall-stack.compact .brick .f-front{ top:4px; height:5px; }

  /* Each wall-stack is two real tiles. Every tile is drawn as a small 3D
     brick — a tilted top face plus a front face with real height, so the
     thickness and the two layers actually read at a glance instead of
     being two flat rectangles. */
  .wall-stack{ position:relative; width:20px; height:40px; flex-shrink:0; }
  .wall-stack.building{ animation: stackDrop .34s cubic-bezier(.22,.85,.3,1) both; }
  @keyframes stackDrop{ from{ opacity:0; transform: translateY(-18px) scale(.6); } to{ opacity:1; transform: translateY(0) scale(1); } }
  .brick{ position:absolute; left:1px; width:18px; height:16px; }
  .brick.layer-bottom{ top:23px; z-index:1; }
  .brick.layer-top{ top:0; z-index:2; filter: drop-shadow(0 3px 2px rgba(0,0,0,.5)); }
  .brick .f-top{
    position:absolute; left:0; top:0; width:100%; height:9px; border-radius:3px 3px 1px 1px;
    background: linear-gradient(155deg, color-mix(in srgb, var(--jade) 96%, white), var(--jade));
    border:1px solid rgba(0,0,0,.4); border-bottom:none;
    transform: perspective(50px) rotateX(48deg); transform-origin: bottom;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.5);
  }
  .brick .f-front{
    position:absolute; left:0; top:7px; width:100%; height:10px; border-radius:0 0 3px 3px;
    background: linear-gradient(180deg, color-mix(in srgb, var(--jade) 70%, black), color-mix(in srgb, var(--jade) 38%, black));
    border:1px solid rgba(0,0,0,.55); border-top:none;
    box-shadow: inset 0 -2px 3px rgba(0,0,0,.4), 0 2px 1px rgba(0,0,0,.35);
  }
  /* The bottom layer sits underneath the top one — a touch darker, as if in
     its shade, so the two layers read as distinct tiles, not one tall block. */
  .brick.layer-bottom .f-top{ background: linear-gradient(155deg, color-mix(in srgb, var(--jade) 78%, white), color-mix(in srgb, var(--jade) 82%, black)); }
  .brick.layer-bottom .f-front{ background: linear-gradient(180deg, color-mix(in srgb, var(--jade) 55%, black), color-mix(in srgb, var(--jade) 28%, black)); }
  .wall-stack.broken .brick .f-top{ box-shadow: inset 0 1px 0 rgba(255,255,255,.65), 0 0 10px 3px var(--gold); }
  .wall-stack.taken{ visibility:hidden; }
  /* The dead wall — the 14 tiles just behind the break point that ordinary
     dealing skips over and flower replacements are drawn from instead. */
  .wall-stack.dead-wall .brick .f-top{ background: linear-gradient(155deg,#c9b27a,#7a6a45); }
  .wall-stack.dead-wall .brick .f-front{ background: linear-gradient(180deg,#7a6a45,#453a24); }
  .wall-stack.dead-wall .brick.layer-bottom .f-top{ background: linear-gradient(155deg,#a08e5c,#5c4e30); }
  .wall-stack.dead-wall .brick.layer-bottom .f-front{ background: linear-gradient(180deg,#5c4e30,#332a17); }
  .wall-stack.dead-wall-edge::after{
    content:"dead wall →"; position:absolute; left:50%; bottom:100%; transform:translateX(-50%);
    margin-bottom:3px; font-size:.48rem; font-weight:800; color:#3a2a08; background: var(--gold);
    border-radius:5px; padding:1px 4px; white-space:nowrap; z-index:3;
  }
  .deal-handtray, .deal-bonustray{ display:flex; gap:2px; flex-wrap:wrap; justify-content:center; max-width:130px; min-height:14px; }
  .deal-bonustray:empty{ display:none; }

  /* Dice roll shares the same center hub the wind wheel normally lives in —
     it's the same table, just showing what's happening on it right now. */
  .deal-dice-panel{ display:flex; flex-direction:column; align-items:center; gap:8px; }
  .deal-dice-label{ color: rgba(243,236,217,.75); font-size:.66rem; font-weight:700; text-transform:uppercase; letter-spacing:.05em; }
  .dice-row{ display:flex; gap:16px; }
  .die{ font-size:2.2rem; color:#fff; line-height:1; text-shadow:0 3px 8px rgba(0,0,0,.55); display:inline-block; }
  .die.rolling{ animation: dieTumble .11s linear infinite; }
  @keyframes dieTumble{ from{ transform:rotate(0deg) scale(1); } to{ transform:rotate(360deg) scale(1.1); } }
  .dice-readout{ color:#f3ecd9; font-weight:700; font-size:.78rem; text-align:center; max-width:220px; line-height:1.35; }
  .flying-ghost{ position:fixed; z-index:200; pointer-events:none; top:0; left:0; will-change:transform,opacity; }
  .flying-ghost.from-deadwall .tileback{ box-shadow: 0 0 8px 2px rgba(201,162,74,.7); }
  @media (max-height:430px){
    .die{ font-size:1.7rem; }
    .wall-stack{ width:15px; height:30px; }
    .brick{ width:13px; height:12px; }
    .brick.layer-bottom{ top:17px; }
    .brick .f-top{ height:7px; }
    .brick .f-front{ top:5px; height:7px; }
  }
  @media (max-height:430px){
    .wind-wheel{ width:64px; height:64px; }
    .wind-wheel .wheel-core .rd{ font-size:.9rem; }
    .wind-wheel .wheel-core .wl{ font-size:.48rem; }
    .wind-wheel .wedge{ font-size:.56rem; width:16px; }
    .wind-wheel .wedge.active{ font-size:.66rem; }
    .last-tile-card{ min-width:40px; }
    .last-tile-card .tile.xl{ --tw:34px; --th:46px; font-size:.9rem; }
    .wall-pill{ font-size:.62rem; padding:3px 8px; }
    .turn-banner{ font-size:.78rem; }
    .hub-row{ gap:8px; }
    .center-hub{ gap:4px; padding:4px 2px; }
  }

  /* ---------- rotate-device hint (landscape is the real target layout) ---------- */
  #rotateHint{
    display:none; position:fixed; inset:0; z-index:80; background: var(--felt-2); color:#f3ecd9;
    flex-direction:column; align-items:center; justify-content:center; gap:12px; text-align:center; padding:24px;
  }
  #rotateHint .icon{ font-size:3rem; animation: rotateNudge 1.6s ease-in-out infinite; }
  #rotateHint h2{ color:#f3ecd9; font-size:1.15rem; }
  #rotateHint p{ color: rgba(243,236,217,.75); max-width:36ch; margin:0; font-size:.88rem; }
  @keyframes rotateNudge{ 0%,100%{ transform:rotate(0deg); } 50%{ transform:rotate(-90deg); } }
  /* (Upright phones used to be asked to turn sideways; they now get their
     own stacked layout, see "UPRIGHT PHONE LAYOUT" at the end.) */
  .modal{
    background: var(--surface); border-radius:18px; max-width:560px; width:100%; max-height: calc(82vh / var(--zoom, 1)); overflow-y:auto;
    padding:20px 22px; box-shadow: var(--shadow); border:1px solid var(--line);
  }
  .modal h2{ font-size:1.3rem; margin-bottom:6px; }
  .modal h3{ font-size:.95rem; margin-top:16px; margin-bottom:4px; color: var(--lacquer); }
  .modal p, .modal li{ color: var(--ink-soft); line-height:1.55; font-size:.9rem; }
  .modal .close-x{ float:right; background:none; border:none; font-size:1.2rem; cursor:pointer; color: var(--ink-soft); }
  table.score-table{ width:100%; border-collapse: collapse; margin-top:8px; }
  table.score-table th, table.score-table td{ text-align:left; padding:7px 8px; border-bottom:1px solid var(--line); font-size:.85rem; }
  table.score-table th{ color: var(--ink-soft); font-size:.72rem; text-transform:uppercase; letter-spacing:.05em; }
  .history-item{ font-size:.82rem; color: var(--ink-soft); padding:6px 0; border-bottom:1px dashed var(--line); }

  .overlay-card{ text-align:center; }
  .overlay-card .win-tiles{ display:flex; gap:4px; flex-wrap:wrap; justify-content:center; margin:12px 0; }
  .fan-list{ list-style:none; padding:0; margin:10px 0; display:inline-flex; flex-direction:column; gap:4px; text-align:left; }
  .fan-list li{ display:flex; justify-content:space-between; gap:16px; font-size:.86rem; }
  .delta-row{ display:flex; justify-content:center; gap:18px; margin-top:10px; flex-wrap:wrap; }
  .delta{ font-weight:800; font-family:"Fraunces",serif; font-size:1.1rem; }
  .delta.pos{ color: var(--jade); } .delta.neg{ color: var(--lacquer); }

  .toast{
    position:fixed; left:50%; transform:translateX(-50%); bottom: calc(90px + env(safe-area-inset-bottom,0px));
    background: var(--ink); color: var(--bg); padding:9px 16px; border-radius:999px; font-size:.85rem; font-weight:700;
    z-index:60; box-shadow: var(--shadow);
  }

  /* ---------- money / history / rematch ---------- */
  .balance-hero{ text-align:center; padding:10px 0; }
  .balance-hero .amt{ font-family:"Fraunces",serif; font-size:2.1rem; font-weight:700; color: var(--lacquer); }
  .money-add-row{ display:flex; gap:8px; justify-content:center; flex-wrap:wrap; margin-top:10px; }
  .history-row{ padding:9px 0; border-bottom:1px dashed var(--line); cursor:pointer; }
  .history-row .hsum{ display:flex; justify-content:space-between; gap:10px; align-items:center; font-size:.86rem; }
  .history-row .hsum .res{ font-weight:800; }
  .history-row .hsum .res.win{ color: var(--jade); }
  .history-row .hsum .res.lose{ color: var(--lacquer); }
  .history-row .hmeta{ font-size:.74rem; color: var(--ink-soft); margin-top:2px; }
  .history-detail{ margin-top:8px; padding:10px; background: var(--surface-2); border-radius:10px; font-size:.82rem; }
  .history-detail .win-tiles{ display:flex; gap:3px; flex-wrap:wrap; margin:8px 0; }
  .rematch-row{ display:flex; gap:8px; flex-wrap:wrap; margin-top:14px; }
  .rematch-status{ font-size:.8rem; color: var(--ink-soft); margin-top:8px; }
  .notice-card{ text-align:center; }

  @media (max-width:520px){
    .topbar .title h1{ font-size:1.05rem; }
    .tile{ --tw:28px; --th:38px; font-size:.88rem; }
  }

  /* ---------- auth screen ----------
     Two halves on a computer: the game's felt with its name and a fan of
     real tiles on the left, the sign-in card on the right. On a phone the
     felt becomes a short band on top and the card fills the rest. */
  .auth-screen{ height: calc(100dvh / var(--zoom, 1)); overflow-y:auto; display:grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(400px, 1fr); background: var(--bg); }
  .auth-hero{ position:relative; overflow:hidden; color:#f3ecd9; display:flex; flex-direction:column; justify-content:center;
    gap: clamp(22px, 4vh, 44px); padding: clamp(28px, 6vh, 72px) clamp(28px, 5vw, 80px);
    background: radial-gradient(ellipse 90% 80% at 40% 40%, #1f5a45 0%, #12392c 55%, #0b241c 100%); }
  .auth-hero::after{ content:""; position:absolute; inset:0; pointer-events:none;
    background: repeating-radial-gradient(circle at 30% 30%, rgba(255,255,255,.018) 0 2px, transparent 2px 5px); }
  .auth-brand{ display:flex; align-items:center; gap:16px; position:relative; z-index:1; }
  .auth-logo{ width:56px; height:56px; border-radius:14px; box-shadow: 0 6px 16px rgba(0,0,0,.35); flex:none; }
  .auth-brand h1{ font-size: clamp(1.9rem, 3.1vw, 3rem); color:#f6ecd2; line-height:1.05; }
  .auth-tag{ margin:6px 0 0; color:#cfc4ad; font-size: clamp(.95rem, 1.1vw, 1.15rem); }
  .auth-fan{ position:relative; z-index:1; height: clamp(120px, 24vh, 230px); display:flex; justify-content:center; align-items:flex-end; }
  .auth-fan .tile{ --tw: clamp(58px, 6vw, 96px); --th: calc(var(--tw) * 1.36); font-size: calc(var(--tw) * .5);
    margin: 0 calc(var(--tw) * -.1); transform-origin: 50% 160%; box-shadow: 0 10px 22px rgba(0,0,0,.35); }
  .auth-fan .tile:nth-child(1){ transform: rotate(-18deg); }
  .auth-fan .tile:nth-child(2){ transform: rotate(-9deg); }
  .auth-fan .tile:nth-child(3){ transform: rotate(0deg) translateY(-6px); }
  .auth-fan .tile:nth-child(4){ transform: rotate(9deg); }
  .auth-fan .tile:nth-child(5){ transform: rotate(18deg); }
  .auth-points{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:10px; position:relative; z-index:1;
    font-size: clamp(.92rem, 1.05vw, 1.08rem); color:#e7dcc3; }
  .auth-points li{ display:flex; align-items:center; gap:10px; }
  .auth-points li::before{ content:""; width:8px; height:8px; border-radius:2px; background: var(--gold); transform: rotate(45deg); flex:none; }
  .auth-side{ display:flex; align-items:center; justify-content:center; padding: clamp(24px, 5vh, 64px) clamp(20px, 4vw, 64px); }
  .auth-card{ width:100%; max-width:440px; }
  .auth-card h2{ font-size: clamp(1.6rem, 2.2vw, 2.2rem); margin:0 0 6px; }
  .auth-lede{ margin:0 0 22px; color: var(--ink-soft); font-size:1rem; }
  .auth-tabs{ display:flex; gap:4px; padding:4px; margin-bottom:18px; background: var(--surface-2); border:1px solid var(--line); border-radius:12px; }
  .auth-tab{ flex:1; border:0; background:none; color: var(--ink-soft); border-radius:9px; padding:10px; font-weight:800; cursor:pointer; font-size:.92rem; }
  .auth-tab.active{ background: var(--surface); color: var(--ink); box-shadow: 0 1px 4px rgba(0,0,0,.12); }
  .auth-field{ display:flex; flex-direction:column; gap:6px; margin-top:14px; }
  .auth-field label{ font-size:.85rem; font-weight:700; color: var(--ink); }
  .auth-field input{ height:48px; padding:0 14px; border-radius:11px; border:1px solid var(--line);
    background: var(--surface); color: var(--ink); font-size:1rem; font-family:inherit; }
  .auth-field input:focus{ border-color: var(--gold); outline:none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 30%, transparent); }
  .auth-hint{ font-size:.8rem; color: var(--ink-soft); }
  .auth-submit{ margin-top:22px; width:100%; height:50px; font-size:1rem; border-radius:12px; }
  .auth-error{ color: var(--lacquer); font-size:.88rem; margin-top:12px; min-height:1.3em; }
  .auth-foot{ margin:18px 0 0; font-size:.8rem; color: var(--ink-soft); }
  /* tablets held upright and phones: felt band on top */
  @media (max-width: 860px){
    .auth-screen{ grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
    .auth-hero{ gap:14px; padding: 22px 20px 20px; padding-top: calc(22px + env(safe-area-inset-top, 0px)); }
    .auth-logo{ width:44px; height:44px; border-radius:11px; }
    .auth-brand h1{ font-size:1.6rem; }
    .auth-tag{ font-size:.9rem; margin-top:3px; }
    .auth-fan{ height:96px; }
    .auth-fan .tile{ --tw:50px; }
    .auth-points{ display:none; }
    .auth-side{ align-items:flex-start; padding: 24px 20px calc(24px + env(safe-area-inset-bottom, 0px)); }
  }
  /* phones held sideways: two short columns, no tile fan */
  @media (max-height: 520px) and (orientation: landscape){
    .auth-screen{ grid-template-columns: minmax(0, .8fr) minmax(0, 1fr); grid-template-rows: none; }
    .auth-hero{ padding: 16px 20px; gap:10px; }
    .auth-fan{ display:none; }
    .auth-points{ display:flex; font-size:.82rem; gap:6px; }
    .auth-side{ align-items:center; padding: 12px 20px; }
    .auth-card h2{ font-size:1.25rem; }
    .auth-lede{ display:none; }
    .auth-tabs{ margin-bottom:8px; }
    .auth-tab{ padding:7px; }
    .auth-field{ margin-top:8px; gap:3px; }
    .auth-field input{ height:40px; }
    .auth-submit{ margin-top:12px; height:42px; }
    .auth-foot{ display:none; }
  }
  .who-chip{ display:flex; align-items:center; gap:6px; }
  .btn-logout{ background:none; border:1px solid var(--line); color: var(--ink-soft); border-radius:10px; padding:6px 11px; font-size:.76rem; font-weight:700; cursor:pointer; }
  .conn-dot{ width:8px; height:8px; border-radius:50%; display:inline-block; margin-right:4px; }
  .conn-dot.up{ background: var(--jade); } .conn-dot.down{ background: var(--lacquer); }

  /* =====================================================================
     ON-TABLE ARENA
     One felt surface. Each seat owns a zone laid straight onto it (hand
     row, wall, discard pond), built as if its owner sits at the bottom and
     then rotated to face where they really sit: 0° for me, 90° for the
     seat on my left, -90° for the seat on my right. Every tile's edge and
     cast shadow therefore fall toward the player who owns it.
     --tu (one tile's width) is set from the felt's real size by
     layoutArena() in client.js, so the whole table scales as one piece.
     ===================================================================== */
  .felt.felt-arena{
    --tu: 26px; --arena-w: 1000px; --placard-x: 20px;
    position:relative; display:block; padding:0; overflow:hidden; min-height:0;
    background:
      radial-gradient(ellipse 62% 58% at 50% 44%, rgba(255,250,225,.10), transparent 72%),
      radial-gradient(ellipse 120% 110% at 50% 45%, transparent 52%, rgba(0,0,0,.42) 100%),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 .55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='.32'/></svg>"),
      var(--felt);
  }
  .arena{
    position:absolute; top:0; bottom:0; left:50%; width: var(--arena-w);
    transform: translateX(-50%);
  }

  /* ---- zones ---- */
  .seat-zone{
    position:absolute; width: calc(var(--tu) * 20.5);
    display:flex; flex-direction:column-reverse; align-items:center;
    gap: calc(var(--tu) * .42);
    padding-bottom: calc(var(--tu) * .3);
    /* anchor the owner's edge (local bottom-centre) on the arena edge, then
       rotate the whole zone about that point to face its owner */
    transform-origin: 50% 100%;
    transform: translate(-50%, -100%) rotate(var(--zrot, 0deg));
  }
  .zone-bottom{ left:50%; top:100%; --zrot: 0deg; }
  .zone-left{ left:0; top:50%; --zrot: 90deg; }
  .zone-right{ left:100%; top:50%; --zrot: -90deg; }

  .zone-hand{
    display:flex; align-items:flex-end; justify-content:center; flex-wrap:wrap-reverse;
    gap: calc(var(--tu) * .32); min-height: calc(var(--tu) * 1.7);
    max-width:100%; transition: filter .25s ease;
  }
  .zone-backs, .zone-flowers, .zone-meld{ display:flex; align-items:flex-end; gap:1px; }
  .zone-melds{ display:flex; align-items:flex-end; gap: calc(var(--tu) * .22); }
  .zone-backs:empty, .zone-flowers:empty{ display:none; }
  .seat-zone.dealing .zone-backs, .seat-zone.dealing .zone-flowers{ display:flex; min-height: calc(var(--tu) * 1.4); }
  .zone-wall{ display:flex; gap:1px; align-items:flex-start; }
  .zone-pond{
    display:flex; flex-wrap:wrap-reverse; align-content:flex-start; justify-content:flex-start;
    gap:2px; width: calc(var(--tu) * 10 + 18px); min-height: calc(var(--tu) * 1.7);
  }
  /* whose turn it is: their side of the table catches the light */
  .seat-zone.active .zone-hand{ filter: drop-shadow(0 0 calc(var(--tu) * .3) rgba(232,190,90,.75)); }

  /* ---- tiles lying on the table ---- */
  .tile.t-table{
    --tw: var(--tu); --th: calc(var(--tu) * 1.36); --tile-radius: calc(var(--tu) * .15);
    font-size: calc(var(--tu) * .5);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.75), inset 0 -2px 2px rgba(0,0,0,.1), 0 1px 2px rgba(0,0,0,.25);
  }
  .tile.t-table.t-flower{ --tw: calc(var(--tu) * .88); --th: calc(var(--tu) * 1.2); font-size: calc(var(--tu) * .46); }
  .tile.t-table .bonus-en{ display:none; }
  .tile.t-table .bonus-svg{ width:1.55em; height:1.55em; }
  .tile.t-table .bonus-label{ font-size:.62em; margin-top:0; }
  .tile.t-table .suitglyph{ font-size:.62em; }
  /* the newest discard glows where it landed — this replaces the old
     "last discard" card in the middle of the table */
  .tile.t-table.latest{
    z-index:2;
    animation: latestGlow 1.5s ease-in-out infinite;
  }
  @keyframes latestGlow{
    0%, 100%{ box-shadow: 0 0 0 2px var(--gold), 0 0 8px 2px rgba(232,190,90,.55); }
    50%{ box-shadow: 0 0 0 2px var(--gold), 0 0 16px 5px rgba(232,190,90,.9); }
  }
  /* claimed discards stay visible, just knocked back */
  .tile.t-table.claimed{ filter: grayscale(.9) brightness(.62); box-shadow:none; }

  /* ---- an opponent's concealed hand: standing tiles, backs toward us ---- */
  .seat-zone .tileback{
    --tside: calc(var(--tu) * .3);
    width: var(--tu); height: calc(var(--tu) * 1.12);
    border-radius: calc(var(--tu) * .15) calc(var(--tu) * .15) 2px 2px;
    margin-bottom: var(--tside); border:none;
    background:
      radial-gradient(120% 70% at 50% 0%, rgba(255,255,255,.22), transparent 60%),
      var(--tile-back);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.35), inset 0 0 0 1px rgba(0,0,0,.22);
    transform:none;
  }
  .seat-zone .tileback::after{
    left:0; right:0; height: var(--tside);
    background: linear-gradient(180deg, var(--tile-back-lo) 0 35%, rgba(0,0,0,.3) 35% calc(35% + 1px), var(--tile-ivory-side) calc(35% + 1px) 100%);
    border-radius: 0 0 2px 2px;
    box-shadow: 0 3px 4px rgba(0,0,0,.4);
  }

  /* ---- the wall: face-down stacks of two ----
     Top = the teal back of the upper tile. The visible side shows both
     tiles' real layers: back / face / back / face. */
  .seat-zone .wall-stack{
    position:relative; width: var(--tu); height: calc(var(--tu) * 2.02); flex:none;
  }
  .seat-zone .wall-stack .ws-top{
    position:absolute; left:0; right:0; top:0; height: calc(var(--tu) * 1.36); z-index:1;
    border-radius: calc(var(--tu) * .14);
    background:
      radial-gradient(120% 70% at 50% 0%, rgba(255,255,255,.24), transparent 62%),
      var(--tile-back);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.4), inset 0 0 0 1px rgba(0,0,0,.28);
  }
  .seat-zone .wall-stack .ws-edge{
    position:absolute; left:1px; right:1px;
    top: calc(var(--tu) * 1.36 - 3px); height: calc(var(--tu) * .66 + 3px);
    border-radius: 0 0 calc(var(--tu) * .12) calc(var(--tu) * .12);
    background:
      linear-gradient(180deg, transparent 80%, rgba(0,0,0,.3) 100%),
      linear-gradient(180deg,
        var(--tile-back-lo) 0 22%,
        var(--tile-ivory-shade) 22% 48%,
        rgba(0,0,0,.5) 48% 51%,
        var(--tile-back-lo) 51% 70%,
        var(--tile-ivory-shade) 70% 100%);
    box-shadow: 0 3px 5px rgba(0,0,0,.45);
  }
  /* one tile left in this stack: the top sits a tile lower */
  .seat-zone .wall-stack.single .ws-top{ top: calc(var(--tu) * .33); }
  .seat-zone .wall-stack.single .ws-edge{
    top: calc(var(--tu) * 1.69 - 3px); height: calc(var(--tu) * .33 + 3px);
    background: linear-gradient(180deg, var(--tile-back-lo) 0 42%, var(--tile-ivory-shade) 42% 100%);
  }
  .seat-zone .wall-stack.taken{ visibility:hidden; }
  .seat-zone .wall-stack.dead-wall .ws-top{
    box-shadow: inset 0 1px 0 rgba(255,255,255,.4), inset 0 0 0 1px rgba(0,0,0,.28), inset 0 -3px 0 rgba(216,181,98,.85);
  }
  .seat-zone .wall-stack.broken .ws-top{
    box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 0 0 2px var(--gold), 0 0 12px 3px rgba(232,190,90,.8);
  }
  .seat-zone .wall-stack.dead-wall-edge::after{ display:none; }

  /* ---- centre: round wind, tiles left, whose turn ---- */
  .arena .center-hub{
    position:absolute; left:50%; top: calc((100% - var(--tu) * 10.5) / 2);
    transform: translate(-50%, -50%); padding:0; gap:10px; width: calc(var(--tu) * 13);
    max-width: calc(var(--arena-w) - var(--tu) * 22);
  }
  .arena .hub-normal{ display:flex; flex-direction:column; align-items:center; gap:10px; }
  .arena .wall-pill{ font-size:.74rem; padding:4px 12px; background: rgba(0,0,0,.28); }
  .arena .turn-banner{ font-size:.95rem; text-shadow: 0 1px 2px rgba(0,0,0,.5); }

  /* ---- opponents' placards, in the felt margin beside their seat ---- */
  .placard{
    position:absolute; top:50%; transform: translateY(-50%); width:140px; z-index:5;
    display:flex; flex-direction:column; align-items:center; gap:6px; color:#f3ecd9;
  }
  /* Each placard turns to face its owner, same as their zone: the left
     player's reads upright from the left edge, the right player's from the
     right edge. */
  .placard-left{ left: var(--placard-x); transform: translateY(-50%) rotate(90deg); }
  .placard-right{ right: var(--placard-x); transform: translateY(-50%) rotate(-90deg); }
  .placard .name-plate{ transition: box-shadow .25s ease; }
  .placard .nm{ font-weight:700; font-size:.78rem; text-align:center; width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .placard .avatar{ width:30px; height:30px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-weight:800; color:#1c1208; font-size:.8rem; }
  .placard-chips{ display:flex; gap:5px; flex-wrap:wrap; justify-content:center; }
  .placard-chips .wind-chip{ margin-top:0; }
  .placard-stats{ display:flex; gap:10px; font-size:.7rem; opacity:.85; }
  .placard.active .name-plate{
    box-shadow: 0 0 0 2px var(--gold), 0 0 18px 5px rgba(232,190,90,.5), 0 5px 9px rgba(0,0,0,.35);
  }
  /* No margin to spare: tuck them, still turned, into the top corners. */
  .felt-arena.placards-compact .placard{ top:8px; width:118px; gap:4px; }
  .felt-arena.placards-compact .placard-left{ left:8px; transform-origin: top left; transform: rotate(90deg) translateY(-100%); }
  .felt-arena.placards-compact .placard-right{ right:8px; transform-origin: top right; transform: rotate(-90deg) translateY(-100%); }
  .felt-arena.placards-compact .placard-stats{ display:none; }

  /* ---- my dock: just me, my hand, my actions ---- */
  .my-plate{ display:flex; flex-direction:column; gap:8px; align-items:flex-start; }
  .my-chips{ display:flex; gap:5px; flex-wrap:wrap; }
  .my-plate .name-plate-h{ max-width:100%; }
  .seat-chip{ background: rgba(201,162,74,.22); color:#f3e2b0; border-color: rgba(201,162,74,.5); }

  /* Dealer (莊) badge rides on the rim beside its wind, pointing outward —
     never across the "round wind" label in the middle of the wheel. */
  .wind-wheel .wedge.s.is-dealer::after{ top:auto; bottom:-16px; transform:translateX(-50%); }
  .wind-wheel .wedge.n.is-dealer::after{ top:-16px; }
  .wind-wheel .wedge.e.is-dealer::after{ top:50%; left:auto; right:-19px; transform:translateY(-50%); }
  .wind-wheel .wedge.w.is-dealer::after{ top:50%; left:-19px; transform:translateY(-50%); }

  /* Chat button floats on the felt just above the dock instead of on top
     of my own name plate. --dock-h is measured by layoutArena(). */
  body.in-game .fab{ bottom: calc(var(--dock-h, 150px) + 14px); }
  body.in-game .drawer{ bottom: calc(var(--dock-h, 150px) + 76px); }

  /* ---- the flower rack: a wooden ledge in front of the hand ----
     Built like a real tile rack: a wooden plank (same wood as the name
     plates) with a darker groove cut into it that the tiles actually sit
     in, and the player's flower fan struck on a gold coin set into the
     end. Everything here is in --tu units, so it scales with the table. */
  .zone-tray{
    position:relative; display:flex; align-items:center;
    gap: calc(var(--tu) * .26);
    padding: calc(var(--tu) * .2) calc(var(--tu) * .24);
    border-radius: calc(var(--tu) * .26);
    background:
      repeating-linear-gradient(90deg, rgba(0,0,0,.035) 0 2px, transparent 2px 9px),
      linear-gradient(170deg, color-mix(in srgb, var(--rail) 86%, white 14%), var(--rail) 50%, color-mix(in srgb, var(--rail) 72%, black));
    border:1px solid color-mix(in srgb, var(--rail) 40%, black);
    box-shadow:
      0 calc(var(--tu) * .1) 0 color-mix(in srgb, var(--rail) 45%, black),
      0 calc(var(--tu) * .18) calc(var(--tu) * .3) rgba(0,0,0,.45),
      inset 0 1px 0 rgba(255,255,255,.3);
  }
  /* the groove the tiles rest in */
  .zone-tray .zone-flowers{
    display:flex; align-items:flex-end; gap: calc(var(--tu) * .1);
    min-height: calc(var(--tu) * 1.7); min-width: calc(var(--tu) * 1.3);
    padding: calc(var(--tu) * .1) calc(var(--tu) * .12) 0;
    border-radius: calc(var(--tu) * .14);
    background: color-mix(in srgb, var(--rail) 55%, black);
    box-shadow: inset 0 calc(var(--tu) * .08) calc(var(--tu) * .16) rgba(0,0,0,.55), 0 1px 0 rgba(255,255,255,.18);
  }
  .zone-tray.empty .zone-flowers{ display:none; }
  /* flowers on the rack are full-size tiles, icon and name both legible */
  .zone-tray .tile.t-table.t-flower{
    --tw: var(--tu); --th: calc(var(--tu) * 1.36); font-size: calc(var(--tu) * .5);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.8), inset 0 -2px 2px rgba(0,0,0,.08), 0 1px 1px rgba(0,0,0,.4);
  }
  .zone-tray .tile.t-table .bonus-svg{ width:1.75em; height:1.75em; }
  .zone-tray .tile.t-table .bonus-label{ font-size:.74em; font-weight:400; }
  /* the flower-fan coin */
  .tray-fan{
    flex:none; width: calc(var(--tu) * 1.28); height: calc(var(--tu) * 1.28); border-radius:50%;
    display:flex; flex-direction:column; align-items:center; justify-content:center; line-height:1;
    background: radial-gradient(circle at 36% 30%, #fff1c2 0%, #e7c262 38%, #b88a2c 78%, #8a6419 100%);
    border:1px solid #5e430f;
    box-shadow: 0 calc(var(--tu) * .07) 0 #5e430f, 0 calc(var(--tu) * .12) calc(var(--tu) * .2) rgba(0,0,0,.5),
                inset 0 0 0 calc(var(--tu) * .07) rgba(255,236,170,.35), inset 0 0 0 calc(var(--tu) * .1) rgba(94,67,15,.35);
    color:#3b2807; text-shadow: 0 1px 0 rgba(255,246,210,.55);
  }
  .tray-fan b{ font-family:"Fraunces", Georgia, serif; font-weight:700; font-size: calc(var(--tu) * .58); }
  .tray-fan span{ font-size: calc(var(--tu) * .22); font-weight:800; text-transform:uppercase; letter-spacing:.08em; margin-top: calc(var(--tu) * .02); }
  /* no flowers yet: just the coin in a small wooden holder */
  .zone-tray.empty{ padding: calc(var(--tu) * .14); border-radius:50%; }
  .zone-tray.empty .tray-fan{ opacity:.8; filter: saturate(.6); }

  /* =====================================================================
     PAUSE + VOICE
     ===================================================================== */
  .btn-pause{ font-weight:800; }
  .btn-pause.is-paused{ background: var(--gold); color:#2d2006; border-color: var(--gold); }

  .pause-overlay{
    position:fixed; inset:0; z-index:35;
    display:flex; align-items:center; justify-content:center; padding:20px;
    background: rgba(6,14,11,.62);
    backdrop-filter: blur(3px) saturate(.8); -webkit-backdrop-filter: blur(3px) saturate(.8);
    animation: pauseFade .2s ease both;
  }
  @keyframes pauseFade{ from{ opacity:0; } to{ opacity:1; } }
  .pause-card{
    width:min(380px, 100%); text-align:center; color:#f3ecd9;
    padding:26px 24px 20px; border-radius:18px;
    background: linear-gradient(170deg, color-mix(in srgb, var(--felt) 85%, white 6%), var(--felt-2));
    border:1px solid rgba(216,181,98,.45);
    box-shadow: 0 24px 60px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.08);
  }
  .pause-glyph{
    width:58px; height:58px; margin:0 auto 10px; border-radius:50%;
    display:flex; align-items:center; justify-content:center; font-size:1.5rem;
    background: radial-gradient(circle at 36% 30%, #fff1c2, #e7c262 40%, #a57a22); color:#2d2006;
    box-shadow: 0 3px 0 #5e430f, 0 6px 14px rgba(0,0,0,.45);
  }
  .pause-card h2{ font-family:"Fraunces", serif; font-size:1.45rem; margin:0 0 4px; }
  .pause-by{ margin:0 0 16px; font-size:.9rem; color: rgba(243,236,217,.8); }
  .pause-by b{ color:#ffe29a; }
  .pause-resume{ width:100%; font-size:.95rem; padding:11px; }
  .pause-talk{ margin-top:18px; padding-top:14px; border-top:1px solid rgba(255,255,255,.1); }
  .pause-talk-lbl{ margin:0 0 8px; font-size:.7rem; font-weight:800; letter-spacing:.07em; text-transform:uppercase; color: rgba(243,236,217,.6); }
  .pause-talk-btns{ display:flex; gap:8px; }
  .pause-talk-btn{
    flex:1; padding:9px 10px; border-radius:10px; cursor:pointer; font-weight:800; font-size:.85rem;
    color:#f3ecd9; background: rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.16);
  }
  .pause-talk-btn:hover{ background: rgba(255,255,255,.13); }
  .pause-talk .voice-people{ margin-top:10px; justify-content:center; }
  /* the game underneath can't be played while paused */
  body.table-paused #myAreaScreen, body.table-paused #tableScreen{ pointer-events:none; }

  /* voice: mic button beside chat, and a small bar listing who's in */
  .fab-voice{ left:80px; background: #2c4a3e; font-size:1.2rem; }
  .fab-voice.on{ background: var(--jade); }
  .fab-voice.muted{ background: #5b4a3a; }
  .voice-count{
    position:absolute; top:-4px; right:-4px; min-width:18px; height:18px; padding:0 4px; border-radius:999px;
    background: var(--gold); color:#2d2006; font-size:.66rem; font-weight:800;
    display:flex; align-items:center; justify-content:center; border:2px solid var(--felt-2);
  }
  .voice-bar{
    position:fixed; left:18px; z-index:40; bottom: calc(var(--dock-h, 150px) + 76px);
    display:flex; flex-direction:column; gap:8px; max-width:260px;
    padding:10px 12px; border-radius:14px; color:#f3ecd9;
    background: rgba(8,20,16,.88); border:1px solid rgba(255,255,255,.12); box-shadow: 0 8px 22px rgba(0,0,0,.4);
  }
  .voice-bar-btns{ display:flex; gap:6px; }
  .voice-btn{
    flex:1; padding:6px 8px; border-radius:8px; font-weight:800; font-size:.74rem; cursor:pointer;
    color:#f3ecd9; background: rgba(255,255,255,.08); border:1px solid rgba(255,255,255,.16);
  }
  .voice-btn.leave{ color:#ffb4b4; border-color: rgba(217,72,76,.5); }
  .voice-people{ display:flex; flex-wrap:wrap; gap:6px; }
  .voice-person{
    display:inline-flex; align-items:center; gap:6px; padding:4px 9px; border-radius:999px;
    font-size:.74rem; font-weight:700; background: rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.12);
    transition: box-shadow .12s ease, border-color .12s ease;
  }
  .voice-person .vp-dot{ width:7px; height:7px; border-radius:50%; background:#6fd3a0; }
  .voice-person.connecting .vp-dot{ background:#c9a24a; }
  .voice-person.muted .vp-dot{ background:#8a8074; }
  .voice-person.speaking{ border-color:#6fd3a0; box-shadow: 0 0 0 2px rgba(111,211,160,.35); }
  .voice-empty{ font-size:.76rem; color: rgba(243,236,217,.55); }
  .msg.system{ color:#e6c97a; font-style:normal; font-weight:700; }
  body.in-game .voice-bar{ bottom: calc(var(--dock-h, 150px) + 76px); }
  /* In a game the chat opens on the right, so it never covers the centred
     pause card or the table's middle. */
  body.in-game .drawer{ left:auto; right:18px; margin:0; width:min(360px, calc(100vw / var(--zoom, 1) - 36px)); }

  /* =====================================================================
     YOUR HAND: tiles standing upright, facing you
     You look slightly down on a standing tile, so what shows besides the
     face is its TOP — the ivory face layer nearest you, then the teal back
     layer behind it — sitting above the face as one continuous block. (A
     tile lying on the table shows its near side below instead; that's the
     base .tile rule.) No perspective tilt, so every tile keeps its true
     rectangle wherever it sits in the row.
     ===================================================================== */
  .my-hand{ perspective:none; align-items:flex-end; }
  .my-hand .tile{
    --tside: calc(var(--th) * .2);
    margin-bottom:0; margin-top: var(--tside);
    border-radius: calc(var(--tile-radius) * .35) calc(var(--tile-radius) * .35) var(--tile-radius) var(--tile-radius);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,.7),
      inset 0 -3px 3px rgba(0,0,0,.1),
      0 3px 0 #b9a978, 0 5px 6px rgba(0,0,0,.35);
  }
  .my-hand .tile::after{
    top:auto; bottom:100%; height: var(--tside);
    border-radius: var(--tile-radius) var(--tile-radius) 0 0;
    background: linear-gradient(180deg,
      var(--tile-back-hi) 0,
      var(--tile-back) 58%,
      rgba(0,0,0,.35) 58% calc(58% + 1px),
      #e9dfc6 calc(58% + 1px) 100%);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.35);
  }
  .bonus-en.long{ letter-spacing:-.01em; font-size:.3rem; }

  /* =====================================================================
     TILE BODIES — one drawing per tile
     Each tile's body (face, ivory layer, teal back, outline) is a single
     SVG, so the face and the side share one outline and one set of corners:
     there is no second box glued underneath and nothing to leave a seam.
     The element itself is only the face area (so the glyph centres on the
     face); ::before paints the full body behind it, extending over the side.
     Generated by gen_shells.py.
     ===================================================================== */
  :root{
    --shell-lying: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 169' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='b' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%238c2a22'/%3E%3Cstop offset='1' stop-color='%235e1712'/%3E%3C/linearGradient%3E%3ClinearGradient id='s' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23e3d7b9'/%3E%3Cstop offset='1' stop-color='%23c9bb95'/%3E%3C/linearGradient%3E%3ClinearGradient id='f' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23fdf9ef'/%3E%3Cstop offset='1' stop-color='%23eee4ca'/%3E%3C/linearGradient%3E%3CradialGradient id='h' cx='.5' cy='0' r='.85'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='.55'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect x='.5' y='0.5' width='99' height='168' rx='12' fill='url(%23b)'/%3E%3Crect x='.5' y='0.5' width='99' height='151' rx='12' fill='url(%23s)'/%3E%3Crect x='.5' y='0.5' width='99' height='136' rx='12' fill='url(%23f)'/%3E%3Crect x='.5' y='0.5' width='99' height='136' rx='12' fill='url(%23h)'/%3E%3Cpath d='M12 1 H88' stroke='%23fff' stroke-opacity='.75' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3Crect x='.5' y='0.5' width='99' height='168' rx='12' fill='none' stroke='%232b200f' stroke-opacity='.32' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
    --shell-standing: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 164' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='t' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23bd4a3e'/%3E%3Cstop offset='1' stop-color='%238f2b22'/%3E%3C/linearGradient%3E%3ClinearGradient id='i' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23f1e8d2'/%3E%3Cstop offset='1' stop-color='%23e0d3b3'/%3E%3C/linearGradient%3E%3ClinearGradient id='f' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23fdf9ef'/%3E%3Cstop offset='1' stop-color='%23eee4ca'/%3E%3C/linearGradient%3E%3CradialGradient id='h' cx='.5' cy='0' r='.85'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='.55'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect x='.5' y='0.5' width='99' height='60' rx='12' fill='url(%23t)'/%3E%3Crect x='.5' y='11' width='99' height='60' rx='12' fill='url(%23i)'/%3E%3Crect x='.5' y='27.5' width='99' height='136' rx='12' fill='url(%23f)'/%3E%3Crect x='.5' y='27.5' width='99' height='136' rx='12' fill='url(%23h)'/%3E%3Cpath d='M12 1 H88' stroke='%23fff' stroke-opacity='.75' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3Crect x='.5' y='0.5' width='99' height='163' rx='12' fill='none' stroke='%232b200f' stroke-opacity='.32' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
    --shell-back: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 142' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='s' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23e3d7b9'/%3E%3Cstop offset='1' stop-color='%23c9bb95'/%3E%3C/linearGradient%3E%3ClinearGradient id='t' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23bd4a3e'/%3E%3Cstop offset='1' stop-color='%238f2b22'/%3E%3C/linearGradient%3E%3CradialGradient id='h' cx='.5' cy='0' r='.85'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='.3'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect x='.5' y='0.5' width='99' height='141' rx='12' fill='url(%23s)'/%3E%3Crect x='.5' y='0.5' width='99' height='121' rx='12' fill='url(%23t)'/%3E%3Crect x='.5' y='0.5' width='99' height='121' rx='12' fill='url(%23h)'/%3E%3Cpath d='M12 1 H88' stroke='%23fff' stroke-opacity='.75' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3Crect x='.5' y='0.5' width='99' height='141' rx='12' fill='none' stroke='%232b200f' stroke-opacity='.32' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
    --shell-stack2: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 202' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='s2' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23d8cbac'/%3E%3Cstop offset='1' stop-color='%23bfb08a'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%238c2a22'/%3E%3Cstop offset='1' stop-color='%235e1712'/%3E%3C/linearGradient%3E%3ClinearGradient id='s' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23e3d7b9'/%3E%3Cstop offset='1' stop-color='%23c9bb95'/%3E%3C/linearGradient%3E%3ClinearGradient id='t' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23bd4a3e'/%3E%3Cstop offset='1' stop-color='%238f2b22'/%3E%3C/linearGradient%3E%3CradialGradient id='h' cx='.5' cy='0' r='.85'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='.3'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect x='.5' y='0.5' width='99' height='201' rx='12' fill='url(%23s2)'/%3E%3Crect x='.5' y='0.5' width='99' height='181.5' rx='12' fill='url(%23b)'/%3E%3Crect x='.5' y='0.5' width='99' height='168.5' rx='12' fill='url(%23s)'/%3E%3Crect x='.5' y='0.5' width='99' height='148.5' rx='12' fill='url(%23b)'/%3E%3Crect x='.5' y='0.5' width='99' height='135.5' rx='12' fill='url(%23t)'/%3E%3Crect x='.5' y='0.5' width='99' height='135.5' rx='12' fill='url(%23h)'/%3E%3Cpath d='M12 1 H88' stroke='%23fff' stroke-opacity='.75' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3Crect x='.5' y='0.5' width='99' height='201' rx='12' fill='none' stroke='%232b200f' stroke-opacity='.32' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
    --shell-stack1: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 169' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='s' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23e3d7b9'/%3E%3Cstop offset='1' stop-color='%23c9bb95'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%238c2a22'/%3E%3Cstop offset='1' stop-color='%235e1712'/%3E%3C/linearGradient%3E%3ClinearGradient id='t' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23bd4a3e'/%3E%3Cstop offset='1' stop-color='%238f2b22'/%3E%3C/linearGradient%3E%3CradialGradient id='h' cx='.5' cy='0' r='.85'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='.3'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect x='.5' y='0.5' width='99' height='168' rx='12' fill='url(%23s)'/%3E%3Crect x='.5' y='0.5' width='99' height='148.5' rx='12' fill='url(%23b)'/%3E%3Crect x='.5' y='0.5' width='99' height='135.5' rx='12' fill='url(%23t)'/%3E%3Crect x='.5' y='0.5' width='99' height='135.5' rx='12' fill='url(%23h)'/%3E%3Cpath d='M12 1 H88' stroke='%23fff' stroke-opacity='.75' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3Crect x='.5' y='0.5' width='99' height='168' rx='12' fill='none' stroke='%232b200f' stroke-opacity='.32' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
  }
  .tile{ background:none; border:none; box-shadow:none; isolation:isolate; border-radius: var(--tile-radius); }
  .tile.t-table, .zone-tray .tile.t-table.t-flower, .zone-tray .zone-flowers .tile, .my-hand .tile{ box-shadow:none; border-radius: var(--tile-radius); }
  .tile::after, .my-hand .tile::after{ content:none; }
  .tile::before{
    content:""; position:absolute; z-index:-1; pointer-events:none;
    left:0; right:0; top:0; bottom: calc(var(--tside) * -1);
    background: var(--shell-lying) 0 0 / 100% 100% no-repeat;
    filter: drop-shadow(0 1px 1.2px rgba(0,0,0,.4));
  }
  .my-hand .tile::before{
    top: calc(var(--tside) * -1); bottom:0;
    background-image: var(--shell-standing);
    filter: drop-shadow(0 4px 3px rgba(0,0,0,.45));
  }
  .tile.claimed, .tile.t-table.claimed{ box-shadow:none; }

  .seat-zone .tileback{ background:none; box-shadow:none; border-radius: calc(var(--tu) * .15); isolation:isolate; }
  .seat-zone .tileback::after{ content:none; }
  .seat-zone .tileback::before{
    content:""; position:absolute; z-index:-1; left:0; right:0; top:0; bottom: calc(var(--tside) * -1);
    background: var(--shell-back) 0 0 / 100% 100% no-repeat;
    filter: drop-shadow(0 2px 2px rgba(0,0,0,.4));
  }

  .seat-zone .wall-stack .ws-top, .seat-zone .wall-stack .ws-edge{ display:none; }
  .seat-zone .wall-stack{
    background: var(--shell-stack2) 0 0 / 100% 100% no-repeat;
    filter: drop-shadow(0 2px 2px rgba(0,0,0,.45));
  }
  .seat-zone .wall-stack.single{
    background-image: var(--shell-stack1);
    background-size: 100% calc(var(--tu) * 1.69);
    background-position: 0 100%;
  }
  .seat-zone .wall-stack.dead-wall::after{
    content:""; position:absolute; left:14%; right:14%; top: calc(var(--tu) * 1.2); height:2px;
    border-radius:2px; background:#e3c16a; opacity:.9;
  }
  .seat-zone .wall-stack.dead-wall-edge::after{ display:block; transform:none; bottom:auto; padding:0; font-size:0; }
  .seat-zone .wall-stack.broken{ filter: drop-shadow(0 0 6px rgba(232,190,90,.95)); }

  /* =====================================================================
     INK CALLIGRAPHY LETTERING
     Every character on a tile is brushwork (TileBrush) in soft black ink,
     with 中 in vermilion and 發 in jade. The faint ink-bleed shadow and the
     light catch underneath make it read as ink sitting in the tile's
     surface rather than type printed on top.
     ===================================================================== */
  .tile .honorglyph, .tile .bonus-label, .tile .suitglyph{
    text-shadow: 0 0 .7px rgba(0,0,0,.5), 0 1px 0 rgba(255,255,255,.7);
    line-height:1;
  }
  /* 白: a double blue frame, like the carved border on real tiles */
  .tile.dragon .dragon-blank{
    border:2px solid #2d5aa0; border-radius:4px;
    box-shadow: inset 0 0 0 2px #fbf6ea, inset 0 0 0 3.5px #2d5aa0;
  }
  /* Flowers & seasons carry their seat number (1–4) in the corner — it's
     what decides which seat each one scores for. */
  .tile .seat-num{
    position:absolute; top:.12em; left:.28em; z-index:2;
    font-size:.62em; line-height:1; color:#c3261a;
    /* an ivory halo so the number stays legible over the painting */
    text-shadow: 0 0 1px #fbf6ea, 0 0 1.5px #fbf6ea, 0 0 2.5px #fbf6ea, 0 0 3.5px #fbf6ea;
  }
  .tile.t-table .seat-num{ top:.08em; left:.22em; font-size:.66em; }
  /* 飛, the joker: no picture, just one big gold-leaf brush character with
     a fine dark keyline — the one luxurious tile in the set. */
  .tile .honorglyph.fei-glyph{
    font-size:1.52em; color:transparent; text-shadow:none;
    -webkit-background-clip:text; background-clip:text;
    background-image: linear-gradient(165deg, #fff3c0 0%, #f1cf6a 22%, #b8862a 48%, #f5d983 70%, #8c5f16 100%);
    filter: drop-shadow(0 0 .5px #3b2606) drop-shadow(0 0 .5px #3b2606) drop-shadow(0 1px .7px rgba(80,50,5,.45));
  }
  /* a fine gold double frame inside the face marks it as the special tile */
  .tile.fei::after{ content:""; display:block; position:absolute; pointer-events:none; background:none; height:auto;
    top:9%; bottom:9%; left:11%; right:11%; border-radius: calc(var(--tile-radius) * .7);
    border:1px solid rgba(190,145,48,.7); box-shadow: inset 0 0 0 2px rgba(255,249,230,.7), inset 0 0 0 3px rgba(190,145,48,.4); }
  .tile.t-table.fei::after, .tile.tiny.fei::after, .tile.small.fei::after{ top:7%; bottom:7%; left:9%; right:9%; box-shadow:none; }
  /* the round-wind wheel speaks the same hand */
  .wind-wheel .wedge, .wind-wheel .wheel-core .rd, .wind-wheel .wedge.is-dealer::after{ font-family:"TileBrush","TileBrushKai",serif; font-synthesis:none; }
  .tile.t-table .honorglyph.fei-glyph, .tile.small .honorglyph.fei-glyph, .tile.tiny .honorglyph.fei-glyph{ font-size:1.36em; }

  /* =====================================================================
     CALMER TABLE
     A mid-tone felt instead of near-black (far less contrast strain against
     the ivory tiles), a fine woven texture, one soft overhead light, and a
     faint printed design — a gold double pinstripe round the playing
     surface and a medallion under the wind console, the way automatic
     tables have their felt printed. Everything decorative stays very low
     contrast so it reads as texture, not as more things to look at.
     ===================================================================== */
  .felt.felt-arena{
    background:
      radial-gradient(ellipse 58% 62% at 50% 44%, rgba(255,248,225,.075), transparent 70%),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.3' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 .5 0'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='.2'/></svg>"),
      repeating-linear-gradient(45deg, rgba(255,255,255,.016) 0 1px, transparent 1px 4px),
      repeating-linear-gradient(-45deg, rgba(0,0,0,.03) 0 1px, transparent 1px 4px),
      radial-gradient(ellipse 130% 120% at 50% 45%, #2b5a4d 0%, #234c41 55%, #1a3a32 100%);
  }
  .felt.felt-arena::before, .felt.felt-arena::after{
    content:""; position:absolute; pointer-events:none; border-radius:18px;
  }
  .felt.felt-arena::before{ inset:10px; border:1px solid rgba(214,178,98,.2); }
  .felt.felt-arena::after{ inset:16px; border:1px solid rgba(214,178,98,.09); border-radius:14px; }
  .arena{ isolation:isolate; }

  /* No constant pulsing any more. The newest discard gets a quiet gold edge
     round the whole tile; the side whose turn it is is shown by the wind
     console's arc and their name plate, not by glowing tiles. */
  .tile.t-table.latest{ animation:none; box-shadow:none; }
  .tile.t-table.latest::before{
    filter: drop-shadow(0 0 .8px #e9c567) drop-shadow(0 0 .8px #e9c567) drop-shadow(0 0 5px rgba(233,197,103,.55));
  }
  .seat-zone.active .zone-hand{ filter:none; }

  /* The tile you just drew lifts out of the rack with a gold halo round the
     WHOLE tile — top edge included — not just a box around its face. */
  .my-hand .tile.just-drawn{ animation: drawnLift .3s cubic-bezier(.22,.85,.3,1) both; box-shadow:none; transform: translateY(-9px); margin-left:14px; }
  .my-hand .tile.just-drawn::before{
    filter: drop-shadow(0 0 1px #f2cf73) drop-shadow(0 0 1px #f2cf73) drop-shadow(0 0 9px rgba(242,207,115,.7)) drop-shadow(0 8px 6px rgba(0,0,0,.45));
  }
  .my-hand .tile.just-drawn.selectable:hover{ transform: translateY(-16px); }
  @keyframes drawnLift{ from{ transform: translateY(0); } to{ transform: translateY(-9px); } }
  @media (prefers-reduced-motion: reduce){ .my-hand .tile.just-drawn{ animation:none; } }

  /* =====================================================================
     WIND CONSOLE
     ===================================================================== */
  .console{
    position:relative; width:168px; height:168px; border-radius:50%; flex:none;
    background: radial-gradient(circle at 50% 32%, #2c2824 0%, #171411 58%, #0c0a08 100%);
    box-shadow: 0 0 0 1px #5d4817, 0 0 0 5px #18140f, 0 0 0 6px #c9a24a, 0 0 0 7px #5d4817,
                0 14px 28px rgba(0,0,0,.45), inset 0 2px 8px rgba(255,255,255,.05);
  }
  .console .c-emblem{
    position:absolute; inset:-150px; z-index:-1; pointer-events:none; opacity:.065;
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-200 -200 400 400'><g fill='none' stroke='%23f0cf7a'><circle r='197' stroke-width='1.4'/><circle r='189' stroke-width='.7'/><circle r='172' stroke-width='12' stroke-dasharray='5 7'/><circle r='155' stroke-width='.7'/><circle r='148' stroke-width='1.4'/><circle r='120' stroke-width='.6' stroke-dasharray='2 5'/></g><g fill='%23f0cf7a'><path d='M0 -205 l6 8 -6 8 -6 -8z'/><path d='M0 205 l6 -8 -6 -8 -6 8z'/><path d='M-205 0 l8 6 8 -6 -8 -6z'/><path d='M205 0 l-8 6 -8 -6 8 -6z'/></g></svg>") center / contain no-repeat;
  }
  .console .c-ticks{ position:absolute; inset:9px; border-radius:50%;
    background: repeating-conic-gradient(from -1deg, rgba(201,162,74,.6) 0 2deg, transparent 2deg 11.25deg);
    -webkit-mask: radial-gradient(circle closest-side, transparent 0 90%, #000 91% 97%, transparent 98%);
            mask: radial-gradient(circle closest-side, transparent 0 90%, #000 91% 97%, transparent 98%); }
  .console .c-ring{ position:absolute; inset:42px; border-radius:50%; border:1px solid rgba(201,162,74,.7);
    box-shadow: 0 0 0 4px rgba(0,0,0,.35), 0 0 0 5px rgba(201,162,74,.28); }
  .console .c-arc{ position:absolute; inset:-9px; border-radius:50%; z-index:2; pointer-events:none;
    background: conic-gradient(from var(--from), #ffd27a 0 50deg, transparent 50deg);
    -webkit-mask: radial-gradient(circle closest-side, transparent 0 92.5%, #000 93.5% 99%, transparent 100%);
            mask: radial-gradient(circle closest-side, transparent 0 92.5%, #000 93.5% 99%, transparent 100%);
    filter: drop-shadow(0 0 4px rgba(255,214,120,.9)); }
  .console .c-wind{ position:absolute; width:34px; height:34px; display:flex; align-items:center; justify-content:center;
    font-family:"TileBrush","TileBrushKai",serif; font-synthesis:none; font-size:24px; color:#cda552; line-height:1;
    transition: color .25s ease, text-shadow .25s ease; }
  .console .c-wind.s{ left:50%; bottom:6px; transform:translateX(-50%); }
  .console .c-wind.w{ left:6px; top:50%; transform:translateY(-50%) rotate(90deg); }
  .console .c-wind.e{ right:6px; top:50%; transform:translateY(-50%) rotate(-90deg); }
  .console .c-wind.turn{ color:#fff1c4; text-shadow: 0 0 10px rgba(255,214,120,.95), 0 0 2px rgba(255,214,120,.9); }
  .console .c-seal{ position:absolute; width:15px; height:15px; border-radius:3px; background:#b3261e; color:#fbf1de;
    font-family:"TileBrush","TileBrushKai",serif; font-size:11px; line-height:1; display:flex; align-items:center; justify-content:center;
    box-shadow: inset 0 0 0 1px #fbf1de, inset 0 0 0 1.6px #b3261e; }
  .console .c-seal.s{ left:calc(50% + 17px); bottom:14px; }
  .console .c-seal.w{ left:14px; top:calc(50% + 17px); transform:rotate(90deg); }
  .console .c-seal.e{ right:14px; top:calc(50% - 32px); transform:rotate(-90deg); }
  .console .c-core{ position:absolute; inset:48px; border-radius:50%; display:flex; flex-direction:column; align-items:center; justify-content:center;
    background: radial-gradient(circle at 50% 35%, #3a342c, #1b1713); }
  .console .c-core b{ font-family:"TileBrush","TileBrushKai",serif; font-synthesis:none; font-weight:400; font-size:38px; line-height:1; color:#f3e6c4; text-shadow: 0 1px 0 rgba(0,0,0,.6); }
  .console .c-core span{ font-size:8.5px; letter-spacing:.22em; color:#b99a58; font-weight:800; margin-top:2px; }
  .tilesleft{ display:flex; align-items:baseline; gap:7px; color:#e9dcbc; }
  .tilesleft b{ font-family:"Fraunces", Georgia, serif; font-size:22px; font-weight:700; color:#f3e6c4; }
  .tilesleft span{ font-size:10px; letter-spacing:.2em; font-weight:800; color:#b99a58; }
  .arena .hub-normal{ gap:12px; }
  .arena .turn-banner{ color:#e9dcbc; }
  .arena .turn-banner b{ color:#f0cf79; }
  @media (max-height:560px){
    .console{ width:128px; height:128px; }
    .console .c-ring{ inset:32px; } .console .c-core{ inset:37px; } .console .c-core b{ font-size:28px; }
    .console .c-wind{ font-size:19px; width:28px; height:28px; }
  }

  /* =====================================================================
     NAME PLATES — long and slim
     ===================================================================== */
  .placard{ width:300px; gap:0; }
  .plate{
    display:flex; align-items:center; gap:10px; width:300px; min-height:62px; padding:8px 12px 8px 8px; border-radius:12px;
    color:#fff8ea; box-sizing:border-box;
    background: linear-gradient(170deg, #8a6440, #6d4b2c 55%, #563a22);
    border:1px solid #3d2915; box-shadow: 0 3px 0 #3d2915, inset 0 1px 0 rgba(255,255,255,.28), 0 8px 14px rgba(0,0,0,.35);
    transition: box-shadow .25s ease;
  }
  .placard.active .plate, .plate.mine.active{
    box-shadow: 0 0 0 2px #e2bd5e, 0 0 16px 3px rgba(226,189,94,.35), 0 3px 0 #3d2915, inset 0 1px 0 rgba(255,255,255,.28);
  }
  .pl-av{ width:44px; height:44px; border-radius:50%; flex:none; overflow:hidden; display:flex; align-items:center; justify-content:center;
    font-weight:800; font-size:18px; color:#1c1208; box-shadow: 0 0 0 2px #e2bd5e, 0 2px 5px rgba(0,0,0,.45); }
  .pl-av img{ width:100%; height:100%; object-fit:cover; display:block; }
  .pl-body{ display:flex; flex-direction:column; gap:4px; min-width:0; flex:1; }
  .pl-name{ font-weight:800; font-size:14px; line-height:1.15; text-shadow:0 1px 0 rgba(0,0,0,.5); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .pl-meta{ display:flex; align-items:center; gap:7px; font-size:11.5px; white-space:nowrap; }
  .pl-wind{ display:inline-flex; align-items:center; gap:4px; font-weight:800; padding:1px 7px 1px 2px; border-radius:999px; background: rgba(0,0,0,.25); color:#f3e2b0; }
  .pl-wind i, .pl-dealer i{ font-style:normal; font-family:"TileBrush","TileBrushKai",serif; font-synthesis:none; }
  .pl-wind i{ font-size:13px; width:18px; height:18px; border-radius:50%; background:#f3e6c4; color:#1a1612; display:flex; align-items:center; justify-content:center; }
  .pl-dealer{ display:inline-flex; align-items:center; gap:3px; font-weight:800; color:#ffe2a0; }
  .pl-dealer i{ width:16px; height:16px; border-radius:3px; background:#b3261e; color:#fbf1de; display:flex; align-items:center; justify-content:center; font-size:11px; box-shadow: inset 0 0 0 1px #fbf1de, inset 0 0 0 1.6px #b3261e; }
  .pl-stat{ color:rgba(255,248,234,.82); }
  .pl-stat b{ font-family:"Fraunces", Georgia, serif; font-size:13px; color:#fff; }
  /* my own plate in the dock */
  .my-plate{ background:none; border:none; padding:0; }
  .my-plate .plate{ width:300px; }
  @media (max-width:900px){ .my-plate .plate{ width:220px; } }

  /* =====================================================================
     FLOWER FAN — a vermilion seal stamped on the rack
     ===================================================================== */
  .fan-seal{
    flex:none; width: calc(var(--tu) * 1.34); height: calc(var(--tu) * 1.34); border-radius: calc(var(--tu) * .16);
    background:#b3261e; color:#fbf1de; display:flex; flex-direction:column; align-items:center; justify-content:center; gap: calc(var(--tu) * .02);
    box-shadow: inset 0 0 0 calc(var(--tu) * .06) #fbf1de, inset 0 0 0 calc(var(--tu) * .1) #b3261e;
    filter: drop-shadow(0 2px 2px rgba(0,0,0,.4));
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='90' height='90'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.55' numOctaves='3' seed='7'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 -9 7.6'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>") 0 0/100% 100%;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='90' height='90'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.55' numOctaves='3' seed='7'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 -9 7.6'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>") 0 0/100% 100%;
  }
  .fan-seal b{ font-family:"Fraunces", Georgia, serif; font-weight:700; font-size: calc(var(--tu) * .62); line-height:.9; }
  .fan-seal i{ font-style:normal; font-family:"TileBrush","TileBrushKai",serif; font-synthesis:none; font-size: calc(var(--tu) * .36); line-height:1; }
  .zone-tray.empty .fan-seal{ background:#7d5a3a; box-shadow: inset 0 0 0 calc(var(--tu) * .06) #e9d7b8, inset 0 0 0 calc(var(--tu) * .1) #7d5a3a; }
  .zone-tray.empty{ border-radius: calc(var(--tu) * .26); padding: calc(var(--tu) * .14); }

  /* =====================================================================
     PROFILE
     ===================================================================== */
  .btn-profile{ display:inline-flex; align-items:center; gap:7px; padding-left:5px !important; }
  .pf-mini-av{ width:24px; height:24px; border-radius:50%; overflow:hidden; display:inline-flex; align-items:center; justify-content:center;
    background:#b3281c; color:#fff3e0; font-weight:800; font-size:12px; box-shadow: 0 0 0 1.5px #c9a24a; }
  .pf-mini-av img{ width:100%; height:100%; object-fit:cover; }
  .profile-screen{ flex:1 1 auto; overflow:auto; color:#f3ecd9;
    background: radial-gradient(ellipse 120% 90% at 50% 0%, #1f4a3e, #0f2721 70%); }
  .pf-bar{ display:flex; align-items:center; gap:14px; padding:14px 28px; border-bottom:1px solid rgba(255,255,255,.08); background:rgba(0,0,0,.18); }
  .pf-bar h1{ margin:0; font-family:"Fraunces", serif; font-size:22px; }
  .pf-back{ border:1px solid rgba(255,255,255,.18); background:none; color:#f3ecd9; border-radius:10px; padding:7px 12px; font-weight:800; font-size:13px; cursor:pointer; }
  .pf-wrap{ display:grid; grid-template-columns: 360px minmax(0,1fr); gap:22px; padding:24px 28px 40px; max-width:1320px; margin:0 auto; }
  @media (max-width:900px){ .pf-wrap{ grid-template-columns: 1fr; padding:16px; } }
  .pf-side{ display:flex; flex-direction:column; gap:18px; }
  .pf-card{ background: rgba(8,20,16,.55); border:1px solid rgba(255,255,255,.08); border-radius:18px; padding:20px; }
  .pf-card h2{ margin:0 0 14px; font-size:12px; letter-spacing:.14em; text-transform:uppercase; color:#c9a24a; font-weight:800; font-family:"Manrope", sans-serif; }
  .pf-hero{ display:flex; flex-direction:column; align-items:center; text-align:center; gap:10px; }
  .pf-av{ width:128px; height:128px; border-radius:50%; overflow:hidden; display:flex; align-items:center; justify-content:center;
    background: radial-gradient(circle at 35% 30%, #d9644a, #9e2a1c); font-family:"Fraunces", serif; font-size:52px; font-weight:700; color:#fff3e0;
    box-shadow: 0 0 0 3px #0f2721, 0 0 0 5px #c9a24a, 0 12px 28px rgba(0,0,0,.45); }
  .pf-av img{ width:100%; height:100%; object-fit:cover; }
  .pf-who{ font-family:"Fraunces", serif; font-size:24px; font-weight:700; }
  .pf-sub{ font-size:12.5px; color:rgba(243,236,217,.62); }
  .pf-btnrow{ display:flex; gap:8px; margin-top:4px; }
  .pf-btn{ border-radius:10px; padding:9px 14px; font-weight:800; font-size:13px; cursor:pointer; font-family:inherit;
    border:1px solid rgba(255,255,255,.16); background:rgba(255,255,255,.06); color:#f3ecd9; }
  .pf-btn.primary{ background:#b3281c; border-color:#b3281c; color:#fff; }
  .pf-btn.gold{ background:#c9a24a; border-color:#c9a24a; color:#2a1d05; }
  .pf-btn:focus-visible, .pf-back:focus-visible, .pf-field input:focus-visible{ outline:2px solid #e2bd5e; outline-offset:2px; }
  .pf-field{ display:flex; flex-direction:column; gap:6px; margin-bottom:12px; }
  .pf-field label{ font-size:11px; letter-spacing:.08em; text-transform:uppercase; color:rgba(243,236,217,.62); font-weight:800; }
  .pf-field input{ border-radius:10px; border:1px solid rgba(255,255,255,.14); background:rgba(0,0,0,.25); color:#f3ecd9; padding:10px 12px; font-size:14px; font-family:inherit; }
  .pf-hint{ font-size:12px; color:rgba(243,236,217,.55); margin:-4px 0 12px; }
  .pf-msg{ font-size:12.5px; margin-top:10px; min-height:1em; }
  .pf-msg.ok{ color:#8fd6a5; } .pf-msg.err{ color:#f09a8e; }
  .pf-main{ min-width:0; display:flex; flex-direction:column; gap:18px; }
  .pf-stats{ display:grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap:12px; }
  @media (max-width:640px){ .pf-stats{ grid-template-columns: repeat(2, minmax(0,1fr)); } }
  .pf-stat{ background: rgba(8,20,16,.55); border:1px solid rgba(255,255,255,.08); border-radius:16px; padding:14px 16px; }
  .pf-stat b{ display:block; font-family:"Fraunces", serif; font-size:26px; font-variant-numeric: tabular-nums; }
  .pf-stat span{ font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:rgba(243,236,217,.6); font-weight:800; }
  .pf-stat.pos b{ color:#8fd6a5; } .pf-stat.neg b{ color:#f09a8e; }
  .pf-hist{ display:flex; flex-direction:column; gap:8px; }
  .pf-empty{ color:rgba(243,236,217,.6); font-size:14px; padding:6px 2px; }
  .pf-row{ display:grid; grid-template-columns: 88px minmax(0,1fr) auto; gap:16px; align-items:center; padding:12px 14px; border-radius:14px;
    background:rgba(255,255,255,.035); border:1px solid rgba(255,255,255,.06); cursor:pointer; }
  .pf-row:hover{ background:rgba(255,255,255,.055); }
  .pf-row.open{ background:rgba(255,255,255,.06); border-color:rgba(201,162,74,.35); }
  .pf-res{ font-weight:800; font-size:12px; letter-spacing:.06em; text-transform:uppercase; padding:6px 0; border-radius:8px; text-align:center; }
  .pf-res.win{ background:rgba(143,214,165,.15); color:#8fd6a5; } .pf-res.lose{ background:rgba(229,115,103,.15); color:#f09a8e; }
  .pf-res.draw, .pf-res.solo{ background:rgba(255,255,255,.08); color:#d8cfbd; }
  .pf-mid{ min-width:0; } .pf-mid .t{ font-weight:800; font-size:14px; } .pf-mid .m{ font-size:12px; color:rgba(243,236,217,.6); margin-top:3px; display:flex; align-items:center; flex-wrap:wrap; gap:6px; }
  .pf-opps{ display:inline-flex; padding-left:5px; }
  .pf-opps i{ width:20px; height:20px; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; font-style:normal; font-size:10px; font-weight:800; color:#fff; margin-left:-3px; text-shadow:0 1px 0 rgba(0,0,0,.35); box-shadow:0 0 0 2px #10261f; }
  .pf-amt{ font-family:"Fraunces", serif; font-size:19px; font-weight:700; text-align:right; font-variant-numeric: tabular-nums; }
  .pf-amt.pos, .pf-kv b.pos{ color:#8fd6a5; } .pf-amt.neg, .pf-kv b.neg{ color:#f09a8e; }
  .pf-detail{ grid-column: 1 / -1; display:flex; gap:18px; align-items:center; flex-wrap:wrap; padding-top:10px; border-top:1px solid rgba(255,255,255,.07); }
  .pf-hand{ --tu:26px; display:flex; flex-direction:column; gap:6px; }
  .pf-tiles{ display:flex; gap:2px; flex-wrap:wrap; align-items:flex-end; }
  .pf-gap{ width:8px; }
  .pf-kv{ font-size:12.5px; color:rgba(243,236,217,.75); line-height:1.7; }
  .my-area-landscape{ grid-template-columns: minmax(220px, 312px) minmax(0,1fr) minmax(120px,190px); }

/* ================= TABLE LIST ================= */
.tables-screen{ margin:14px; overflow-y:auto; display:flex; flex-direction:column; gap:14px; max-width:980px; width:calc(100% - 28px); align-self:center; }
.tables-head{ display:flex; align-items:flex-end; justify-content:space-between; gap:16px; flex-wrap:wrap;
  background: var(--surface); border:1px solid var(--line); border-radius:16px; padding:18px 20px; box-shadow: var(--shadow); }
.tables-head h2{ font-size:1.5rem; margin:0 0 4px; }
.tables-head p{ margin:0; color:var(--ink-soft); max-width:58ch; line-height:1.5; }
.tables-list{ display:flex; flex-direction:column; gap:10px; }
.tables-empty{ padding:28px 20px; text-align:center; color:var(--ink-soft); border:1px dashed var(--line); border-radius:14px; }
.tl-row{ display:flex; align-items:center; gap:16px; padding:14px 16px; border-radius:14px; background: var(--surface); border:1px solid var(--line); }
.tl-row.busy{ opacity:.72; }
.tl-main{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:9px; }
.tl-title{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-weight:800; font-size:1rem; }
.tl-status{ font-size:.7rem; font-weight:800; letter-spacing:.06em; text-transform:uppercase; padding:3px 8px; border-radius:999px;
  background: color-mix(in srgb, var(--jade) 16%, var(--surface-2)); color: var(--jade); }
.tl-status.playing{ background: color-mix(in srgb, var(--gold) 20%, var(--surface-2)); color: var(--gold-ink); }
.tl-fan{ font-size:.72rem; color:var(--ink-soft); font-weight:700; }
.tl-seats{ display:flex; gap:8px; flex-wrap:wrap; }
.tl-seat{ display:inline-flex; align-items:center; gap:7px; font-size:.85rem; font-weight:700; padding:3px 10px 3px 3px; border-radius:999px; background: var(--surface-2); border:1px solid var(--line); max-width:220px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.tl-seat.open{ color:var(--ink-soft); font-weight:600; border-style:dashed; }
.tl-av{ width:24px; height:24px; border-radius:50%; flex:none; display:inline-flex; align-items:center; justify-content:center; font-size:.72rem; font-weight:800; color:#fff; background:#8a8074; overflow:hidden; }
.tl-av img{ width:100%; height:100%; object-fit:cover; }
.tl-join{ flex:none; }
.table-crumb{ display:flex; align-items:center; gap:10px; margin-bottom:4px; color:var(--ink-soft); font-size:.85rem; font-weight:700; }
.btn-crumb{ border:1px solid var(--line); background: var(--surface-2); color: var(--ink); border-radius:999px; padding:5px 12px; font-weight:800; font-size:.8rem; cursor:pointer; }
.btn-crumb:hover{ border-color: var(--gold); }
.rematch-status.warn{ color: var(--lacquer); font-weight:700; }
.delta-note{ margin-top:6px; font-size:.78rem; }
@media (max-width:560px){ .tl-row{ flex-direction:column; align-items:stretch; } }

/* Season numbers are inked black; flower numbers stay red. */
.tile.season .seat-num{ color:#141414; }
/* Bonus tiles carry only their Chinese name: with no English line under it,
   the painting gets a little more room. */
.tile .bonus-en{ display:none !important; }
.tile.flower .bonus-svg, .tile.season .bonus-svg, .tile.animal .bonus-svg, .tile.joker .bonus-svg{ width:2.1em; height:2.1em; }
.tile.small.flower .bonus-svg, .tile.small.season .bonus-svg, .tile.small.animal .bonus-svg, .tile.small.joker .bonus-svg{ width:1.75em; height:1.75em; }
.tile.tiny.flower .bonus-svg, .tile.tiny.season .bonus-svg, .tile.tiny.animal .bonus-svg, .tile.tiny.joker .bonus-svg{ width:1.4em; height:1.4em; }
.tile.t-table.flower .bonus-svg, .tile.t-table.season .bonus-svg, .tile.t-table.animal .bonus-svg, .tile.t-table.joker .bonus-svg{ width:1.55em; height:1.55em; }
.zone-tray .tile.t-table.flower .bonus-svg, .zone-tray .tile.t-table.season .bonus-svg, .zone-tray .tile.t-table.animal .bonus-svg, .zone-tray .tile.t-table.joker .bonus-svg{ width:1.75em; height:1.75em; }

/* Animal and joker tiles are icon-only: the picture fills the face. */
.tile.animal .bonus-svg, .tile.joker .bonus-svg,
.tile.small.animal .bonus-svg, .tile.small.joker .bonus-svg,
.tile.tiny.animal .bonus-svg, .tile.tiny.joker .bonus-svg,
.tile.t-table.animal .bonus-svg, .tile.t-table.joker .bonus-svg,
.zone-tray .tile.t-table.animal .bonus-svg, .zone-tray .tile.t-table.joker .bonus-svg{
  width: calc(var(--tw) * .9); height: calc(var(--tw) * .9);
}

#myBalanceChip{ cursor:pointer; }
#myBalanceChip:hover{ filter:brightness(1.06); }

/* ================= CLAIM / ACTION BUTTONS =================
   A tray that rises above your hand only when you have a call to make: each
   button carries the call in brush script (胡 槓 碰 吃 過), a small label,
   and the exact tiles it would use. A ring counts down the claim window. */
.my-area-landscape{ position:relative; }
.action-bar{ justify-content:flex-end; }
.act-hint{ color: rgba(243,236,217,.58); font-size:.78rem; font-weight:600; text-align:right; line-height:1.35; }
.act-tray{
  position:absolute; left:50%; bottom:calc(100% + 14px); transform:translateX(-50%);
  display:flex; align-items:center; gap:10px; padding:10px 12px; z-index:35;
  border-radius:18px; background: rgba(9,14,12,.78); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border:1px solid rgba(201,162,74,.38);
  box-shadow: 0 18px 44px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.06);
  animation: actTrayIn .2s ease-out;
}
@keyframes actTrayIn{ from{ opacity:0; transform:translate(-50%, 10px); } to{ opacity:1; transform:translate(-50%, 0); } }
.act{
  display:flex; align-items:center; gap:10px; height:64px; padding:0 18px 0 10px;
  border-radius:12px; border:1px solid; cursor:pointer; color:#fbf3e2; font:inherit; white-space:nowrap;
  box-shadow: 0 6px 14px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.18);
  transition: transform .12s ease, filter .12s ease, box-shadow .12s ease;
}
.act:hover{ transform: translateY(-2px); filter: brightness(1.1); }
.act:active{ transform: translateY(1px); filter: brightness(.95); }
.act:disabled{ opacity:.5; cursor:default; transform:none; filter:none; }
.act:focus-visible{ outline:2px solid #f0cf79; outline-offset:2px; }
.act-tiles{ display:flex; gap:1px; padding:4px 4px 5px; border-radius:8px; background: rgba(0,0,0,.3); box-shadow: inset 0 1px 2px rgba(0,0,0,.4); }
.act-tiles .tile{ margin:0 !important; transform:none !important; }
.act-label{ display:flex; flex-direction:column; align-items:flex-start; line-height:1; }
.act-zh{ font-family:"TileBrush","TileBrushKai",serif; font-size:30px; font-weight:400; letter-spacing:.02em; }
.act-en{ margin-top:5px; font-size:9.5px; font-weight:800; letter-spacing:.14em; text-transform:uppercase; opacity:.78; }
.act-hu{
  background: linear-gradient(180deg, #d0402f 0%, #9e1f16 60%, #7a150f 100%); border-color:#f0cf79;
  box-shadow: 0 0 0 1px rgba(240,207,121,.35), 0 10px 22px rgba(179,38,30,.5), inset 0 1px 0 rgba(255,255,255,.28);
  animation: actHuGlow 1.6s ease-in-out infinite;
}
.act-hu .act-zh{ color:#ffe7a6; text-shadow: 0 1px 0 rgba(0,0,0,.35); }
@keyframes actHuGlow{ 0%,100%{ box-shadow: 0 0 0 1px rgba(240,207,121,.35), 0 10px 22px rgba(179,38,30,.45), inset 0 1px 0 rgba(255,255,255,.28); } 50%{ box-shadow: 0 0 0 2px rgba(240,207,121,.7), 0 10px 30px rgba(240,120,60,.6), inset 0 1px 0 rgba(255,255,255,.28); } }
.act-kong{ background: linear-gradient(180deg, #4a4078 0%, #2a2448 100%); border-color: rgba(196,178,255,.5); }
.act-kong .act-zh{ color:#e6dcff; }
.act-pong{ background: linear-gradient(180deg, #2a735c 0%, #144236 100%); border-color: rgba(150,226,190,.5); }
.act-pong .act-zh{ color:#dcf5e8; }
.act-chi{ background: linear-gradient(180deg, #2f6580 0%, #173548 100%); border-color: rgba(150,205,235,.5); }
.act-chi .act-zh{ color:#def0fa; }
.act-pass{ padding:0 18px; background: linear-gradient(180deg, #3b3733 0%, #211e1b 100%); border-color: rgba(255,255,255,.2); }
.act-pass .act-zh{ color:#e2d9c9; }
.act-timer{ position:relative; width:46px; height:46px; flex:none; margin-right:2px; }
.act-timer svg{ width:100%; height:100%; transform: rotate(-90deg); }
.act-timer .tr-bg{ fill:none; stroke: rgba(255,255,255,.12); stroke-width:3; }
.act-timer .tr-fg{ fill:none; stroke:#f0cf79; stroke-width:3; stroke-linecap:round; stroke-dasharray:100; stroke-dashoffset:0; transition: stroke-dashoffset .2s linear, stroke .2s; }
.act-timer b{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font:800 15px Manrope, sans-serif; color:#f3e6c4; font-variant-numeric: tabular-nums; }
.act-timer.urgent .tr-fg{ stroke:#e8553f; }
.act-timer.urgent b{ color:#ff9a88; }
@media (max-width:700px){
  .act-tray{ gap:6px; padding:8px; max-width: calc(100vw / var(--zoom, 1) - 16px); flex-wrap:wrap; justify-content:center; }
  .act{ height:54px; padding:0 12px 0 8px; gap:7px; }
  .act-zh{ font-size:24px; }
  .act-en{ display:none; }
}
@media (prefers-reduced-motion: reduce){ .act-tray, .act-hu{ animation:none; } }

/* ================= REMATCH PANEL ================= */
.rm-panel{ margin-top:14px; padding:14px 16px 12px; border-radius:14px; background: rgba(0,0,0,.035); border:1px solid var(--line); text-align:left; }
.rm-panel.invited{ border-color: var(--gold); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 22%, transparent); animation: rmIn .3s ease-out; }
@keyframes rmIn{ from{ transform: scale(.98); opacity:.6; } to{ transform:none; opacity:1; } }
.rm-title{ display:flex; align-items:center; justify-content:space-between; gap:10px; font-weight:800; font-size:1rem; margin-bottom:10px; }
.rm-count{ font-size:.72rem; font-weight:800; letter-spacing:.06em; color: var(--ink-soft); background: var(--surface-2); border:1px solid var(--line); padding:3px 8px; border-radius:999px; white-space:nowrap; }
.rm-list{ display:flex; flex-direction:column; gap:6px; }
.rm-row{ display:flex; align-items:center; gap:10px; padding:6px 10px 6px 6px; border-radius:10px; background: var(--surface-2); border:1px solid var(--line); }
.rm-row.ready{ border-color: color-mix(in srgb, var(--jade) 55%, transparent); background: color-mix(in srgb, var(--jade) 10%, var(--surface-2)); }
.rm-av{ width:30px; height:30px; border-radius:50%; flex:none; display:flex; align-items:center; justify-content:center; font-weight:800; font-size:.8rem; color:#fff; overflow:hidden; }
.rm-av img{ width:100%; height:100%; object-fit:cover; }
.rm-name{ flex:1; min-width:0; font-weight:700; font-size:.9rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rm-name i{ font-style:normal; color: var(--ink-soft); font-weight:600; }
.rm-dealer{ display:inline-flex; align-items:center; justify-content:center; width:18px; height:18px; border-radius:3px; background:#b3261e; color:#fbf1de; font-family:"TileBrush",serif; font-size:12px; vertical-align:-3px; margin-left:4px; }
.rm-state{ font-size:.78rem; font-weight:800; color: var(--ink-soft); }
.rm-row.ready .rm-state{ color: var(--jade); }
.rm-note{ margin:10px 0 2px; font-size:.84rem; color: var(--ink-soft); text-align:center; }
.rm-note b{ color: var(--ink); }
.rm-east{ font-weight:800; color:#b3261e; }
.rm-warn{ margin-top:8px; font-size:.74rem; color: var(--ink-soft); text-align:center; }
.rm-pulse{ animation: rmPulse 1.2s ease-in-out infinite; }
@keyframes rmPulse{ 0%,100%{ box-shadow: 0 0 0 0 rgba(179,38,30,.45); } 50%{ box-shadow: 0 0 0 7px rgba(179,38,30,0); } }
@media (prefers-reduced-motion: reduce){ .rm-pulse, .rm-panel.invited{ animation:none; } }

/* ================= 聽 WAITING HINT ================= */
.wait-box{ margin-top:6px; padding:8px 10px; border-radius:12px; background: rgba(0,0,0,.28); border:1px solid rgba(240,207,121,.45); max-width:190px; animation: waitIn .25s ease-out; }
@keyframes waitIn{ from{ opacity:0; transform: translateY(4px); } to{ opacity:1; transform:none; } }
.wait-title{ display:flex; align-items:center; gap:6px; font-size:.72rem; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color: rgba(243,236,217,.75); margin-bottom:6px; }
.wait-title b{ font-family:"TileBrush","TileBrushKai",serif; font-weight:400; font-size:1.2rem; letter-spacing:0; color:#f0cf79; text-transform:none; }
.wait-tiles{ display:flex; flex-wrap:wrap; gap:6px; }
.wait-t{ position:relative; display:flex; flex-direction:column; align-items:center; }
.wait-t b{ margin-top:2px; font:800 .7rem Manrope, sans-serif; color:#f3e6c4; font-variant-numeric: tabular-nums; }
.wait-t.sd-only .tile{ outline:1px dashed rgba(240,207,121,.8); outline-offset:1px; }
.wait-t.gone{ opacity:.4; }
.wait-t.gone b{ color:#ff9a88; }
/* tiles you can throw and still be one away */
.my-hand .tile.keeps-ready::after{
  content:""; position:absolute; top:-9px; left:50%; width:7px; height:7px; margin-left:-3.5px; border-radius:50%;
  background:#f0cf79; box-shadow: 0 0 6px rgba(240,207,121,.9); pointer-events:none; z-index:3;
}

/* ================= FRIENDLY EFFECTS ================= */
.fx-layer{ position:fixed; inset:0; pointer-events:none; z-index:120; overflow:hidden; }
.fx{ position:absolute; transform: translate(-50%, -50%); }
/* newest discard drops onto the felt */
.tile.t-table.drop-in{ animation: tileDrop .32s cubic-bezier(.2,.9,.3,1.25); }
@keyframes tileDrop{ 0%{ transform: translateY(-18px) scale(1.25); opacity:0; } 60%{ opacity:1; } 100%{ transform:none; opacity:1; } }
/* call burst: 碰 / 吃 / 槓 at the caller's seat */
.fx-call span{
  display:flex; align-items:center; justify-content:center; width:96px; height:96px; border-radius:50%;
  font-family:"TileBrush","TileBrushKai",serif; font-size:60px; color:#fff6dc;
  background: radial-gradient(circle at 40% 35%, #d0402f, #8e1a13 70%); border:3px solid #f0cf79;
  box-shadow: 0 0 0 6px rgba(240,207,121,.25), 0 14px 30px rgba(0,0,0,.45);
  animation: callPop 1.25s cubic-bezier(.2,.9,.3,1.2) forwards;
}
@keyframes callPop{ 0%{ transform: scale(.2) rotate(-12deg); opacity:0; } 18%{ transform: scale(1.15) rotate(3deg); opacity:1; } 30%{ transform: scale(1) rotate(0); } 75%{ transform: scale(1); opacity:1; } 100%{ transform: scale(.85) translateY(-14px); opacity:0; } }
/* win: gold burst + confetti */
.fx-win{ display:flex; align-items:center; justify-content:center; }
.fx-win span{
  position:relative; font-family:"TileBrush","TileBrushKai",serif; font-size:132px; line-height:1; color:#ffe7a6;
  text-shadow: 0 0 22px rgba(255,200,90,.9), 0 4px 0 #8e1a13, 0 10px 30px rgba(0,0,0,.5);
  animation: winPop 2.1s cubic-bezier(.2,.9,.3,1.2) forwards;
}
.fx-ring{ position:absolute; width:160px; height:160px; border-radius:50%; border:4px solid #f0cf79; left:50%; top:50%; margin:-80px 0 0 -80px; animation: winRing 1.2s ease-out forwards; }
@keyframes winPop{ 0%{ transform: scale(.3); opacity:0; } 15%{ transform: scale(1.18); opacity:1; } 28%{ transform: scale(1); } 80%{ opacity:1; } 100%{ transform: scale(1.05) translateY(-20px); opacity:0; } }
@keyframes winRing{ 0%{ transform: scale(.4); opacity:.9; } 100%{ transform: scale(3.2); opacity:0; } }
.fx-confetti i{ position:absolute; left:0; top:0; width:9px; height:14px; border-radius:2px; opacity:0; animation: confetti 1.9s cubic-bezier(.15,.7,.3,1) var(--d) forwards; }
@keyframes confetti{ 0%{ transform: translate(0,0) rotate(0); opacity:1; } 70%{ opacity:1; } 100%{ transform: translate(var(--dx), calc(var(--dy) + 220px)) rotate(var(--rot)); opacity:0; } }
/* emoji reactions float up from a player's plate */
.fx-react span{ display:block; font-size:44px; filter: drop-shadow(0 4px 8px rgba(0,0,0,.35)); animation: reactUp 2.3s ease-out forwards; }
.fx-react.still span{ animation: reactStill 2.3s linear forwards; }
@keyframes reactUp{ 0%{ transform: translateY(10px) scale(.4); opacity:0; } 15%{ transform: translateY(-10px) scale(1.2); opacity:1; } 30%{ transform: translateY(-20px) scale(1); } 80%{ opacity:1; } 100%{ transform: translateY(-110px) scale(.9); opacity:0; } }
@keyframes reactStill{ 0%, 85%{ opacity:1; } 100%{ opacity:0; } }
/* friendlier panel entrances */
#roundEndCard{ animation: cardIn .35s cubic-bezier(.2,.9,.3,1.15); }
@keyframes cardIn{ from{ transform: translateY(18px) scale(.97); opacity:0; } to{ transform:none; opacity:1; } }
.plate.active{ animation: plateGlow 1.8s ease-in-out infinite; }
@keyframes plateGlow{ 0%,100%{ filter: none; } 50%{ filter: drop-shadow(0 0 8px rgba(240,207,121,.55)); } }
@media (prefers-reduced-motion: reduce){
  .tile.t-table.drop-in, #roundEndCard, .plate.active, .wait-box{ animation:none !important; }
}
/* sound + reaction buttons sit beside chat and mic */
.fab-sound{ left:142px; background:#2c3a4a; font-size:1.2rem; }
.fab-sound.off{ background:#4a4038; opacity:.85; }
.fab-react{ left:204px; background:#4a3a2c; font-size:1.25rem; }
.react-tray{
  position:fixed; left:18px; bottom: calc(80px + env(safe-area-inset-bottom,0px)); z-index:45;
  display:flex; gap:6px; padding:8px 10px; border-radius:16px; background: rgba(12,16,14,.88); border:1px solid rgba(240,207,121,.4);
  box-shadow: 0 12px 30px rgba(0,0,0,.45); animation: waitIn .18s ease-out;
}
.react-tray button{ font-size:26px; width:44px; height:44px; border-radius:12px; border:none; background:transparent; cursor:pointer; transition: transform .12s, background .12s; }
.react-tray button:hover{ transform: translateY(-3px) scale(1.12); background: rgba(255,255,255,.08); }

/* ================= LEADERBOARD ================= */
.lb-card{ background: var(--surface); border:1px solid var(--line); border-radius:16px; padding:16px 18px; box-shadow: var(--shadow); }
.lb-head{ display:flex; align-items:baseline; justify-content:space-between; gap:10px; flex-wrap:wrap; margin-bottom:10px; }
.lb-head h3{ margin:0; font-size:1.15rem; }
.lb-head span{ font-size:.75rem; color: var(--ink-soft); }
.lb-body{ display:flex; flex-direction:column; gap:4px; overflow-x:auto; }
.lb-row{ display:grid; grid-template-columns: 34px minmax(120px,1fr) 92px 58px 58px 58px; align-items:center; gap:8px; padding:7px 8px; border-radius:10px; font-size:.88rem; min-width:440px; }
.lb-row:not(.lb-th):nth-child(even){ background: var(--surface-2); }
.lb-row.me{ outline:2px solid color-mix(in srgb, var(--gold) 60%, transparent); }
.lb-th{ font-size:.68rem; font-weight:800; letter-spacing:.08em; text-transform:uppercase; color: var(--ink-soft); }
.lb-row span:nth-child(n+3){ text-align:right; font-variant-numeric: tabular-nums; }
.lb-rank{ font-weight:800; text-align:center; }
.lb-name{ display:flex; align-items:center; gap:8px; font-weight:700; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.lb-av{ width:26px; height:26px; border-radius:50%; flex:none; background:#8a8074; color:#fff; display:inline-flex; align-items:center; justify-content:center; font-size:.72rem; font-weight:800; overflow:hidden; }
.lb-av img{ width:100%; height:100%; object-fit:cover; }
.lb-net{ font-weight:800; }
.lb-net.pos{ color: var(--jade); } .lb-net.neg{ color: var(--lacquer); }
.lb-empty{ padding:14px; text-align:center; color: var(--ink-soft); font-size:.88rem; }

/* =====================================================================
   PHONES IN LANDSCAPE (short screens)
   Everything tightens up so the felt gets the room: a slim top bar (the
   round/dealer chips are already on the dial and name plates), one row of
   hand tiles that always fits, compact plates, a smaller dial, and the
   round buttons tucked into the bottom-right corner.
   ===================================================================== */
@media (max-height: 500px) and (orientation: landscape){
  .topbar{ padding:3px 10px !important; gap:8px; min-height:0; }
  .topbar .title h1{ font-size:.95rem; }
  .topbar .title .sub{ display:none; }
  body.in-game #topChips{ display:none; }
  .topbar .chip, .topbar .icon-btn, .topbar .btn-logout{ padding:3px 9px; font-size:.72rem; }
  .solo-bar{ padding:2px 10px !important; font-size:.72rem; gap:6px; }
  .solo-bar .solo-seat-btn{ padding:1px 9px; font-size:.7rem; }

  .my-area{ padding:3px 8px calc(3px + env(safe-area-inset-bottom,0px)) !important; }
  .my-area-landscape{ grid-template-columns: 132px minmax(0,1fr) 72px !important; gap:6px !important; align-items:center; }
  .my-plate .plate{ width:132px !important; min-height:0; padding:5px 7px; gap:6px; }
  .my-plate .pl-av{ width:28px; height:28px; font-size:.75rem; }
  .my-plate .pl-name{ font-size:11px; }
  .my-plate .pl-meta{ font-size:10px; gap:4px; }
  .my-plate .pl-dealer{ display:none; }
  .my-hand{ flex-wrap:nowrap !important; gap:2px; min-height:0; padding:4px 0 0; }
  .my-hand .tile{
    --tw: clamp(22px, calc((100vw - 250px) / 15), 36px); --th: calc(var(--tw) * 1.36);
    font-size: calc(var(--tw) * .58);
  }
  .my-hand .tile.just-drawn{ margin-left:6px; }
  .act-hint{ display:none; }
  .wait-box{ padding:4px 6px; max-width:72px; }
  .wait-title{ font-size:0; margin-bottom:2px; } .wait-title b{ font-size:.95rem; }

  .act-tray{ gap:5px; padding:6px; bottom:calc(100% + 6px); }
  .act{ height:46px; padding:0 10px 0 6px; gap:6px; }
  .act-zh{ font-size:22px; } .act-en{ display:none; }
  .act-timer{ width:36px; height:36px; }

  .console{ width:92px !important; height:92px !important; }
  .console .c-ring{ inset:22px !important; } .console .c-core{ inset:26px !important; }
  .console .c-core b{ font-size:20px !important; } .console .c-core span{ display:none; }
  .console .c-wind{ font-size:14px !important; width:20px !important; height:20px !important; }
  .console .c-wind.s{ bottom:2px; } .console .c-wind.w{ left:2px; } .console .c-wind.e{ right:2px; }
  .console .c-seal{ width:11px; height:11px; font-size:8px; }
  .console .c-seal.s{ left:calc(50% + 11px); bottom:6px; } .console .c-seal.w{ left:7px; top:calc(50% + 11px); } .console .c-seal.e{ right:7px; top:calc(50% - 22px); }
  .console .c-emblem{ inset:-80px; }
  .tilesleft b{ font-size:15px; } .tilesleft span{ font-size:8px; }
  .arena .turn-banner{ display:none; }

  body.in-game .fab{ width:36px; height:36px; font-size:.95rem; left:auto; bottom: calc(var(--dock-h, 70px) + 6px); opacity:.92; }
  body.in-game #chatToggle{ right:8px; }
  body.in-game .fab-voice{ right:50px; }
  body.in-game .fab-sound{ right:92px; }
  body.in-game .fab-react{ right:134px; }
  body.in-game .react-tray{ left:auto; right:8px; bottom: calc(var(--dock-h, 70px) + 50px); }
  body.in-game .drawer{ bottom: calc(var(--dock-h, 70px) + 50px); height: min(70vh, 300px); }
  .fx-call span{ width:64px; height:64px; font-size:40px; }
  .fx-win span{ font-size:84px; }
}
/* narrow phones in portrait: keep the lobby usable */
@media (max-width: 520px){
  .topbar{ flex-wrap:wrap; row-gap:6px; }
  .topbar .title .sub{ display:none; }
  .topbar > div:last-child{ flex-wrap:wrap; justify-content:flex-end; }
  .lb-row{ grid-template-columns: 30px minmax(100px,1fr) 84px 50px; min-width:0; }
  .lb-row span:nth-child(5), .lb-row span:nth-child(6){ display:none; }
}
@media (max-height: 500px) and (orientation: landscape){
  .felt-arena.placards-compact .placard{ width:auto; top:6px; }
  .felt-arena.placards-compact .plate{ width:176px; min-height:0; padding:3px 8px 3px 4px; gap:6px; border-radius:9px; }
  .felt-arena.placards-compact .pl-av{ width:24px; height:24px; font-size:.7rem; }
  .felt-arena.placards-compact .pl-name{ font-size:10.5px; }
  .felt-arena.placards-compact .pl-meta{ font-size:9.5px; gap:4px; }
  .felt-arena.placards-compact .pl-wind i, .felt-arena.placards-compact .pl-dealer i{ width:14px; height:14px; font-size:10px; }
  .felt-arena.placards-compact .placard-stats{ display:none; }
  .felt-arena.placards-compact .pl-stat{ font-size:9.5px; }
  .felt-arena.placards-compact .pl-stat b{ font-size:10.5px; }
}

/* ---------- invite link (table seat picker) ---------- */
.invite-strip{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin:8px 0 2px; padding:11px 13px;
  background: color-mix(in srgb, var(--gold) 16%, var(--surface)); border:1px dashed color-mix(in srgb, var(--gold) 70%, transparent); border-radius:12px; }
.invite-lbl{ font-weight:800; font-size:.82rem; color: var(--gold-ink); }
.invite-link{ flex:1 1 240px; min-width:0; font:600 .8rem ui-monospace, "SF Mono", Menlo, Consolas, monospace; color: var(--ink-soft);
  background: var(--surface); border:1px solid var(--line); border-radius:8px; padding:8px 10px; text-overflow:ellipsis; }
.invite-btn{ border:0; border-radius:8px; padding:8px 13px; font-weight:800; font-size:.8rem; cursor:pointer; color:#fff; }
.invite-btn.copy{ background: var(--felt); color:#f1e7cf; }
.invite-btn.share{ background: var(--lacquer); }
.invite-warn{ flex-basis:100%; margin:0 !important; font-size:.78rem; color: var(--lacquer) !important; }

/* ---------- install bar (table list, phones) ---------- */
.install-bar{ display:flex; align-items:center; gap:12px; background: var(--surface); border:1px solid var(--line); border-radius:14px; padding:10px 12px; box-shadow: var(--shadow); }
.install-ic{ width:40px; height:40px; border-radius:10px; flex:none; }
.install-txt{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:1px; }
.install-txt b{ font-size:.92rem; }
.install-txt span{ font-size:.78rem; color: var(--ink-soft); }
.install-go{ padding:8px 14px; border-radius:9px; font-size:.82rem; }
.install-x{ border:0; background:none; font-size:1.3rem; line-height:1; color: var(--ink-soft); cursor:pointer; padding:4px 6px; }

/* ---------- voice: relayed through the server ---------- */
.vp-relay{ font-size:.8em; opacity:.75; }

/* ---------- admin ---------- */
.btn-admin{ background: var(--felt) !important; color:#f1e7cf !important; border-color: var(--felt) !important; }
.admin-screen{ flex:1 1 auto; overflow-y:auto; margin:14px; display:flex; flex-direction:column; gap:14px; max-width:1100px; width:calc(100% - 28px); align-self:center; }
.adm-head{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.adm-head h2{ font-size:1.5rem; margin:0; flex:1 1 auto; }
.adm-tabs{ display:flex; gap:3px; background: var(--surface-2); border:1px solid var(--line); border-radius:11px; padding:3px; flex-wrap:wrap; }
.adm-tabs button{ border:0; background:none; padding:6px 12px; border-radius:8px; font:700 .82rem "Manrope", sans-serif; color: var(--ink-soft); cursor:pointer; }
.adm-tabs button.on{ background: var(--surface); color: var(--ink); box-shadow:0 1px 3px rgba(0,0,0,.1); }
.adm-stats{ display:grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap:10px; }
.adm-stat{ background: var(--surface); border:1px solid var(--line); border-radius:12px; padding:10px 14px; }
.adm-stat small{ display:block; color: var(--ink-soft); font-weight:800; font-size:.68rem; letter-spacing:.1em; text-transform:uppercase; }
.adm-stat b{ font:700 1.45rem "Fraunces", Georgia, serif; font-variant-numeric: tabular-nums; }
.adm-card{ background: var(--surface); border:1px solid var(--line); border-radius:16px; padding:12px 16px; box-shadow: var(--shadow); }
.adm-tbl-wrap{ overflow-x:auto; }
.adm-tbl{ width:100%; border-collapse:collapse; font-variant-numeric: tabular-nums; font-size:.88rem; min-width:640px; }
.adm-tbl th{ text-align:left; font-size:.68rem; letter-spacing:.1em; text-transform:uppercase; color: var(--ink-soft); padding:6px 10px; border-bottom:1px solid var(--line); }
.adm-tbl td{ padding:9px 10px; border-bottom:1px solid var(--line); vertical-align:middle; white-space:nowrap; }
.adm-tbl tr:last-child td{ border-bottom:0; }
.adm-tbl tr.locked td{ opacity:.6; }
.adm-tbl .num{ text-align:right; }
.adm-tbl .neg{ color: var(--lacquer); }
.adm-who{ display:flex; align-items:center; gap:9px; }
.adm-who small{ display:block; color: var(--ink-soft); font-size:.74rem; }
.adm-un{ color: var(--ink-soft); font-size:.78rem; }
.adm-av{ position:relative; width:30px; height:30px; border-radius:50%; background:#8a7f72; color:#fff; display:inline-flex; align-items:center; justify-content:center; font-weight:800; font-size:.8rem; flex:none; }
.adm-av img{ width:100%; height:100%; border-radius:50%; object-fit:cover; }
.adm-av i{ position:absolute; right:-1px; bottom:-1px; width:10px; height:10px; border-radius:50%; border:2px solid var(--surface); background:#9a9a9a; }
.adm-av i.on{ background:#1f9d55; }
.adm-tag{ font-size:.62rem; font-weight:800; letter-spacing:.08em; text-transform:uppercase; border-radius:6px; padding:2px 6px; background: var(--gold); color:#2a1f0c; margin-left:6px; vertical-align:2px; }
.adm-tag.lock{ background: var(--lacquer); color:#fff; }
.adm-acts{ display:flex; gap:6px; justify-content:flex-end; align-items:center; }
.adm-btn{ border:1px solid var(--line); background: var(--surface-2); color: var(--ink); border-radius:9px; padding:8px 14px; font:800 .82rem "Manrope", sans-serif; cursor:pointer; }
.adm-btn:hover{ border-color: var(--gold); }
.adm-btn.sm{ padding:5px 10px; font-size:.76rem; border-radius:8px; }
.adm-btn.felt{ background: var(--felt); color:#f1e7cf; border-color: var(--felt); }
.adm-btn.red{ background: var(--lacquer); color:#fff; border-color: var(--lacquer); }
.adm-btn:disabled{ opacity:.6; cursor:default; }
.adm-more{ padding:4px 10px !important; font-size:.9rem !important; line-height:1; }
.adm-menu{ display:flex; flex-direction:column; gap:6px; margin-bottom:12px; }
.adm-menu button{ border:1px solid var(--line); background: var(--surface-2); text-align:left; padding:10px 12px; border-radius:9px; font:700 .86rem "Manrope", sans-serif; color: var(--ink); cursor:pointer; }
.adm-menu button:hover{ border-color: var(--gold); }
.adm-menu button.danger{ color: var(--lacquer); }
.adm-tables{ display:grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap:12px; }
.adm-ltable{ background: var(--surface); border:1px solid var(--line); border-radius:14px; padding:12px 14px; box-shadow: var(--shadow); }
.adm-ltable header{ display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.adm-ltable header b{ font:700 1rem "Fraunces", Georgia, serif; flex:1; }
.adm-pill{ font-size:.72rem; font-weight:800; border-radius:999px; padding:3px 9px; background: color-mix(in srgb, #1f9d55 18%, var(--surface)); color: color-mix(in srgb, #1f9d55 70%, var(--ink)); white-space:nowrap; }
.adm-pill.wait{ background: color-mix(in srgb, var(--gold) 24%, var(--surface)); color: var(--gold-ink); }
.adm-lseat{ display:flex; align-items:center; gap:8px; padding:6px 0; border-top:1px dashed var(--line); font-size:.88rem; }
.adm-lseat span{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; }
.adm-lseat span.open{ color: var(--ink-soft); }
.adm-lseat em{ font-style:normal; font-size:.74rem; color: var(--lacquer); font-weight:700; }
.adm-lfoot{ display:flex; gap:6px; margin-top:8px; }
.adm-note{ color: var(--ink-soft); font-size:.82rem; line-height:1.5; margin:10px 2px 0; max-width:80ch; }
.adm-voice{ max-width:560px; }
.adm-voice h3{ margin:0; font-size:1.05rem; }
.adm-voice .adm-note{ margin:4px 0 12px; }
.adm-field{ display:flex; flex-direction:column; gap:4px; margin-bottom:10px; }
.adm-field label{ font-weight:700; font-size:.8rem; }
.adm-field input, .adm-field select{ font:500 .88rem "Manrope", sans-serif; padding:8px 10px; border:1px solid var(--line); border-radius:8px; background: var(--surface-2); color: var(--ink); }
.adm-right{ display:flex; gap:8px; justify-content:flex-end; }
.adm-msg{ font-size:.82rem; min-height:1.2em; margin:0 0 8px; color: var(--ink-soft); }
.adm-msg.ok{ color:#1f7a45; }
.adm-msg.err, .adm-err{ color: var(--lacquer); font-size:.82rem; }
.adm-err{ min-height:1.1em; margin-bottom:6px; }
.adm-log > div{ padding:8px 0; border-top:1px dashed var(--line); font-size:.88rem; }
.adm-log > div:first-child{ border-top:0; }
.adm-log time{ color: var(--ink-soft); font-size:.78rem; margin-right:10px; font-variant-numeric: tabular-nums; }
.adm-by{ color: var(--ink-soft); font-size:.78rem; }
.adm-empty{ color: var(--ink-soft); padding:18px 4px; }
.adm-modal{ max-width:380px; }
.adm-modal h3{ margin:0 0 4px; font:700 1.15rem "Fraunces", Georgia, serif; color: var(--ink); }
.adm-modal p{ margin:0 0 12px; }
.adm-seg{ display:flex; gap:4px; margin-bottom:10px; }
.adm-seg button{ flex:1; border:1px solid var(--line); background: var(--surface-2); color: var(--ink); border-radius:8px; padding:7px; font:800 .8rem "Manrope", sans-serif; cursor:pointer; }
.adm-seg button.on{ background: var(--felt); color:#f1e7cf; border-color: var(--felt); }
.adm-preview{ font-size:.88rem; color: var(--ink) !important; }
.adm-temp{ font:700 1.2rem ui-monospace, "SF Mono", Menlo, Consolas, monospace; letter-spacing:.06em; text-align:center; padding:12px; margin-bottom:12px; border-radius:10px;
  background: color-mix(in srgb, var(--gold) 16%, var(--surface)); border:1px dashed color-mix(in srgb, var(--gold) 70%, transparent); user-select:all; word-break:break-all; }
@media (max-width:700px){
  .adm-stats{ grid-template-columns: repeat(2, minmax(0,1fr)); }
  .admin-screen{ margin:10px; width:calc(100% - 20px); }
}
.invite-warn{ max-width:none !important; }
.adm-newtab{ font-size:.8rem; font-weight:700; color: var(--jade); text-decoration:none; }
.adm-newtab:hover{ text-decoration:underline; }
.adm-site{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; background: var(--surface); border:1px solid var(--line); border-radius:12px; padding:10px 14px; font-size:.88rem; }
.adm-site:empty{ display:none; }
.adm-site-lbl{ font-weight:800; font-size:.68rem; letter-spacing:.1em; text-transform:uppercase; color: var(--ink-soft); }
.adm-site a{ font:700 .88rem ui-monospace, "SF Mono", Menlo, Consolas, monospace; color: var(--jade); word-break:break-all; }
.adm-site-none{ color: var(--ink-soft); }

/* ---------- screen sizes ----------
   In a game the top bar stays one line on a laptop: the tagline goes, and
   the less important chips hide when space is short. */
body.in-game .topbar{ flex-wrap:nowrap; }
body.in-game .topbar .title span.sub{ display:none; }
body.in-game .topbar .title h1{ white-space:nowrap; }
body.in-game .chips{ flex-wrap:nowrap; min-width:0; overflow:hidden; }
body.in-game .chip{ white-space:nowrap; }
@media (max-width:1500px){ body.in-game .chip.minor{ display:none; } }
.confirm-btns{ display:flex; gap:10px; justify-content:center; flex-wrap:wrap; margin-top:6px; }
#confirmBackdrop{ z-index:60; }

/* ================= UPRIGHT PHONE LAYOUT =================
   body.portrait-play (set by client.js for upright phones/small tablets
   during a hand): opponents side by side on top, the table's centre line,
   your flowers, melds and discards, then your hand in two rows. */
body.portrait-play #tableScreen{ display:none !important; }
body.portrait-play #topChips{ display:none; }
body.portrait-play .topbar{ padding:4px 10px !important; padding-top: calc(4px + env(safe-area-inset-top, 0px)) !important; }
body.portrait-play .topbar .title h1{ font-size:1rem; }
.pboard{ flex:1 1 auto; min-height:0; overflow-y:auto; display:flex; flex-direction:column; gap:8px; padding:8px 8px 52px; color:#f3ecd9;
  background: radial-gradient(ellipse 120% 80% at 50% 45%, #1d5241 0%, var(--felt) 55%, var(--felt-2) 100%); }
.pboard[hidden]{ display:none !important; }
.pb-opps{ display:grid; grid-template-columns: 1fr 1fr; gap:8px; }
.pb-opp, .pb-mine{ --tu: 21px; display:flex; flex-direction:column; gap:6px; padding:8px; border-radius:12px; min-width:0;
  background: rgba(0,0,0,.2); border:1px solid rgba(255,255,255,.07); transition: box-shadow .25s ease, border-color .25s ease; }
.pb-opp.active, .pb-mine.active{ border-color: rgba(240,207,121,.8); box-shadow: 0 0 0 2px rgba(240,207,121,.25), 0 0 18px rgba(240,207,121,.18); }
.pb-id{ display:flex; align-items:center; gap:7px; min-width:0; }
.pb-av{ width:30px; height:30px; border-radius:50%; flex:none; display:flex; align-items:center; justify-content:center; font-weight:800; font-size:.8rem; color:#fff; overflow:hidden; box-shadow: 0 0 0 2px rgba(201,162,74,.7); }
.pb-av img{ width:100%; height:100%; object-fit:cover; }
.pb-idt{ display:flex; flex-direction:column; min-width:0; line-height:1.2; }
.pb-idt b{ font-size:.82rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.pb-idt span{ font-size:.7rem; color: rgba(243,236,217,.72); display:flex; align-items:center; gap:4px; }
.pb-wind, .pb-deal{ font-style:normal; font-family:"TileBrush","TileBrushKai",serif; font-size:.85rem; color:#f0cf79; }
.pb-deal{ color:#ff8f7f; }
.pboard .zone-tray{ display:flex; align-items:center; gap:4px; min-height:0; padding:3px 4px; border-radius:8px; background: rgba(0,0,0,.18); transform:none !important; position:static !important; }
.pboard .zone-tray.empty .zone-flowers::before{ content:"No flowers"; font-size:.66rem; color: rgba(243,236,217,.5); }
.pboard .zone-flowers{ display:flex; flex-wrap:wrap; gap:2px; flex:1; min-width:0; }
.pboard .fan-seal{ flex:none; position:static !important; transform:none !important; }
.pboard .zone-melds{ display:flex; flex-wrap:wrap; gap:4px; transform:none !important; position:static !important; }
.pboard .zone-meld{ display:flex; gap:1px; padding:2px; border-radius:5px; background: rgba(255,255,255,.08); }
.pboard .zone-pond{ display:flex; flex-wrap:wrap; gap:2px; align-content:flex-start; min-height: calc(var(--tu) * 1.36); transform:none !important; position:static !important; width:auto !important; }
.pboard .tile.t-table{ margin:0 !important; }
.pb-opp .zone-pond{ --tu: 19px; }
.pb-center{ display:flex; align-items:center; gap:10px; padding:6px 10px; border-radius:12px; background: rgba(0,0,0,.28); border:1px solid rgba(201,162,74,.3); }
.pb-left{ display:flex; flex-direction:column; align-items:center; line-height:1; flex:none; }
.pb-left b{ font:700 1.3rem "Fraunces", Georgia, serif; color:#f0cf79; }
.pb-left span{ font-size:.58rem; letter-spacing:.12em; text-transform:uppercase; color: rgba(243,236,217,.7); margin-top:2px; }
.pb-turn{ flex:1; font-size:.78rem; line-height:1.3; min-width:0; }
.pb-turn b{ color:#f0cf79; }
.pb-round{ flex:none; font-size:.66rem; color: rgba(243,236,217,.65); text-align:right; max-width:70px; }
.pb-mine{ --tu: 24px; }
.pb-mine-top{ display:flex; flex-wrap:wrap; gap:6px; align-items:center; }
.pb-mine-top .zone-tray{ flex:0 1 auto; }

/* your hand: two rows of seven, big enough to tap */
body.portrait-play #myAreaScreen{ display:block !important; padding:6px 8px calc(8px + env(safe-area-inset-bottom, 0px)) !important; }
body.portrait-play .my-area-landscape{ display:flex !important; flex-direction:column; gap:6px !important; align-items:stretch; }
body.portrait-play .my-plate{ order:0; padding:4px 6px; }
body.portrait-play .my-plate .plate{ width:auto !important; min-height:0; padding:4px 8px; }
body.portrait-play .my-plate .pl-av{ width:26px; height:26px; font-size:.72rem; }
body.portrait-play .my-hand-dock{ order:1; }
body.portrait-play .my-hand{ flex-wrap:wrap !important; justify-content:center; gap:4px; padding:4px 0 0; min-height:0; max-width: calc(var(--ptw) * 7 + 30px); margin:0 auto; }
body.portrait-play{ --ptw: min(calc((100vw - 48px) / 7), 60px); }
body.portrait-play .my-hand .tile{ --tw: var(--ptw); --th: calc(var(--ptw) * 1.36); font-size: calc(var(--ptw) * .56); }
body.portrait-play .my-hand .tile.selectable:hover{ transform:none; }
body.portrait-play .my-hand .tile.just-drawn{ margin-left:0; }
body.portrait-play .action-bar{ order:2; max-width:none; justify-self:auto; justify-content:center; }
body.portrait-play .act-hint{ text-align:center; font-size:.72rem; }
body.portrait-play .act-tray{ position:fixed; left:50%; bottom: calc(var(--dock-h, 220px) + 10px); max-width: calc(100vw - 16px); flex-wrap:wrap; justify-content:center; gap:6px; padding:8px; }
body.portrait-play .act{ height:52px; padding:0 12px 0 6px; gap:6px; }
body.portrait-play .act-zh{ font-size:24px; } body.portrait-play .act-en{ display:none; }
body.portrait-play .wait-box{ max-width:none; margin:0 auto; }
body.portrait-play .fab{ width:36px; height:36px; font-size:.95rem; left:auto; bottom: calc(var(--dock-h, 220px) + 8px); opacity:.94; }
body.portrait-play #chatToggle{ right:8px; }
body.portrait-play .fab-voice{ right:50px; }
body.portrait-play .fab-sound{ right:92px; }
body.portrait-play .fab-react{ right:134px; }
body.portrait-play .react-tray{ left:auto; right:8px; bottom: calc(var(--dock-h, 220px) + 52px); }
body.portrait-play .drawer{ left:8px; right:8px; width:auto; bottom: calc(var(--dock-h, 220px) + 52px); height: min(50vh, 320px); }
body.portrait-play .voice-bar{ bottom: calc(var(--dock-h, 220px) + 52px); }
body.portrait-play .fx-call span{ width:64px; height:64px; font-size:40px; }
body.portrait-play .fx-win span{ font-size:80px; }
body.portrait-play .topbar .title{ display:none; }
body.portrait-play .topbar{ justify-content:flex-end; flex-wrap:nowrap; }
body.portrait-play .solo-bar{ flex-wrap:wrap; font-size:.72rem; padding:3px 8px !important; gap:5px; }

/* ================= HAND REPLAY ================= */
.replay-backdrop{ padding:16px; z-index:55; }
.replay{ width:min(1100px, 100%); max-height: calc(94vh / var(--zoom, 1)); display:flex; flex-direction:column; border-radius:18px; overflow:hidden;
  background: radial-gradient(ellipse 120% 90% at 50% 30%, #1d5241 0%, var(--felt) 55%, var(--felt-2) 100%); color:#f3ecd9;
  border:1px solid rgba(201,162,74,.45); box-shadow: 0 24px 60px rgba(0,0,0,.5); }
.rp-head{ display:flex; align-items:flex-start; gap:12px; padding:14px 18px 10px; border-bottom:1px solid rgba(255,255,255,.08); }
.rp-titles{ flex:1; min-width:0; }
.rp-head h2{ color:#f6ecd2; font-size:1.25rem; margin:0; }
.rp-head p{ margin:3px 0 0; color: rgba(243,236,217,.75); font-size:.86rem; }
.rp-x{ border:0; background: rgba(255,255,255,.08); color:#f3ecd9; width:34px; height:34px; border-radius:50%; font-size:1rem; cursor:pointer; flex:none; }
.rp-seats{ flex:1 1 auto; overflow-y:auto; padding:12px 14px; display:flex; flex-direction:column; gap:10px; }
.rp-seat{ padding:10px 12px; border-radius:12px; background: rgba(0,0,0,.22); border:1px solid rgba(255,255,255,.07); display:flex; flex-direction:column; gap:8px; transition: border-color .2s ease, box-shadow .2s ease; }
.rp-seat.turn{ border-color: rgba(240,207,121,.75); box-shadow: 0 0 0 2px rgba(240,207,121,.2); }
.rp-seat.won{ border-color:#f0cf79; box-shadow: 0 0 0 2px rgba(240,207,121,.35), 0 0 24px rgba(240,207,121,.2); }
.rp-who{ display:flex; align-items:center; gap:8px; font-size:.9rem; }
.rp-av{ width:26px; height:26px; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; color:#fff; font-weight:800; font-size:.75rem; box-shadow: 0 0 0 2px rgba(201,162,74,.6); }
.rp-wind, .rp-deal{ font-style:normal; font-family:"TileBrush","TileBrushKai",serif; color:#f0cf79; font-size:1rem; }
.rp-deal{ color:#ff8f7f; }
.rp-won{ margin-left:4px; padding:2px 8px; border-radius:999px; background: var(--lacquer); color:#fff; font-size:.72rem; font-weight:800; }
.rp-row{ display:flex; flex-wrap:wrap; gap:10px; align-items:flex-end; }
.rp-hand{ display:flex; flex-wrap:wrap; gap:2px; }
.rp-hand .tile.just-drawn{ margin-left:8px; box-shadow: 0 0 0 2px #f0cf79, 0 4px 10px rgba(0,0,0,.35); }
.rp-melds, .rp-bonus{ display:flex; flex-wrap:wrap; gap:6px; align-items:flex-end; padding:3px 5px; border-radius:8px; background: rgba(255,255,255,.07); }
.rp-meld{ display:flex; gap:1px; }
.rp-bonus{ gap:2px; background: rgba(90,56,26,.45); }
.rp-pond{ display:flex; flex-wrap:wrap; gap:2px; min-height:26px; align-items:center; }
.rp-pond .tile.latest{ box-shadow: 0 0 0 2px #f0cf79, 0 0 10px rgba(240,207,121,.6); }
.rp-pond .tile.claimed{ opacity:.4; }
.rp-none{ font-size:.75rem; color: rgba(243,236,217,.45); }
.rp-foot{ padding:10px 14px calc(12px + env(safe-area-inset-bottom, 0px)); border-top:1px solid rgba(255,255,255,.08); background: rgba(0,0,0,.25); display:flex; flex-direction:column; gap:8px; }
.rp-caption{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; min-height:1.5em; }
.rp-step{ font-size:.72rem; letter-spacing:.06em; text-transform:uppercase; color: rgba(243,236,217,.6); }
.rp-caption b{ font-size:1rem; color:#f6ecd2; }
.rp-controls{ display:flex; align-items:center; gap:6px; }
.rp-btn{ border:1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.08); color:#f3ecd9; min-width:38px; height:38px; border-radius:10px; font-size:1.05rem; cursor:pointer; }
.rp-btn:hover{ border-color:#c9a24a; }
.rp-play{ background: var(--lacquer); border-color: var(--lacquer); min-width:48px; }
.rp-speed{ font-size:.8rem; font-weight:800; }
.rp-slider{ flex:1; min-width:60px; accent-color:#c9a24a; }
.rp-open{ margin-top:10px; border:0; border-radius:9px; padding:8px 14px; background: var(--lacquer); color:#fff; font-weight:800; font-size:.82rem; cursor:pointer; }
@media (max-width:600px){
  .replay-backdrop{ padding:0; }
  .replay{ max-height:none; height: calc(100dvh / var(--zoom, 1)); border-radius:0; }
  .rp-seats{ padding:8px; gap:8px; }
  .rp-seat{ padding:8px; }
  .rp-hand .tile.small{ --tw:22px; --th:30px; font-size:.66rem; }
  .rp-btn{ min-width:34px; height:36px; }
}
.rp-lbl{ font-size:.62rem; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color: rgba(243,236,217,.5); margin-right:6px; }
.rp-pond .tile.small{ --tw:24px; --th:32px; font-size:.7rem; }
@media (max-width:600px){ .rp-pond .tile.small{ --tw:19px; --th:26px; font-size:.56rem; } .rp-lbl{ flex-basis:100%; margin-bottom:2px; } }
