/*! popcorn_arcade — style.css: the whole page's CSS, extracted verbatim from index.html's
    <style> block. Bump the ?v= on the <link> in index.html when this file changes. */
  /* Replay layer. The Android-browser player does NOT reparent the game canvas into
     the dialog (Chrome renders a reparented canvas as a black layer — see
     mountReplayCanvas), so the canvas floats over the dialog as a sibling and its
     stacking has to be derived from the dialog's, not guessed. They were hard-coded
     independently once (dialog 85 / canvas 86); raising the dialog to sit above the
     match log then buried the video under the dialog's own placeholder box, and
     Android replays showed a dark rectangle.
     Layer order above the replay dialog, all of it deliberate:
       --z-replay      95  the dialog
       +1              96  the Android overlay canvas (the video itself)
       #frToasts/#fsHint  97  small chrome that sat above the canvas before and still must
       .sharecard     100  the 戰績卡, opened from inside the player
       #reloadOverlay 110  a deploy is landing — above everything, always */
  :root { --z-replay: 95; }
  /* gaming-style cursor: chunky gold arrow with a dark outline (hotspot at the tip) */
  :root { --game-cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cpath d='M5 3 L5 24 L11 18 L15 27 L19 25 L15 16 L23 16 Z' fill='%23ffd64a' stroke='%23142a3c' stroke-width='1.8' stroke-linejoin='round'/%3E%3C/svg%3E") 5 3, auto; }
  html, body {
    margin: 0; padding: 0; height: 100%; overflow: hidden;
    background: #000; touch-action: none;
    font-family: -apple-system, "Avenir Next", "Segoe UI", sans-serif;
}
.supporter-account-badge{display:inline-flex;align-items:center;gap:4px;margin-left:5px;padding:2px 7px 2px 3px;border-radius:999px;background:linear-gradient(135deg,#c2571a,#8f3a0c);color:#fff;text-shadow:0 1px 0 rgba(0,0,0,.35);font-size:12px;font-weight:900;box-shadow:0 1px 4px #71330f55}.supporter-account-badge img{width:20px;height:20px;object-fit:contain}.supporter-slot-mark{position:absolute;z-index:4;top:5px;right:5px;display:grid;place-items:center;width:24px;height:24px;border-radius:50%;background:#fff2c7e8;box-shadow:0 2px 7px #71330f55;pointer-events:none}.supporter-slot-mark span{display:none}.supporter-slot-mark img{width:20px;height:20px;object-fit:contain}@media(max-width:820px){.supporter-account-badge{flex:none;margin-left:0;padding:2px}.supporter-account-badge span{display:none}.supporter-account-badge img{width:19px;height:19px}}
  /* one consistent cursor across the whole game — never switch to a hand/caret on hover */
  * { cursor: var(--game-cursor) !important; }
  /* ===== selection: the interface is not content =====
     A drag across the lobby while waiting should not paint every label blue. Only the
     text a player might genuinely want to copy opts back in: chat logs, the board
     (announcements / messages / wishes), private messages, and every text field.
     Canvas-drawn text is never selectable to begin with. */
  body { -webkit-user-select: none; user-select: none; }
  input, textarea, [contenteditable="true"],
  .chat-log, .board-list, .fr-dmlog, #gameChatLog, #sysAnnounceText {
    -webkit-user-select: text; user-select: text; }
  #game { display: block; width: 100vw; height: 100vh; filter: saturate(1.18) contrast(1.06); }
  /* mobile: 100vh is the LARGEST viewport (URL bar hidden) — dvh tracks the real one */
  @supports (height: 100dvh) { #game { width: 100dvw; height: 100dvh; } }
  /* page-transition cover: fade to black, switch while hidden, fade back in */
  #fade { position: fixed; inset: 0; background: #000; z-index: 9999; opacity: 0; pointer-events: none; transition: opacity 0.24s ease; }
  #fade.on { opacity: 1; pointer-events: auto; }

  /* ===== arcade-style lobby ===== */
  #lobby {
    position: fixed; inset: 0; z-index: 20; display: none;
    align-items: stretch; justify-content: stretch; box-sizing: border-box;
    background:
      radial-gradient(120% 90% at 50% -10%, #6fd3f4 0%, #2ea6e0 45%, #1d7fc4 100%);
  }
  /* Use the visible viewport, not the browser's historical 100vh value. This also
     matters on desktop when browser chrome, a PWA title bar, or an OS taskbar
     changes the actual space available to the lobby. */
  @supports (height: 100dvh) { #lobby { height: 100dvh; } }
  #lobby.show { display: flex; }
  .arc-screen {
    width: 100%; height: 100%;
    background: linear-gradient(#39b6ea, #1f8fd0);
    display: flex; flex-direction: column; color: #fff; overflow: hidden;
  }
  .arc-screen.hidden { display: none; }

  .arc-header {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    flex-wrap: wrap; row-gap: 6px;   /* narrow landscape phones: buttons wrap, never spill off-screen */
    padding: 12px 16px;
    background: linear-gradient(#1c7cc0, #1a6fb0); border-bottom: 3px solid #6fc6ee;
  }
  .arc-title {
    font-size: clamp(18px, 3.2vmin, 28px); font-weight: 900; letter-spacing: 1px;
    text-shadow: 0 2px 0 #15598f; flex: 1; text-align: center;
  }
  .arc-title #roomCode { color: #ffe14d; letter-spacing: 4px; }

  .pill {
    font-family: inherit; font-weight: 800; color: #fff; cursor: pointer;
    border: 3px solid rgba(255,255,255,0.85); border-radius: 999px;
    padding: 10px 18px; font-size: clamp(13px, 2vmin, 17px);
    background: linear-gradient(#3aa6e6, #1f82c8);
    box-shadow: 0 3px 0 rgba(0,0,0,0.18), inset 0 2px 0 rgba(255,255,255,0.35);
    transition: transform .05s;
  }
  .pill:active { transform: translateY(2px); }
  .pill.yellow { background: linear-gradient(#ffd84a, #f5a31b); color: #6b3b00; text-shadow: 0 1px 0 #ffe9a8; border-color: #fff3c9; }
  .pill.green  { background: linear-gradient(#6fdc6f, #2faa4a); }
  .pill.blue   { background: linear-gradient(#5cc3f2, #2e8fd6); }
  .pill.ghost  { background: linear-gradient(#86a9bd, #5d8299); }
  .pill:disabled { opacity: 0.45; cursor: default; box-shadow: none; }
  /* waiting for the server after Create / Quick / Join / Start (netBusyLock in js/net.js) */
  .pill.is-busy { position: relative; opacity: 0.7; cursor: progress; }
  .pill.is-busy::before { content: ''; position: absolute; top: 50%; right: 10px; width: 14px; height: 14px; margin-top: -7px;
    border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; animation: pill-busy .8s linear infinite; }
  @keyframes pill-busy { to { transform: rotate(360deg); } }
  @media (prefers-reduced-motion: reduce) { .pill.is-busy::before { animation: none; } }
  /* shared/client/conn-status.js ping pill: its default bottom-left spot covers the build stamp
     and the phone's stop button — lift it into the free strip above them */
  body .pcs-rtt { bottom: calc(70px + env(safe-area-inset-bottom)); }
  .pill.big { width: 100%; padding: clamp(10px, 1.8vh, 16px); font-size: clamp(17px, 2.6vmin, 26px); }

  .arc-toolbar { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 12px 16px; flex-wrap: wrap; }
  .arc-toolbar input, .panel input {
    box-sizing: border-box; padding: 11px 14px; border-radius: 12px;
    border: 3px solid #cfeaf8; background: #e9f7ff; color: #134d77;
    font-size: 16px; font-weight: 700; outline: none; min-width: 0;
  }
  #nameInput { width: 180px; }

  /* ===== Channel: focused lobby, dark-glass over the scenic background ===== */
  /* 2026-09-17: 樂園廣場 (codex 產, art_source/lobby/); 直向另一張同場景的 9:16 母圖 */
  #lobbyList { color: #3d3020; position: relative;
    background: linear-gradient(rgba(255,250,238,0.04), rgba(60,40,20,0.24) 88%), url("assets/scenes/lobby_bg_wide.webp?v=1") center 60% / cover no-repeat; }
  @media (orientation: portrait) {
    #lobbyList { background-image: linear-gradient(rgba(255,250,238,0.02), rgba(60,40,20,0.28) 90%), url("assets/scenes/lobby_bg_tall.webp?v=1"); background-position: center top; }
  }
  /* the cards ride above the ambient float layer */
  #lobbyList .ch-top, #lobbyList .ch-stage, #lobbyList .ch-dock { position: relative; z-index: 1; }

  /* ambient dressing: popcorn / sparkles drifting at the screen edges. Kept OUT of
     the 1280px content column so they never sit under a card on wide screens. */
  .ch-float { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
  /* longhand on purpose: a `background:` shorthand here would out-specific the
     per-item background-image below and reset it to none */
  .ch-float .pf { position: absolute; display: block; background-position: center; background-size: contain; background-repeat: no-repeat; opacity: 0.9;
    filter: drop-shadow(0 5px 9px rgba(90,70,40,0.20)); animation: pfFloat 8s ease-in-out infinite alternate; }
  .pf1 { left: 2.5%; top: 17%;  width: clamp(34px, 4.5vw, 62px); aspect-ratio: 1; background-image: url("assets/scenes/lobby_pop1.webp?v=1"); animation-duration: 8.5s; }
  .pf2 { left: 5%;   top: 58%;  width: clamp(26px, 3.4vw, 46px); aspect-ratio: 1; background-image: url("assets/scenes/lobby_pop2.webp?v=1"); animation-duration: 10s; animation-delay: -3.5s; }
  .pf3 { left: 1.5%; top: 82%;  width: clamp(20px, 2.4vw, 34px); aspect-ratio: 1; background-image: url("assets/scenes/lobby_star.webp?v=1"); animation-duration: 7s; animation-delay: -1.6s; }
  .pf4 { right: 2%;  top: 22%;  width: clamp(30px, 4vw, 56px);  aspect-ratio: 1; background-image: url("assets/scenes/lobby_pop3.webp?v=1"); animation-duration: 9.5s; animation-delay: -5s; }
  .pf5 { right: 4.5%; top: 64%; width: clamp(22px, 2.8vw, 40px); aspect-ratio: 1; background-image: url("assets/scenes/lobby_pop1.webp?v=1"); animation-duration: 11s; animation-delay: -7.2s; }
  .pf6 { right: 1.5%; top: 44%; width: clamp(18px, 2.2vw, 30px); aspect-ratio: 1; background-image: url("assets/scenes/lobby_star.webp?v=1"); animation-duration: 7.8s; animation-delay: -2.8s; }
  @keyframes pfFloat { from { transform: translateY(-11px) rotate(-8deg); } to { transform: translateY(13px) rotate(9deg); } }
  @media (prefers-reduced-motion: reduce) { .ch-float .pf, .ch-play::after { animation: none !important; } }
  .ch-glass { background: rgba(255,252,244,0.88); border: 1.5px solid rgba(150,115,55,0.22);
    border-radius: 20px; box-shadow: 0 10px 34px rgba(90,70,40,0.16), inset 0 1px 0 rgba(255,255,255,0.14); backdrop-filter: blur(9px); -webkit-backdrop-filter: blur(9px); }

  .ch-top { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px clamp(14px, 3vw, 34px); }
  .ch-logo { display:block; width:auto; height:clamp(40px,5.5vh,58px); max-width:32vw; object-fit:contain;
    filter:drop-shadow(0 3px 5px rgba(90,45,10,.22)); }
  .ch-top-right { display: flex; align-items: center; gap: 8px; }
  .iconbtn { display: inline-flex; align-items: center; justify-content: center; gap: 5px; min-width: 38px; height: 38px; padding: 0 12px;
    font-family: inherit; font-weight: 800; font-size: 13px; color: #6b5327; cursor: pointer;
    background: rgba(255,255,255,0.55); border: 1.5px solid rgba(150,115,55,0.24); border-radius: 11px; }
  .iconbtn:hover { background: rgba(255,255,255,0.9); color: #3a2c12; }
  .iconbtn svg { display: block; }
  #lobbyList .acctchip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border-radius: 999px;
    background: rgba(255,255,255,0.78); border: 1.5px solid rgba(150,115,55,0.26); color: #3d3020; }
  #lobbyList .acctchip .acct-name { color: #3a2c12; font-weight: 800; }
  #lobbyList .acctchip .acct-rating { color: #b8790f; font-weight: 800; }
  #lobbyList .acct-edit { background: rgba(255,255,255,0.9); color: #3d3020; }
  #lobbyList .acct-edit:hover { background: rgba(255,255,255,1); }

  .ch-stage { flex: 1; min-height: 0; display: flex; flex-direction: row; gap: clamp(12px, 1.6vw, 22px);
    width: 100%; max-width: 1280px; margin: 0 auto; padding: 2px clamp(14px, 3vw, 34px) 6px; box-sizing: border-box; }
  .ch-main { flex: 2; min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: clamp(12px, 2vh, 22px); }
  /* always-open side column: lobby chat (top) + message board (bottom) */
  .ch-side { flex: 1; min-width: 260px; max-width: 380px; min-height: 0; display: flex; flex-direction: column; gap: clamp(10px, 1.6vh, 16px); }
  .ch-panel { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 8px; padding: 12px 14px;
    background: linear-gradient(rgba(255,253,247,0.90), rgba(255,248,232,0.84)); border: 2px solid rgba(184,121,15,0.24); border-radius: 18px;
    box-shadow: 0 10px 30px rgba(90,70,40,0.16), 0 2px 0 rgba(184,121,15,0.14), inset 0 2px 0 rgba(255,255,255,0.5); backdrop-filter: blur(9px); -webkit-backdrop-filter: blur(9px); }
  .ch-panel-title { flex: none; display: flex; align-items: center; gap: 7px; font-weight: 900; font-size: clamp(13px, 1.6vmin, 15px); color: #6b5327; letter-spacing: 0.5px; }
  /* little gold ticket-stub marker in front of every section title */
  .ch-panel-title::before, .ch-rooms-head > span::before { content: ''; display: inline-block; width: 9px; height: 9px; border-radius: 3px;
    background: linear-gradient(#ffd84a, #f5a91b); box-shadow: 0 0 0 3px rgba(245,169,27,0.20); transform: rotate(45deg); }
  .ch-rooms-head > span { display: inline-flex; align-items: center; gap: 8px; }
  .ch-panel .chat-log, .ch-panel .board-list { flex: 1; min-height: 0; overflow-y: auto; color: #6b5327; }
  .ch-panel .chat-row, .ch-panel .board-row { flex: none; display: flex; gap: 6px; }
  .ch-panel .chat-row input, .ch-panel .board-row input { flex: 1; min-width: 0; padding: 8px 12px; border-radius: 999px;
    border: 1.5px solid rgba(150,115,55,0.28); background: rgba(255,255,255,0.78); color: #3a2c12; font-size: 13px; font-weight: 600; outline: none; }
  .ch-panel .chat-row .pill, .ch-panel .board-row .pill { flex: none; padding: 8px 14px; }
  .ch-panel .board-tabs { flex: none; display: flex; gap: 6px; }
  .ch-panel .board-tab { flex: 1; padding: 6px 8px; border-radius: 999px; border: 1.5px solid rgba(150,115,55,0.28); background: rgba(255,255,255,0.55);
    color: #6b5327; font-weight: 900; font-size: 12.5px; cursor: pointer; }
  .ch-panel .board-tab.on { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; }
  /* ===== chat tabs: 大家聊天 / 私訊 =====
     The DM pane replaces the log AND the send row inside the same panel, so the two
     conversations never overlap and the panel never changes size. The unread pip rides
     on the tab, which is why a message arriving while you read the room chat is still
     visible without covering a single line of it. */
  .chat-tabs { flex: none; display: flex; gap: 6px; margin: 0 0 6px; }
  .chat-tab { flex: 1; padding: 6px 8px; border-radius: 999px; border: 1.5px solid rgba(150,115,55,0.28);
    background: rgba(255,255,255,0.55); color: #6b5327; font-weight: 900; font-size: 12.5px; cursor: pointer;
    position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
  .chat-tab.on { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; }
  .chat-tab .tab-pip { display: inline-grid; place-items: center; min-width: 17px; height: 17px; padding: 0 4px;
    border-radius: 999px; background: #e5484d; color: #fff; font-size: 10.5px; font-weight: 1000; line-height: 1; }
  .chat-dm { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; }
  /* the room panel's tabs sit in its head strip, beside the mascot */
  .chat-head .chat-tabs { margin: 0 0 0 auto; max-width: 62%; }
  .ch-panel .board-item { display: flex; align-items: flex-start; gap: 7px; background: rgba(255,255,255,0.6); border: 1.5px solid rgba(150,115,55,0.20); border-radius: 12px; padding: 6px 8px; margin-bottom: 5px; }
  .ch-panel .board-item .bmain { flex: 1; min-width: 0; }
  .ch-panel .board-item .bwho { font-size: 11px; font-weight: 800; color: #b8790f; display: flex; align-items: baseline; gap: 6px; }
  /* 留言時間: pushed to the far edge of the name line so the names still align */
  .ch-panel .board-item .btime { margin-left: auto; flex: none; font-size: 10px; font-weight: 600; color: #a08a63; font-variant-numeric: tabular-nums; }
  .ch-panel .board-item .btext { font-size: 13px; color: #3d3020; word-break: break-word; line-height: 1.35; }
  .ch-panel .board-heart { flex: none; display: flex; align-items: center; gap: 3px; background: none; border: 0; cursor: pointer; color: #a89a7c; font-weight: 900; font-size: 12px; padding: 2px; }
  .ch-panel .board-heart.on { color: #f2557a; }
  .ch-panel .board-empty, .ch-panel .chat-log .csys { color: #93805f; font-size: 12.5px; font-style: italic; }
  .ch-panel .chat-log .cwho { color: #b8790f; }
  .ch-social-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
  .ch-social-actions button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 34px;
    border: 1.5px solid rgba(150,115,55,.24); border-radius: 11px; background: rgba(255,255,255,.62);
    color: #6b5327; font: 800 12px/1 inherit; cursor: pointer; transition: transform .16s ease, background .16s ease, border-color .16s ease; }
  .ch-social-actions button:hover { transform: translateY(-1px); background: #fff; border-color: #d59b22; color: #3a2c12; }

  /* the play button carries a slow sheen sweep — the one moving highlight on the card */
  .ch-play { position: relative; overflow: hidden; }
  .ch-play::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
    background: linear-gradient(115deg, transparent 32%, rgba(255,255,255,0.55) 46%, rgba(255,255,255,0.2) 52%, transparent 64%);
    background-size: 260% 100%; animation: chSheen 3.4s ease-in-out infinite; }
  @keyframes chSheen { 0% { background-position: 120% 0; } 55% { background-position: -60% 0; } 100% { background-position: -60% 0; } }
  .ch-count { position: relative; font-weight: 800; font-size: clamp(12px, 1.5vmin, 14px); color: #8a651d; min-height: 18px; text-align: center; }
  .ch-count.empty { display: none; }
  .ch-count .hs-title { color: #b8790f; } .ch-count .hs-hint { color: #93805f; font-weight: 700; font-size: 0.9em; margin-top: 2px; }
  /* above the mascots' z-index 3: art may never end up on top of a button */
  .ch-cta { position: relative; z-index: 4; display: flex; flex-direction: column; align-items: stretch; gap: 8px; width: min(460px, 94%); box-sizing: border-box;
    padding: 10px; border: 1.5px solid rgba(150,115,55,.20); border-radius: 18px; background: rgba(255,255,255,.48); box-shadow: inset 0 1px 0 #fff8; }
  .pill.gold { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; border-color: #ffedb0;
    text-shadow: 0 1px 0 rgba(255,255,255,0.4); box-shadow: 0 6px 20px rgba(245,169,27,0.45), inset 0 2px 0 rgba(255,255,255,0.45); }
  #quickBtn.ch-play { display: inline-flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 52px; letter-spacing: 1px; font-size: 18px; }
  .ch-play svg { margin-top: -1px; }
  .ch-secondary-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .ch-secondary-row .pill { min-height: 42px; box-shadow: none; }
  .ch-join-row { display: grid; grid-template-columns: minmax(0,1fr) auto; gap: 8px; padding-top: 8px; border-top: 1px solid rgba(150,115,55,.18); }
  .ch-join-row #codeInput { min-width: 0; box-sizing: border-box; padding: 10px 14px; border-radius: 12px; text-align: center;
    border: 1.5px solid rgba(150,115,55,0.30); background: rgba(255,255,255,0.78); color: #3a2c12; font-size: 15px; font-weight: 800; outline: none; }
  .ch-join-row #codeInput:focus { border-color: #e3a51e; box-shadow: 0 0 0 3px rgba(245,169,27,.14); }
  .ch-join-row #codeInput::placeholder { color: rgba(110,85,45,0.5); }
  .ch-join-row #joinCodeBtn { min-width: 82px; background: #fff; color: #6b5327; border-color: rgba(150,115,55,.32); box-shadow: none; }
  .ch-tutor { display: inline-flex; align-items: center; justify-content: center; gap: 7px; align-self: center; min-height: 34px; padding: 6px 12px; border: 0; background: transparent; color: #806a43; box-shadow: none; font-size: 12px; }
  .ch-tutor.big { order: -1; align-self: stretch; min-height: 42px; border: 1.5px solid #efbd37; background: rgba(255,231,154,.48); color: #6b4a00; font-size: 14px; box-shadow: none; }
  .ch-tutor:not(.big)::before { content: '✓'; display: grid; place-items: center; width: 18px; height: 18px; border-radius: 50%; background: #5dbb70; color: #fff; font-size: 11px; font-weight: 900; }
  .ch-tutor:not(.big) svg { display: none; }
  /* follow-us strip under the hero CTA — IG-gradient badge, arcade-card body */
  .ig-cta { position: relative; display: flex; align-items: center; gap: 10px; width: min(460px, 94%); box-sizing: border-box;
    padding: 7px 10px; border-radius: 13px; text-decoration: none; cursor: pointer;
    background: transparent; border: 1px solid transparent;
    box-shadow: none; transition: transform 0.12s, box-shadow 0.12s, border-color 0.12s; }
  .ig-cta:hover { transform: translateY(-1px); border-color: #e1306c; box-shadow: 0 7px 20px rgba(225,48,108,0.22); }
  .ig-cta:active { transform: translateY(1px); }
  .ig-badge { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 10px; color: #fff;
    background: linear-gradient(45deg, #f9ce34, #ee2a7b 55%, #6228d7); box-shadow: 0 2px 8px rgba(238,42,123,0.35); }
  .ig-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
  /* font scales with the viewport so the handle never clips on a 320px phone */
  .ig-txt b { font-size: clamp(11px, 3.1vw, 13.5px); font-weight: 900; color: #3a2c12; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .ig-txt i { font-size: clamp(9.5px, 2.6vw, 11.5px); font-style: normal; font-weight: 700; color: #93805f; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .ig-go { flex: none; color: #b8790f; }

  /* rooms */
  .ch-rooms { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 12px 14px;
    background: linear-gradient(rgba(255,253,247,0.90), rgba(255,248,232,0.84)); border: 2px solid rgba(184,121,15,0.24); border-radius: 20px;
    box-shadow: 0 10px 30px rgba(90,70,40,0.16), 0 2px 0 rgba(184,121,15,0.14), inset 0 2px 0 rgba(255,255,255,0.5); backdrop-filter: blur(9px); -webkit-backdrop-filter: blur(9px); }
  .ch-rooms-head { flex: none; display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;
    font-weight: 900; font-size: clamp(13px, 1.6vmin, 16px); color: #6b5327; letter-spacing: 0.5px; }
  /* 線上人數 chip: 跟同一列的 .iconbtn 用同一組淺色 token, 不要把遊戲內 HUD 的
     深色搬進大廳。綠點會呼吸 —— 這是唯一會動的元素, 所以「現在」這件事不用寫字。
     只有數字: 誰在線上的名字在好友清單裡 (點下去就是那裡)。 */
  .online-chip { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; margin-right: 8px;
    height: 38px; padding: 0 13px; cursor: pointer; font-family: inherit; font-weight: 800; font-size: 13px;
    color: #6b5327; background: rgba(255,255,255,0.55); border: 1.5px solid rgba(150,115,55,0.24); border-radius: 11px;
    white-space: nowrap; }
  .online-chip[hidden] { display: none; }
  .online-chip:hover { background: rgba(255,255,255,0.9); color: #3a2c12; }
  .online-chip:active { transform: translateY(1px); }
  .online-chip svg { display: block; flex: none; }
  .online-chip .oc-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: #35c15f;
    box-shadow: 0 0 0 0 rgba(53,193,95,0.6); animation: ocPulse 2.4s ease-out infinite; }
  .online-chip .oc-friends { color: #2f8f4e; }
  @keyframes ocPulse { 0% { box-shadow: 0 0 0 0 rgba(53,193,95,0.55); }
    70% { box-shadow: 0 0 0 6px rgba(53,193,95,0); } 100% { box-shadow: 0 0 0 0 rgba(53,193,95,0); } }
  @media (prefers-reduced-motion: reduce) { .online-chip .oc-dot { animation: none; box-shadow: none; } }
  /* 窄螢幕: 標題那一列要塞三個東西, chip 先丟掉圖示只留數字 */
  @media (max-width: 720px) {
    .online-chip { height: 34px; padding: 0 10px; gap: 5px; margin-right: 6px; font-size: 12px; }
    .online-chip svg { display: none; }
  }
  .room-grid { flex: 1; min-height: 0; overflow-y: auto; display: grid; gap: 10px; padding-right: 2px; align-content: start;
    grid-template-columns: repeat(auto-fill, minmax(clamp(150px, 22vw, 210px), 1fr)); }
  .room-card { display: flex; flex-direction: column; gap: 7px; padding: 9px; cursor: pointer;
    background: rgba(255,255,255,0.55); border: 1.5px solid rgba(150,115,55,0.22); border-radius: 15px; transition: transform .08s, border-color .08s; }
  .room-card:hover { border-color: #b8790f; transform: translateY(-2px); }
  .room-card .thumb { width: 100%; height: clamp(64px, 10vh, 96px); border-radius: 11px; border: 1.5px solid rgba(150,115,55,0.22); background-size: cover; background-position: center; }
  .room-card .info { text-align: left; min-width: 0; }
  .room-card .rname { font-weight: 900; font-size: 14px; color: #3a2c12; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .room-card .rmeta { font-size: 11px; color: #93805f; margin-top: 2px; display: flex; align-items: center; gap: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .room-card .rjoin { font-size: 12px; font-weight: 900; text-align: center; padding: 6px; border-radius: 9px; }
  .rjoin.waiting { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; }
  .rjoin.playing { background: rgba(255,120,120,0.18); color: #b03030; border: 1px solid rgba(200,80,80,0.45); }
  .room-card .rwatch { display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 5px; border-radius: 9px;
    background: rgba(255,255,255,0.78); border: 1.5px solid rgba(150,115,55,0.26); color: #6b5327; font-weight: 800; font-size: 12px; cursor: pointer; }
  .room-card .rwatch:hover { background: rgba(255,255,255,0.95); }
  .room-empty { grid-column: 1 / -1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 20px 10px; color: #93805f; font-weight: 700; text-align: center; }
  .room-empty b { color: #6b5327; font-size: 15px; }
  .room-empty span { max-width: 360px; font-size: 12px; line-height: 1.45; }
  /* empty list gets the popcorn bucket instead of a bare sentence */
  .room-empty::before { content: ''; width: clamp(110px, 17vh, 164px); aspect-ratio: 0.96;
    background: url("assets/ui/lobby-empty-park-v2.webp") center / contain no-repeat;
    filter: drop-shadow(0 6px 12px rgba(90,70,40,0.22)); }

  /* A desktop browser often has only 650–850 CSS px of usable height. The hero
     used to keep its full natural height and leave the flexible room panel with
     less than one card, so overflow clipped every recommendation halfway through.
     Reserve one complete card row and compact secondary chrome first. If an
     unusually short window still cannot hold both sections, the main column is
     the scroll owner; individual room cards are never used as the clipping point. */
  /* The announcement board stays in the lobby. Chat alone is moved into its
     overlay on demand. */
  #lobbyList .ch-side > .ch-chat { display: none !important; }

  @media (min-width: 821px) {
    .ch-rooms { min-height: 188px; }
    /* No rooms means no room container: expose the carnival instead of preserving
       an empty dashboard card. The section returns on the next rooms update. */
    .ch-rooms.is-empty { display: none; }
    .ch-side { flex: 0 0 clamp(260px, 22vw, 310px); }
    .ch-side > .ch-friends { flex: none; }
    .ch-side > .ch-board { display: flex; flex: 1 1 300px; min-height: 260px; }
  }
  @media (min-width: 821px) and (max-height: 900px) {
    .ch-top { padding-block: 7px; }
    .ch-logo { height: clamp(36px, 5.5vh, 46px); }
    .ch-stage { gap: 10px; padding-top: 0; }
    .ch-main { gap: 10px; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; padding: 12px 8px 12px 0; margin-top: -12px; }
    .ch-count { min-height: 14px; }
    .ch-count .hs-hint { display: none; }
    .ch-cta { gap: 5px; padding: 7px; }
    #quickBtn.ch-play { min-height: 42px; font-size: 16px; }
    .ch-secondary-row .pill { min-height: 36px; padding-block: 7px; }
    .ch-join-row { padding-top: 5px; }
    .ch-join-row #codeInput { padding-block: 7px; }
    .ch-join-row #joinCodeBtn { padding-block: 7px; }
    .ch-tutor { min-height: 27px; padding-block: 3px; }
    .ig-cta { padding-block: 4px; }
    .ig-badge { width: 27px; height: 27px; border-radius: 8px; }
    .ig-badge svg { width: 16px; height: 16px; }
    .ig-txt i { display: none; }
    .ch-rooms { flex: 0 0 auto; height: 190px; box-sizing: border-box; padding: 9px 11px; border-radius: 17px; }
    /* Width is plentiful in desktop landscape, so use it instead of sacrificing
       the bottom half of a portrait card. The optional Watch action simply adds
       a third compact row beside the thumbnail. */
    .room-card { display: grid; grid-template-columns: minmax(70px, 38%) minmax(0, 1fr); grid-template-rows: auto auto auto;
      align-items: center; column-gap: 8px; row-gap: 4px; min-height: 84px; padding: 7px; }
    .room-card .thumb { grid-column: 1; grid-row: 1 / -1; align-self: stretch; height: auto; min-height: 78px; }
    .room-card .info, .room-card .rjoin, .room-card .rwatch { grid-column: 2; }
    .room-card .rjoin, .room-card .rwatch { padding-block: 4px; }
    .ch-dock { padding-block: 6px 8px; }
    .dock-btn { flex-direction: row; justify-content: center; width: clamp(102px, 11vw, 132px); padding: 6px 10px; border-radius: 14px; }
    .dock-btn .dicon { width: 32px; height: 32px; border-radius: 10px; }
  }

  /* bottom dock: game-style tiles — each button owns a color identity so the row
     reads as four distinct destinations rather than four grey pills */
  .ch-dock { flex: none; display: flex; align-items: center; justify-content: center; gap: clamp(8px, 1.5vw, 16px); padding: 10px clamp(14px, 3vw, 34px) 14px; flex-wrap: wrap; }
  .dock-btn { position: relative; display: flex; flex-direction: column; align-items: center; gap: 5px; width: clamp(72px, 9.5vw, 94px); padding: 9px 6px 8px;
    background: linear-gradient(rgba(255,253,247,0.94), rgba(255,247,230,0.90)); border: 2px solid rgba(184,121,15,0.26); border-radius: 18px; color: #6b5327; cursor: pointer;
    box-shadow: 0 6px 18px rgba(90,70,40,0.14), 0 2px 0 rgba(184,121,15,0.16), inset 0 1px 0 rgba(255,255,255,0.5); transition: transform .08s, border-color .08s, box-shadow .08s; }
  .dock-btn:hover { transform: translateY(-3px); border-color: #b8790f; color: #3a2c12; box-shadow: 0 10px 24px rgba(90,70,40,0.20), 0 2px 0 rgba(184,121,15,0.16); }
  .dock-btn .dicon { display: flex; align-items: center; justify-content: center; width: 38px; height: 38px; border-radius: 12px; color: #fff;
    box-shadow: inset 0 2px 0 rgba(255,255,255,0.4), 0 3px 8px rgba(90,70,40,0.22); }
  .dock-tasks   .dicon { background: linear-gradient(#5cc3f2, #2e8fd6); }
  .dock-ach     .dicon { background: linear-gradient(#ffd84a, #f5a91b); }
  .dock-friends .dicon { background: linear-gradient(#6fdc6f, #2faa4a); }
  .dock-shop    .dicon { background: linear-gradient(#ff9ec1, #f2557a); }
  .dock-btn .dlabel { font-weight: 800; font-size: clamp(11px, 1.3vmin, 13px); line-height: 1; }
  .dock-btn .qdot { position: absolute; top: 5px; right: 8px; min-width: 18px; height: 18px; padding: 0 4px; border-radius: 999px;
    background: #e74c3c; border: 2px solid #fff; color: #3a2c12; font-size: 11px; font-weight: 900;
    display: flex; align-items: center; justify-content: center; }

  /* phones: everything stacks into ONE scrollable column — the fixed-height
     desktop split cannot fit a portrait screen, so the stage itself scrolls
     and each section takes a bounded natural height. (These sit AFTER the
     channel base rules on purpose: equal-specificity overrides need the
     later position in the cascade.) */
  @media (max-width: 820px) {
    .ch-top { flex-wrap: wrap; row-gap: 6px; padding: 8px 12px; }
    .ch-top-right { flex-wrap: wrap; justify-content: flex-end; row-gap: 6px; min-width: 0; }
    #lobbyList .acctchip { min-width: 0; }
    #lobbyList .acctchip .acct-name { max-width: 90px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .ch-stage { flex-direction: column; overflow-y: auto; -webkit-overflow-scrolling: touch;
      padding-bottom: 92px; }   /* content scrolls clear of the fixed bottom nav */
    .ch-main { flex: none; }
    .ch-rooms { flex: none; min-height: 150px; }
    .room-grid { max-height: 40vh; }
    .ch-side { max-width: none; min-width: 0; flex: none; flex-direction: column; }
    .ch-side .ch-panel { flex: none; height: min(300px, 42vh); }
    /* phones: the dock becomes an app-style bottom navigation bar — fixed, blurred
       cream, gold hairline. It covers the "powered by" footer while the channel is
       open, which is fine: the footer still shows on the login page (no dock). */
    .ch-dock { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; flex-wrap: nowrap; gap: 6px;
      padding: 7px 10px calc(7px + env(safe-area-inset-bottom));
      background: linear-gradient(rgba(255,253,247,0.94), rgba(255,247,230,0.97));
      backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
      border-top: 2px solid rgba(184,121,15,0.28); box-shadow: 0 -8px 24px rgba(90,70,40,0.18); }
    .dock-btn { flex: 1; width: auto; min-width: 0; padding: 5px 2px 4px; gap: 3px;
      background: none; border: none; box-shadow: none; border-radius: 12px; }
    .dock-btn:hover { transform: none; box-shadow: none; }
    .dock-btn .dicon { width: 34px; height: 34px; }
    .dock-btn .dlabel { font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
    .dock-btn .qdot { top: 0; right: calc(50% - 26px); }
    .ch-cta { width: 100%; }
    .ig-cta { width: 100%; }
    /* ambient floaters thin out on phones: two per side, clear of the cards */
    .pf2, .pf5 { display: none; }
    /* the fixed bottom nav owns that strip of screen — the "powered by" pill
       (z 80, above the nav on purpose for every other scene) steps aside while
       the channel is open */
    body:has(#lobby.show) #bpFooter { display: none; }
  }
  /* short landscape phones (wide but low): the tall hero can't fit the height —
     compact it and let the main column scroll under the always-visible dock */
  @media (min-width: 821px) and (max-height: 500px) {
    .ch-main { overflow-y: auto; -webkit-overflow-scrolling: touch; }
    .ch-hero .pill.big { padding: 8px; font-size: 16px; }
    #quickBtn.ch-play { min-height: 42px; }
    .ch-cta { gap: 5px; padding: 7px; }
    .ch-tutor { min-height: 28px; padding: 3px 9px; }
    .ch-main > * { flex: none; }
    .ch-main .ch-rooms { min-height: 140px; }
    /* the follow strip drops its subtitle so the compacted hero keeps its height */
    .ig-cta { padding: 5px 10px; }
    .ig-badge { width: 26px; height: 26px; border-radius: 8px; }
    .ig-badge svg { width: 16px; height: 16px; }
    .ig-txt i { display: none; }
  }

  /* channel overlays (chat + board) */
  .ch-overlay { position: fixed; inset: 0; z-index: 32; display: none; align-items: center; justify-content: center; padding: 16px;
    background: rgba(70,55,30,0.35); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
  .ch-overlay.show { display: flex; }
  .ch-ovbox { width: min(94vw, 520px); max-height: 82vh; display: flex; flex-direction: column; gap: 10px; padding: 16px;
    background: rgba(255,252,244,0.97); border: 1.5px solid rgba(150,115,55,0.24); border-radius: 20px; box-shadow: 0 18px 50px rgba(90,70,40,0.25); }
  .ch-ovhead { flex: none; display: flex; align-items: center; gap: 10px; }
  .ch-ovtitle { flex: 1; font-weight: 900; font-size: 19px; color: #3a2c12; }
  .ch-ovbox .chat-log { flex: 1; min-height: 200px; overflow-y: auto; color: #6b5327; }
  .ch-ovbox .chat-row { flex: none; display: flex; gap: 6px; }
  .ch-ovbox .chat-row input { flex: 1; min-width: 0; padding: 9px 14px; border-radius: 999px; border: 1.5px solid rgba(150,115,55,0.28);
    background: rgba(255,255,255,0.78); color: #3a2c12; font-size: 14px; font-weight: 600; outline: none; }
  .ch-ovbox .board-tabs { flex: 1; display: flex; gap: 6px; }
  .ch-ovbox .board-tab { flex: 1; padding: 7px 8px; border-radius: 999px; border: 1.5px solid rgba(150,115,55,0.28); background: rgba(255,255,255,0.55);
    color: #6b5327; font-weight: 900; font-size: 13px; cursor: pointer; }
  .ch-ovbox .board-tab.on { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; }
  .ch-ovbox .board-list { flex: 1; min-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; padding-right: 2px; }
  .ch-ovbox .board-item { display: flex; align-items: flex-start; gap: 7px; background: rgba(255,255,255,0.6); border: 1.5px solid rgba(150,115,55,0.20); border-radius: 12px; padding: 7px 9px; }
  .ch-ovbox .board-item .bmain { flex: 1; min-width: 0; }
  .ch-ovbox .board-item .bwho { font-size: 11px; font-weight: 800; color: #b8790f; }
  .ch-ovbox .board-item .btext { font-size: 14px; color: #3d3020; word-break: break-word; line-height: 1.35; }
  .ch-ovbox .board-heart { flex: none; display: flex; align-items: center; gap: 3px; background: none; border: 0; cursor: pointer; color: #a89a7c; font-weight: 900; font-size: 12px; padding: 2px; }
  .ch-ovbox .board-heart.on { color: #f2557a; }
  .ch-ovbox .board-row { flex: none; display: flex; gap: 6px; }
  .ch-ovbox .board-row input { flex: 1; min-width: 0; padding: 9px 14px; border-radius: 999px; border: 1.5px solid rgba(150,115,55,0.28);
    background: rgba(255,255,255,0.78); color: #3a2c12; font-size: 14px; font-weight: 600; outline: none; }
  .ch-ovbox .board-empty { color: #93805f; font-size: 13px; font-style: italic; text-align: center; padding: 16px 0; }

  /* ===== Waiting room: same scenic theme, light cards ===== */
  #lobbyRoom { background: linear-gradient(rgba(255,250,238,0.06), rgba(60,40,20,0.22) 90%), url("assets/scenes/lobby_bg_wide.webp?v=1") center 60% / cover no-repeat; }
  @media (orientation: portrait) {
    #lobbyRoom { background-image: linear-gradient(rgba(255,250,238,0.02), rgba(60,40,20,0.28) 90%), url("assets/scenes/lobby_bg_tall.webp?v=1"); background-position: center top; }
  }
  #lobbyRoom .arc-header { background: transparent; border-bottom: 0; }
  #lobbyRoom .arc-title { color: #fff; text-shadow: 0 2px 6px rgba(20,77,119,0.5); }
  #lobbyRoom .arc-title #roomCode { color: #ffe14d; }
  #lobbyRoom .slot { background: rgba(255,255,255,0.93); border-color: #fff; color: #1c6aa3; box-shadow: 0 4px 0 rgba(0,0,0,0.1); }
  #lobbyRoom .slot.empty { background: rgba(255,255,255,0.5); color: #2c6488; border-color: rgba(255,255,255,0.8); }
  #lobbyRoom .slot .pname { color: #1c6aa3; }
  #lobbyRoom .tag.notready { background: rgba(20,77,119,0.14); color: #1c6aa3; }
  #lobbyRoom .side { background: rgba(255,255,255,0.93); border: 3px solid #fff; border-radius: 18px; padding: 12px 14px; box-shadow: 0 6px 16px rgba(20,77,119,0.2); }
  #lobbyRoom .panel-label { color: #1c6aa3; }
  /* room chatbox: a polished rounded card with a mascot, bubbles, rounded input */
  #lobbyRoom .chat { flex: 1 1 auto; min-height: 90px; background: rgba(255,255,255,0.95); border: 3px solid #fff; border-top: 3px solid #fff;
    border-radius: 18px; margin: 0; padding: 8px 14px 10px; gap: 4px;
    box-shadow: 0 6px 16px rgba(20,77,119,0.22); position: relative; }
  #lobbyRoom .chat-head { display: flex; align-items: center; gap: 8px; flex: none; }
  #lobbyRoom .chat-mascot { width: clamp(26px, 3vw, 38px); height: clamp(26px, 3vw, 38px); object-fit: contain;
    filter: drop-shadow(0 2px 3px rgba(0,0,0,0.2)); }
  #lobbyRoom .chat-title { font-weight: 900; color: #1c6aa3; font-size: clamp(13px, 1.5vmin, 16px); }
  #lobbyRoom .chat .chat-log { color: #2c6488; padding-right: 4px; }
  #lobbyRoom .chat-row input { border-radius: 999px; border: 2px solid #cfe6f7; background: #f1faff; padding: 9px 14px; }
  #lobbyRoom .chat-row button { border-radius: 999px; padding: 9px 18px; }

  /* chat bubbles (room + lobby) */
  .chat-log .cmsg { display: flex; flex-direction: column; align-items: flex-start; margin: 5px 0; }
  .chat-log .cmsg.me { align-items: flex-end; }
  .chat-log .cmsg.sys { align-items: center; }
  .chat-log .cwho { font-size: 11px; font-weight: 800; color: #1c6aa3; margin: 0 6px 1px; }
  .chat-log .cbubble { display: inline-block; max-width: 82%; padding: 6px 11px; border-radius: 13px;
    background: #e9f3ff; color: #15466b; font-weight: 600; word-break: break-word; box-shadow: 0 1px 2px rgba(0,0,0,0.08); }
  .chat-log .cmsg.me .cbubble { background: linear-gradient(#ffe79a, #ffd667); color: #6b4a00; }
  .chat-log .cmsg.sys .csys { font-size: 12px; color: #7aa6c2; font-style: italic; }
  .channel-chat .chat-log .cwho { color: #1c6aa3; }

  /* waiting room */
  /* ===== 園區共用分享面板 (shared/client/share.js) 的米花爆皮膚 =====
     那支元件的預設是暗色玻璃 (rgba(0,0,0,.55) + 白字 + 8px 方角), 因為先接的兩館
     (米花飄、米花地下城) 都是暗色遊戲, 對它們是對的。米花爆是亮的, 所以走它的
     主題化介面: 四個 --pshare-* 變數 + 它保證穩定的 class。米花飄對 social.js
     用的就是同一招。
     它現在只出現在「邀請」對話框裡 (共用 dock 的 Social.openSheet), 不再排進房間
     版面 —— 站主 2026-09-10: 「這些還是太占位置了」。所以這裡沒有寬度／置中／
     滿版那一類規則了, 版面由 sheet 負責, 這裡只管長相。
     配色是量出來的, 不是配出來的: 卡片 = .slot 座位卡 (白 .93 / 3px #fff / r16 /
     0 4px 0)、按鈕 = 座位下拉 .slot-sel (#eaf7ff / r999 / 0 3px 0 + inset 高光 /
     字 #134d77)、LINE = .pill.yellow (#ffd84a→#f5a31b / 字 #6b3b00 / 邊 #fff3c9)。 */
  #roomShare.pshare {
    --pshare-bg: rgba(255,255,255,0.93); --pshare-fg: #134d77;
    --pshare-accent: #6b3b00; --pshare-btn: #eaf7ff;
    box-sizing: border-box; width: 100%; margin: 0;
    display: flex; flex-direction: column; align-items: stretch;
    gap: 12px; padding: 13px 14px;
    border: 3px solid #fff; border-radius: 16px;
    box-shadow: 0 4px 0 rgba(0,0,0,0.10);
  }
  #roomShare .pshare-head { align-items: center; gap: 10px; }
  #roomShare .pshare-label { opacity: 1; color: #5b93bd; font-weight: 800; font-size: 12.5px; letter-spacing: 0.10em; }
  /* 房號本身是一顆按鈕 (點了複製房號), 所以給它按鈕的長相 —— 舊版是一串黃字, 沒人
     知道那可以點。 */
  #roomShare .pshare-code {
    padding: 5px 16px; border: 3px solid #fff3c9; border-radius: 999px;
    background: linear-gradient(#ffd84a, #f5a31b); color: #6b3b00;
    text-shadow: 0 1px 0 #ffe9a8; font-size: 22px; font-weight: 900; letter-spacing: 0.08em;
    box-shadow: 0 3px 0 rgba(0,0,0,0.18), inset 0 2px 0 rgba(255,255,255,0.35);
    transition: transform .05s;
  }
  #roomShare .pshare-code:active { transform: translateY(2px); }
  /* 對話框裡寬度是固定的, 所以四顆按鈕各佔一半, 兩兩成排 —— 比擠成一行好按 */
  #roomShare .pshare-row { gap: 8px; }
  #roomShare .pshare-row button {
    flex: 1 1 calc(50% - 4px); min-width: 0;
    padding: 9px 12px; min-height: 44px; font-size: 14px; font-weight: 800;
    color: #134d77; background: #eaf7ff;
    border: 3px solid #fff; border-radius: 999px;
    box-shadow: 0 3px 0 rgba(0,0,0,0.18), inset 0 2px 0 rgba(255,255,255,0.7);
    transition: transform .05s, border-color .08s;
  }
  /* 共用預設的 hover 是 filter:brightness(1.15) —— 那是給暗底按鈕寫的, 套在淺藍上
     只是把它洗白。改成這款遊戲自己的 hover: 邊框變天藍 + 微微浮起。 */
  #roomShare .pshare-row button:hover { filter: none; border-color: #64bce8; transform: translateY(-1px); }
  #roomShare .pshare-row button:active { transform: translateY(2px); box-shadow: 0 1px 0 rgba(0,0,0,0.18); }
  /* LINE 是主要動作: 整個成長迴路就是把房間連結丟進 LINE 群 (share.js 的檔頭自己
     這樣寫)。這款遊戲的主要動作一律是蜂蜜黃, 所以它跟 Quick Start 同一件衣服。
     選擇器必須比上面那條基底 (#roomShare .pshare-row button) 重: 少了 .pshare-row
     與 button, 權重 (1,1,0) 輸給 (1,1,1), LINE 會安靜地留著淺藍底。 */
  #roomShare .pshare-row button.pshare-line {
    color: #6b3b00; background: linear-gradient(#ffd84a, #f5a31b);
    border-color: #fff3c9; text-shadow: 0 1px 0 #ffe9a8;
  }
  #roomShare .pshare-row button.pshare-line:hover { border-color: #ffb43c; }
  /* QR 在對話框裡就行內展開就好 —— sheet 自己會捲 (max-height:78vh)。 */
  #roomShare .pshare-qr {
    align-items: center; gap: 8px;
    background: none; border: 0; padding: 0; box-shadow: none; color: #134d77;
  }
  #roomShare .pshare-qr svg {
    width: min(56vw, 210px); height: min(56vw, 210px); padding: 10px; box-sizing: content-box;
    background: #fff; border: 3px solid #fff3c9; border-radius: 14px;
    box-shadow: 0 3px 0 rgba(0,0,0,0.12);
  }
  #roomShare .pshare-qr > div { color: #5b93bd; font-size: 12.5px; font-weight: 800; text-align: center; }
  /* 「已複製」以前是一行淡淡的小字, 在白卡上幾乎看不到。改成一顆蜂蜜色小籌碼。 */
  #roomShare .pshare-toast { min-height: 0; opacity: 1; }
  #roomShare .pshare-toast:not([hidden]) {
    align-self: flex-start; padding: 4px 12px; border-radius: 999px;
    background: linear-gradient(#ffe9a8, #ffd45e); border: 2px solid #fff3c9;
    color: #5a3800; font-size: 12.5px; font-weight: 800;
  }
  @media (prefers-reduced-motion: reduce) {
    #roomShare .pshare-row button, #roomShare .pshare-code { transition: none; }
    #roomShare .pshare-row button:hover { transform: none; }
  }

  /* 標題旁的邀請鈕。它在 .arc-title 裡面 (站主要求「到上方房號旁邊」), 而 .arc-title
     的字級是 clamp(18px,3.2vmin,28px) —— 按鈕不能繼承那個大小。 */
  .arc-title .rm-invite {
    display: inline-flex; align-items: center; gap: 6px; vertical-align: 3px;
    margin-left: 12px; padding: 6px 14px; border-width: 2px;
    font-size: 14px; font-weight: 800; letter-spacing: 0; text-shadow: none;
    box-shadow: 0 3px 0 rgba(0,0,0,0.18), inset 0 2px 0 rgba(255,255,255,0.35);
  }
  .arc-title .rm-invite svg { flex: none; vertical-align: 0; }

  .room-body { flex: 1; display: flex; gap: clamp(16px, 3vw, 40px); padding: clamp(16px, 3vh, 36px) clamp(16px, 5vw, 90px); overflow: hidden; width: 100%; max-width: 1320px; margin: 0 auto; box-sizing: border-box; }
  .room-left { flex: 2.2; min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: clamp(8px, 1.4vh, 16px); }
  /* square 4x2 grid: a 2:1 box scaled to fit the area, so every cell is square */
  .slots-area { flex: none; min-height: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; }
  .slots { width: 100%; display: grid; grid-template-columns: repeat(4, 1fr); align-items: end; gap: clamp(8px, 1.2vmin, 14px); }
  .slot-cell { display: flex; flex-direction: column; justify-content: flex-end; gap: 4px; min-width: 0; min-height: 0; }
  .slot {
    position: relative; width: 100%; height: auto; aspect-ratio: 1; box-sizing: border-box; min-height: 0; min-width: 0; overflow: hidden; border-radius: 16px; border: 3px solid #7fcdee;
    display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 3px;
    padding: clamp(5px, 0.9vmin, 10px); text-align: center; background: linear-gradient(#2a90d2, #2079bb);
  }
  .slot.empty { justify-content: center; color: #bfe6f7; font-weight: 800; border-style: dashed; background: rgba(255,255,255,0.06); }
  .avatar { flex: 1; min-height: 0; width: 100%; display: flex; align-items: center; justify-content: center; }
  .avatar img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
  .slot .who { flex: none; width: 100%; text-align: center; min-width: 0; }
  .slot .pname { font-weight: 900; font-size: clamp(12px, 1.7vmin, 20px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; line-height: 1.1; }
  .slot .hostcheck { color: #2ecc40; font-weight: 900; text-shadow: 0 1px 1px rgba(0,0,0,0.25); }
  /* the team "ground" is a constant-height ribbon for every seat, ready or not, so
     the READY state can live on it without ever resizing the character above */
  .slot .ground { flex: none; width: 72%; height: clamp(14px, 2.4vmin, 20px); margin-top: auto; border-radius: 999px;
    box-shadow: 0 1px 2px rgba(0,0,0,0.3); display: flex; align-items: center; justify-content: center; }
  .slot .ground .rdy { font-size: clamp(9px, 1.4vmin, 12px); font-weight: 900; color: #fff; letter-spacing: 0.5px;
    line-height: 1; text-shadow: 0 1px 2px rgba(0,0,0,0.5); white-space: nowrap; }
  .slot .ground .rdy.off { opacity: 0.6; }
  .slot .tags { margin-top: 3px; display: flex; gap: 4px; flex-wrap: wrap; justify-content: center; }
  /* 自動準備: an opt-in that persists across sessions, so the chip itself has to read
     ON or OFF at a glance — grey outline when off, solid green when on. The native
     checkbox stays in the DOM (keyboard + a11y) but the tick is our own SVG box. */
  .auto-ready { display: flex; align-items: center; justify-content: center; gap: 8px;
    width: fit-content; max-width: 100%; margin: 8px auto 0; padding: 6px 14px 6px 11px;
    border-radius: 999px; border: 2px solid rgba(20,77,119,0.18); background: rgba(20,77,119,0.07); color: #1c6aa3;
    font-size: clamp(12px, 1.2vw, 15px); font-weight: 800; cursor: pointer; user-select: none;
    transition: background 0.15s, border-color 0.15s, color 0.15s; }
  .auto-ready:hover { background: rgba(20,77,119,0.13); border-color: rgba(20,77,119,0.32); }
  .auto-ready.on { background: #6fdc6f; border-color: #2faa4a; color: #134d22; }
  .auto-ready.on:hover { background: #63d363; }
  .auto-ready input { position: absolute; width: 18px; height: 18px; margin: 0; opacity: 0; cursor: pointer; }
  .auto-ready .box { flex: none; width: 18px; height: 18px; border-radius: 5px; background: #fff;
    border: 2px solid rgba(20,77,119,0.38); display: flex; align-items: center; justify-content: center; transition: border-color 0.15s; }
  .auto-ready .box svg { opacity: 0; transition: opacity 0.12s; }
  .auto-ready.on .box { border-color: #134d22; }
  .auto-ready.on .box svg { opacity: 1; }
  .auto-ready input:focus-visible + .box { outline: 3px solid #ffd84a; outline-offset: 2px; }
  .auto-ready.hidden { display: none; }
  .tag { font-size: clamp(11px, 1.1vw, 14px); font-weight: 900; padding: 4px 10px; border-radius: 7px; }
  .tag.host { background: #ffd84a; color: #6b3b00; }
  .tag.bot  { background: #8aa6b8; color: #fff; }
  .tag.ready { background: #6fdc6f; color: #134d22; }
  .tag.notready { background: rgba(255,255,255,0.25); color: #eaf7ff; }
  .tag.open { background: #5cc3f2; color: #08324d; }
  .slot-cell .slot-ctrls { width: 100%; flex: none; display: flex; flex-direction: column; gap: 4px; }
  .slot-cell select.slotkind { width: 100%; padding: 6px 26px 6px 12px; font-size: clamp(11px, 1.2vmin, 14px); text-align: center; text-align-last: center; }
  .tag.team { background: #888; color: #fff; }
  .slot.selectable { cursor: pointer; }
  .slot.team-editing { outline: 3px solid #ffe14d; outline-offset: -1px; }
  .teamblocks { display: flex; gap: 10px; margin-top: 7px; }
  .teamblock { flex: 1; height: clamp(38px, 6vh, 56px); border-radius: 10px; border: 3px solid rgba(255,255,255,0.5); cursor: pointer; box-shadow: inset 0 -4px 8px rgba(0,0,0,0.18); }
  .teamblock.sel { border-color: #fff; box-shadow: 0 0 0 3px #ffe14d, inset 0 -4px 8px rgba(0,0,0,0.2); }
  .charblocks { display: flex; gap: 8px; margin-top: 6px; }
  .charblock { flex: 1; height: clamp(42px, 8vh, 66px); border-radius: 12px; border: 3px solid rgba(255,255,255,0.45); background: rgba(255,255,255,0.12) center/contain no-repeat; cursor: pointer; }
  .charblock.sel { border-color: #fff; box-shadow: 0 0 0 3px #ffe14d; background-color: rgba(255,255,255,0.22); }

  .side { flex: 1; max-width: 460px; min-height: 0; display: flex; flex-direction: column; gap: clamp(6px, 1vh, 12px); overflow: hidden; }
  /* controls scroll (instead of clipping) when the screen is too short; START/READY stay pinned */
  .side-main { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 9px; overflow-y: auto; padding: 1px 4px 4px 1px; }
  .side-foot { flex: 0 0 auto; padding-top: 6px; }   /* START / READY always pinned & visible */
  .room-setting { border: 1.5px solid rgba(28,106,163,.13); border-radius: 14px; padding: 9px 10px 10px; background: rgba(235,248,255,.66); }
  .panel-label { display:flex; align-items:center; gap:7px; font-weight: 900; font-size: clamp(12px, 1.15vw, 14px); color: #d6f0ff; margin: 0 0 7px; letter-spacing: .08em; }
  .panel-label::before { content:""; width:4px; height:14px; flex:none; border-radius:4px; background:linear-gradient(#ffd84a,#ffad33); box-shadow:0 1px 2px rgba(107,59,0,.2); }
  .modesel { display:flex; gap:10px; flex-wrap:wrap; }
  #modeSel { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 7px; }
  #modeSel .pill { min-width:0; min-height:42px; padding:8px 6px; border:2px solid #cbe8f8; border-radius:11px; background:#fff; color:#286889; box-shadow:0 2px 0 rgba(20,77,119,.1); font-size:clamp(12px,1.2vw,15px); }
  #modeSel .pill:hover:not(:disabled) { border-color:#64bce8; transform:translateY(-1px); }
  #modeSel .pill.sel { outline:0; border-color:#f0b926; color:#6b4700; background:linear-gradient(180deg,#fff8d6,#ffe48a); box-shadow:0 2px 0 #d69b17, inset 0 1px #fff; }
  .rules-toggle { width: 100%; display: flex; align-items: center; justify-content: space-between; padding:9px 12px; border-radius:10px; }
  .rules-chevron { font-size: 16px; transition: transform 0.16s ease; }
  .rules-toggle[aria-expanded="true"] .rules-chevron { transform: rotate(180deg); }
  .rules-panel { margin-top: 7px; padding: 10px; border: 2px solid rgba(19,77,119,0.18); border-radius: 14px; background: rgba(255,255,255,0.38); }
  .rules-panel.hidden { display: none; }
  .rules-enable { width: 100%; }
  /* room rules: random-drop ban grid (host taps; guests read-only) */
  .rules-sub { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 8px 0 5px; font-weight: 800; font-size: 12.5px; color: #bfe6f7; letter-spacing: 0.5px; }
  .rules-hint { font-weight: 700; font-size: 11px; color: #7aa6c2; text-align: right; }
  .dropbans { display: flex; flex-wrap: wrap; gap: 6px; }
  .dropban { position: relative; display: flex; flex-direction: column; align-items: center; gap: 3px; width: 54px; padding: 6px 2px 4px;
    background: rgba(255,255,255,0.10); border: 1.5px solid rgba(255,255,255,0.28); border-radius: 10px; cursor: pointer; font-family: inherit; }
  .dropban img { width: 26px; height: 26px; object-fit: contain; }
  .dropban span { font-size: 10px; font-weight: 800; color: #d9f1ff; line-height: 1; white-space: nowrap; }
  .dropban .banx { position: absolute; top: 8px; left: 50%; transform: translateX(-50%); pointer-events: none; filter: drop-shadow(0 1px 1px rgba(0,0,0,0.4)); }
  .dropban.banned { border-color: #e04040; background: rgba(224,64,64,0.16); }
  .dropban.banned img { filter: grayscale(1); opacity: 0.45; }
  .dropban.banned span { color: #f2a5a5; }
  .dropban:not(:disabled):hover { border-color: #ffe14d; }
  .dropbans.ro .dropban { cursor: default; }
  /* the waiting room is light glass: darken the rules text/chips there */
  #lobbyRoom .rules-sub { color: #1c6aa3; }
  #lobbyRoom .rules-hint { color: #6e94ad; }
  #lobbyRoom .dropban { background: rgba(255,255,255,0.85); border-color: #bfe6f7; }
  #lobbyRoom .dropban span { color: #134d77; }
  #lobbyRoom .dropban.banned { border-color: #e04040; background: rgba(224,64,64,0.10); }
  #lobbyRoom .dropban.banned span { color: #c04040; }
  .modesel button { flex:1 1 auto; min-width:0; }
  #modeSel button { flex:none; }
  .dropdown { width: 100%; box-sizing: border-box; padding: clamp(8px, 1.1vh, 12px) 36px clamp(8px, 1.1vh, 12px) 14px; margin-top: 6px; font-size: clamp(14px, 1.3vw, 17px); background-position: right 14px center; background-size: 16px; }
  .droprow { display: flex; gap: 8px; }
  .droprow .dropdown { flex: 1; min-width: 0; }
  /* chunky cartoon select to match the game UI (closed control; option list stays native) */
  .dropdown, select.slotkind {
    -webkit-appearance: none; -moz-appearance: none; appearance: none;
    border: 3px solid #ffffff; border-radius: 999px;
    background-color: #eaf7ff; color: #134d77; font-family: inherit; font-weight: 800;
    background-repeat: no-repeat; background-position: right 10px center; background-size: 13px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%231c7cc0' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    box-shadow: 0 3px 0 rgba(0,0,0,0.18), inset 0 2px 0 rgba(255,255,255,0.7);
    cursor: pointer; outline: none; transition: transform .05s, border-color .1s;
  }
  .dropdown:hover, select.slotkind:hover { border-color: #ffe14d; }
  .dropdown:focus, select.slotkind:focus { border-color: #ffe14d; box-shadow: 0 0 0 3px rgba(255,225,77,0.55), inset 0 2px 0 rgba(255,255,255,0.7); }
  .dropdown:active, select.slotkind:active { transform: translateY(2px); box-shadow: inset 0 2px 4px rgba(0,0,0,0.2); }
  .dropdown:disabled, select.slotkind:disabled { opacity: 0.55; cursor: default; box-shadow: none; }
  .dropdown option, select.slotkind option { background: #1f8fd0; color: #fff; font-weight: 700; }
  .map-thumb { position: relative; border-radius: 12px; overflow: hidden; border: 3px solid #fff; margin-top: 8px; box-shadow:0 3px 10px rgba(20,77,119,.18); }
  .map-thumb img { width: 100%; height: clamp(90px, 17vh, 200px); object-fit: cover; display: block; }
  .map-thumb::after { content:""; position:absolute; inset:50% 0 0; background:linear-gradient(transparent,rgba(5,35,55,.75)); pointer-events:none; }
  .map-thumb span { position: absolute; z-index:1; left: 11px; right:11px; bottom: 8px; color:#fff; font-weight: 900; text-shadow: 0 2px 4px #000; font-size: clamp(14px, 1.4vw, 18px); }
  .community-map-btn { width:100%; margin-top:8px; min-height:40px; display:flex; align-items:center; gap:8px; border-radius:11px; text-align:left; }
  .community-map-btn > span:nth-child(2) { flex:1; min-width:0; white-space:normal; }
  .community-map-arrow { font-size:22px; line-height:1; }
  #lobbyRoom .teamblocks, #lobbyRoom .charblocks { margin-top:0; }
  #lobbyRoom .teamblock, #lobbyRoom .charblock { border-color:#fff; box-shadow:0 2px 5px rgba(20,77,119,.15); }
  #lobbyRoom .teamblock.sel, #lobbyRoom .charblock.sel { border-color:#fff; outline:3px solid #f6c52c; outline-offset:1px; box-shadow:0 2px 7px rgba(107,59,0,.2); }
  /* The room's status line. One pill, and its colour says WHY the match has not
     started: amber = the host still has something to fix, green = good to go,
     blue-grey = waiting on somebody else, cyan = you are only watching. */
  #waitMsg { font-size: clamp(13px, 1.2vw, 16px); text-align: center; min-height: 16px; }
  .wait-msg { display: flex; align-items: center; justify-content: center; gap: 7px;
    width: fit-content; max-width: 100%; margin: 8px auto 0; padding: 7px 15px;
    border-radius: 999px; font-weight: 800; line-height: 1.3; }
  .wait-msg svg { flex: none; }
  .wait-msg.blocked { background: #ffd84a; color: #6b3b00; }
  .wait-msg.ready   { background: #6fdc6f; color: #134d22; }
  .wait-msg.waiting { background: rgba(20,77,119,0.12); color: #1c6aa3; }
  .wait-msg.watch   { background: #5cc3f2; color: #08324d; }
  .err { color: #ffd1d1; font-weight: 700; text-align: center; padding: 0 16px 6px; min-height: 16px; }

  /* short viewports: tighten the waiting room so all controls fit without scrolling */
  @media (max-height: 760px) {
    #lobbyRoom .chat { min-height: 76px; }
    #lobbyRoom .room-body { padding-top: clamp(10px, 1.6vh, 18px); padding-bottom: clamp(10px, 1.6vh, 18px); }
    #lobbyRoom .side-main { gap: 6px; }
    #lobbyRoom .panel-label { margin-top: 0; }
    #lobbyRoom .map-thumb img { height: clamp(70px, 13vh, 120px); }
    #lobbyRoom .teamblock { height: clamp(30px, 4.6vh, 44px); }
    #lobbyRoom .charblock { height: clamp(34px, 5.6vh, 52px); }
    #lobbyRoom .pill.big { padding: 10px; font-size: clamp(15px, 2.1vmin, 20px); }
    #lobbyRoom .room-setting { padding:7px 8px 8px; }
    #lobbyRoom .panel-label { margin-bottom:5px; }
    #lobbyRoom #modeSel .pill { min-height:36px; padding-block:6px; }
  }

  /* Desktop / tablet landscape: compress the whole setup before introducing a
     scrollbar. The footer remains pinned; scrolling is only the final fallback. */
  @media (min-width: 721px) and (max-height: 900px) {
    #lobbyRoom .room-body { padding-top:10px; padding-bottom:10px; }
    #lobbyRoom .side { padding:9px 11px; gap:5px; }
    #lobbyRoom .side-main { gap:5px; }
    #lobbyRoom .room-setting { padding:6px 8px 7px; border-radius:11px; }
    #lobbyRoom .panel-label { margin-bottom:4px; font-size:12px; }
    #lobbyRoom #modeSel .pill { min-height:34px; padding:5px 4px; }
    #lobbyRoom .rules-toggle { min-height:34px; padding:6px 10px; }
    #lobbyRoom .dropdown { min-height:34px; margin-top:0; padding-top:6px; padding-bottom:6px; }
    #lobbyRoom .map-thumb { margin-top:5px; }
    #lobbyRoom .map-thumb img { height:clamp(56px,8vh,74px); }
    #lobbyRoom .community-map-btn { min-height:34px; margin-top:5px; padding-block:6px; }
    #lobbyRoom .teamblock { height:32px; min-height:32px; }
    #lobbyRoom .charblock { height:40px; min-height:40px; }
    #lobbyRoom #charStats { margin-top:5px; padding:5px 8px; }
    #lobbyRoom #charStats .statname { margin-bottom:2px; font-size:12px; }
    #lobbyRoom #charStats .statrow { margin:1px 0; }
    #lobbyRoom #charStats .pips i,
    #lobbyRoom #charStats .statlegend i { width:9px; height:9px; }
    #lobbyRoom #charStats .statlegend { margin-top:3px; font-size:10px; }
    #lobbyRoom .side-foot { padding-top:3px; }
    #lobbyRoom .wait-msg { margin-top:4px; padding:5px 12px; }
  }

  /* ===== phones =====
     Portrait (narrow): the desktop side-by-side columns collapse into ONE
     scrollable stack — nothing may rely on everything fitting the height.
     Short landscape (browser URL/tool bars eating the height): the side columns
     scroll on their own instead of shrink-overlapping. */
  @media (max-width: 720px) {
    #lobbyList .title-row { position: static; transform: none; }   /* was absolute-centered → collided with the buttons */
    .arc-header { flex-wrap: wrap; row-gap: 6px; padding: 8px 10px; justify-content: center; }
    .arc-title { font-size: 18px; }
    .arc-toolbar { padding: 8px 10px; gap: 8px; }
    .channel-main, .room-body, .shop-body { flex-direction: column; overflow-y: auto; -webkit-overflow-scrolling: touch; }
    .channel-left, .channel-right, .room-left, .side, .shop-preview, .shop-main { flex: none; width: 100%; max-width: none; box-sizing: border-box; }
    .channel-main { padding: 4px 12px 12px; }
    .hero-card { min-height: 180px; }
    #lobbyList .channel-chat { min-height: 170px; }
    .board-list { max-height: 180px; }
    .quick-menu { grid-template-columns: repeat(4, 1fr); }
    .room-body { padding: 10px 12px; gap: 10px; }
    .side-main { overflow: visible; }
    #lobbyRoom .side { padding:10px; }
    #lobbyRoom .room-setting { padding:10px; }
    #lobbyRoom #modeSel .pill { min-height:44px; }
    #lobbyRoom .droprow { gap:6px; }
    #lobbyRoom .dropdown { min-height:44px; font-size:14px; }
    #lobbyRoom .community-map-btn { min-height:44px; }
    #lobbyRoom .teamblock { min-height:44px; }
    #lobbyRoom .charblock { min-height:52px; }
    #lobbyRoom .chat { min-height: 110px; }
    .shop-body { padding: 10px 12px; gap: 10px; }
    .shop-preview { flex-direction: row; flex-wrap: wrap; justify-content: center; padding: 10px; }
    .shop-preview canvas { width: 34%; }
    .shop-tabs { flex-wrap: wrap; gap: 6px; }
    .shop-tabs .pill { padding: 7px 12px; }
    .shop-grid { overflow: visible; }
    .chat { padding: 8px 12px; }
  }
  @media (max-height: 430px) {
    .arc-header { padding: 5px 10px; }
    .arc-toolbar { padding: 5px 10px; gap: 8px; }
    .channel-right { overflow-y: auto; }
    .channel-right > * { flex: none; }   /* shrink-to-overlap is what broke short landscape */
    .board-list { max-height: 140px; }
    .quick-tile .qicon { height: 26px; }
    .room-body { padding: 6px 12px; gap: 10px; }
    .room-left { overflow-y: auto; min-height: 0; }
    .chat { height: 72px; padding: 6px 12px; }
    #lobbyRoom .chat { min-height: 56px; }
    #lobbyRoom .side-main { overflow-y:auto; }
  }

  @media (max-width: 380px) {
    #lobbyRoom #modeSel { grid-template-columns:1fr; }
    #lobbyRoom #modeSel .pill { min-height:40px; }
    #lobbyRoom .droprow { flex-direction:column; }
    #lobbyRoom .dropdown { width:100%; margin-top:0; }
  }

  /* chat (channel + room) */
  .chat { border-top: 3px solid #6fc6ee; background: #1a72b4; padding: 8px clamp(16px, 5vw, 90px); display: flex; flex-direction: column; gap: 6px; height: clamp(84px, 12vh, 160px); flex: none; }
  .acctchip { font-weight: 800; color: #fff; font-size: clamp(13px, 1.6vmin, 17px); white-space: nowrap; }
  .acctchip span { color: #ffe14d; }
  .chat-log { flex: 1; overflow-y: auto; font-size: 14px; line-height: 1.45; color: #eaf7ff; }
  .chat-log .cmsg { margin: 1px 0; }
  .chat-log .cwho { font-weight: 800; color: #ffe14d; }
  .chat-log .csys { color: #bfe6f7; font-style: italic; }
  .chat-row { display: flex; gap: 6px; }
  .chat-row input { flex: 1; min-width: 0; padding: 8px 10px; border-radius: 9px; border: 2px solid #cfeaf8; background: #e9f7ff; color: #134d77; font-size: 14px; font-weight: 600; outline: none; }
  .chat-row button { padding: 8px 16px; }

  /* menu (name + start), overlaid on the canvas logo */
  /* Column flex + margin-top:auto (not align-items:flex-end): the card still sits at
     the bottom when there's room, but when the viewport is SHORTER than the card —
     a phone in landscape, where browser toolbars eat most of the height — the auto
     margin collapses and the container scrolls. Bottom-anchoring without scroll
     pushed the overflow off the TOP of the screen, hiding the username/password
     fields under the browser's URL bar with no way to reach them. */
  /* pre-login showcase: two tilted gameplay polaroids flanking the login card
     (desktop); on narrow screens they become a small centred row above the card */
  #homeShots { display: contents; }
  .home-shot { position: absolute; top: 50%; width: min(23vw, 330px); pointer-events: none;
    background: #fff; padding: 8px 8px 6px; border-radius: 12px; box-shadow: 0 10px 28px rgba(0,0,0,0.35); }
  .home-shot img { display: block; width: 100%; border-radius: 8px; }
  .home-shot span { display: block; text-align: center; font-weight: 800; color: #134d77; font-size: 13px; padding-top: 5px; }
  .home-shot.left { left: 3vw; transform: translateY(-58%) rotate(-4deg); }
  .home-shot.right { right: 3vw; transform: translateY(-58%) rotate(4deg); }
  @media (max-width: 1100px) {
    #homeShots { display: flex; gap: 14px; justify-content: center; align-items: flex-end; margin-top: auto; padding: 0 10px; pointer-events: none; }
    .home-shot { position: static; width: min(40vw, 210px); padding: 5px 5px 4px; }
    .home-shot.left { transform: rotate(-3deg); }
    .home-shot.right { transform: rotate(3deg); }
    .home-shot span { font-size: 11px; padding-top: 3px; }
    #menuScreen .menu-card { margin-top: 14px; }   /* homeShots takes the auto margin, card stays glued below */
  }
  /* short landscape phones: no room — the login card wins */
  @media (max-height: 480px) { #homeShots { display: none; } #menuScreen .menu-card { margin-top: auto; } }
  #menuScreen { position: fixed; inset: 0; display: none; flex-direction: column; align-items: center; pointer-events: none; z-index: 5;
    overflow-y: auto; padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); }
  #menuScreen.show { display: flex; }
  .menu-card { pointer-events: auto; flex: none; display: flex; flex-direction: column; gap: 12px; align-items: stretch; width: min(86vw, 360px); margin-top: auto; margin-bottom: min(9vh, 40px); background: rgba(18,40,62,0.66); border: 3px solid #7fcdee; border-radius: 16px; padding: 16px; box-shadow: 0 8px 24px rgba(0,0,0,0.35); }
  .menu-card .name-row { display: flex; align-items: center; gap: 6px; background: #e9f7ff; border: 2px solid #cfeaf8; border-radius: 999px; padding: 0 14px; }
  .menu-card .name-row label { flex: none; color: #134d77; font-weight: 800; font-size: 16px; }
  .menu-card input { flex: 1; min-width: 0; padding: 8px 4px; border: 0; background: transparent; color: #134d77; font-size: 16px; font-weight: 800; outline: none; }
  .menu-card input::placeholder { color: #7fa8c4; font-weight: 600; }
  #menuAuth, #menuHome { display: flex; flex-direction: column; gap: 12px; }
  /* login / register fields: white text + white password dots on the dark card */
  .pill.gpill { display: none; align-items: center; justify-content: center; gap: 10px;
    background: linear-gradient(#ffffff, #eef2f5); color: #3c4043; text-shadow: none; border-color: #fff; }
  .pill.gpill svg { flex: none; }
  #authUser, #authPass, #guestName { padding: 12px 14px; border-radius: 11px; border: 2px solid #7fcdee; background: rgba(255,255,255,0.12);
    color: #fff; -webkit-text-fill-color: #fff; caret-color: #fff; font-weight: 800; }
  #authUser::placeholder, #authPass::placeholder, #guestName::placeholder { color: rgba(255,255,255,0.6); -webkit-text-fill-color: rgba(255,255,255,0.6); font-weight: 600; }
  /* the guest name belongs to the guest button below it, not to the login fields above */
  #guestName { margin-top: 6px; }
  /* 標題畫面頂端列: 音樂 / 音效 / 設定 靠左, 全螢幕置中, 語言靠右。一列 flex, 所以
     每顆的間距是 gap 給的 —— 不會再有「兩顆按鈕的點擊範圍互相重疊 10px」這種事。 */
  .menu-topbar { position: absolute; top: 0; left: 0; right: 0; z-index: 2;
    display: flex; align-items: center; gap: 8px; padding: 12px; box-sizing: border-box; pointer-events: none; }
  .menu-topbar > * { pointer-events: auto; flex: none; }
  .langbtn { position: static; font-size: 14px; padding: 8px 16px; }
  /* prominent fullscreen hint, top-centre of the menu */
  .fsbtn { position: static; margin: 0 auto;
    font-size: clamp(14px, 1.8vmin, 18px); padding: 10px 22px; box-shadow: 0 4px 0 rgba(0,0,0,0.22), inset 0 2px 0 rgba(255,255,255,0.4); animation: fspulse 2.4s ease-in-out infinite; }
  .fsbtn:active { transform: translateY(2px); }
  /* 窄螢幕: 全螢幕只留圖示。整列 (三顆圖示 + 全螢幕 + 語言) 在 320px 就放得下, 不用
     換行, 也就不會落到下面那排遊戲截圖上。 */
  @media (max-width: 480px) {
    .menu-topbar { gap: 6px; padding: 12px 10px; }
    .fsbtn span { display: none; }
    .fsbtn { padding: 10px 13px; }
    .langbtn { padding: 8px 12px; }
  }
  /* 夠寬的時候「全螢幕」回到畫面正中央 (它原本的設計位置, 對齊中間那張登入卡)。
     在 flex 列裡 margin:auto 只會把它排在「剩下的空間」正中間 —— 左邊三顆圖示比
     右邊的語言鈕寬, 於是整顆偏右 60px。620px 以上圖示列佔不到 200px、語言鈕佔不到
     60px, 置中的按鈕碰不到任何一邊, 才把絕對定位加回來。 */
  @media (min-width: 620px) {
    .fsbtn { position: absolute; top: 12px; left: 50%; transform: translateX(-50%); margin: 0; }
    .fsbtn:active { transform: translateX(-50%) translateY(2px); }
    /* 全螢幕離開這一列之後, 靠右的語言鈕沒東西推它了 —— 自己貼右邊 */
    .langbtn { margin-left: auto; }
  }
  @keyframes fspulse { 0%,100% { box-shadow: 0 4px 0 rgba(0,0,0,0.22), inset 0 2px 0 rgba(255,255,255,0.4), 0 0 0 0 rgba(255,255,255,0.0); } 50% { box-shadow: 0 4px 0 rgba(0,0,0,0.22), inset 0 2px 0 rgba(255,255,255,0.4), 0 0 0 6px rgba(255,255,255,0.18); } }
  /* short viewports (phone landscape): the centred fullscreen hint lands ON the login
     card's tabs — and iPhone Safari has no fullscreen API for page content anyway */
  @media (max-height: 420px) { .fsbtn { display: none; } }
  /* icon-only mute pill: top-left of the login page; also sits in the channel + room headers */
  .mute-toggle svg { display: block; }
  /* SVG icons inside the mode / stakes pills */
  .modesel .pill svg { vertical-align: -3px; margin-right: 6px; }
  /* per-character stat card (base vs cap pips) */
  #charStats { margin-top: 8px; background: rgba(10,40,66,0.55); border: 2px solid #7fcdee; border-radius: 12px; padding: 8px 10px; }
  #charStats .statname { font-size: 13px; font-weight: 900; color: #ffe86e; margin-bottom: 4px; }
  #charStats .statrow { display: flex; align-items: center; gap: 8px; margin: 3px 0; }
  #charStats .statrow span { flex: none; width: 4.5em; font-size: 12px; font-weight: 900; color: #cfeaff; }
  #charStats .pips { display: flex; gap: 3px; flex: 1; }
  #charStats .pips i, #charStats .statlegend i { display: inline-block; width: 12px; height: 12px; border-radius: 3px; border: 1px solid rgba(0,0,0,0.35); }
  #charStats .p-base { background: linear-gradient(#ffe86e, #f5b21b); }
  #charStats .p-max { background: linear-gradient(#8fe07a, #3fae4e); }
  #charStats .p-off { background: rgba(255,255,255,0.14); }
  #charStats .statlegend { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 11px; font-weight: 800; color: #cfeaff; }
  #charStats .statlegend i { margin-left: 6px; }
  .arc-title svg, .chat-title svg, .reco-head svg, .acctchip svg, .coinbal svg, .pill svg { vertical-align: -2px; }
  [data-i18n] svg { margin-right: 6px; vertical-align: -2px; }
  .mutebtn, .sfxbtn { position: static; }
  .menu-card .acct-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; color: #fff; font-weight: 900; font-size: 18px; padding: 0 4px; }
  .acct-rating { color: #ffe14d; }
  #logoutBtn { font-size: 13px; padding: 8px; }

  /* login / register */
  #auth { position: fixed; inset: 0; z-index: 40; display: none; align-items: center; justify-content: center;
    background: radial-gradient(120% 90% at 50% -10%, #6fd3f4 0%, #2ea6e0 45%, #1d7fc4 100%); }
  #auth.show { display: flex; }
  .auth-card { width: min(88vw, 360px); display: flex; flex-direction: column; gap: 12px; padding: 22px;
    background: rgba(18,40,62,0.72); border: 3px solid #7fcdee; border-radius: 18px; box-shadow: 0 10px 30px rgba(0,0,0,0.4); }
  .auth-logo { text-align: center; font-weight: 900; font-size: 26px; color: #fff; }
  .auth-tabs button { flex: 1; }
  .auth-card input { padding: 12px 14px; border-radius: 11px; border: 2px solid #cfeaf8; background: #e9f7ff; color: #134d77; font-size: 16px; font-weight: 700; outline: none; }
  .slot .srating { font-size: clamp(11px, 1.4vmin, 16px); font-weight: 900; color: #ffe14d; margin-left: 4px; }
  .slot .slv { font-size: clamp(10px, 1.3vmin, 14px); font-weight: 900; color: #6b4a00; background: linear-gradient(#ffe86e, #f5b21b); border-radius: 999px; padding: 0 6px; margin-left: 5px; }
  .slot .slv[class*="rank-"] { color: #fff; }
  #menuShopBtn { font-size: 15px; }

  /* outfit shop */
  /* ===== progression panels (任務 / 成就 / 排行榜) ===== */
  .acct-lv { margin-left: 6px; padding: 1px 8px; border-radius: 999px; background: #5a3a12; color: #ffe86e; font-weight: 900; font-size: 12px; }
  .xpbar { display: inline-block; width: 64px; height: 8px; margin-left: 6px; border-radius: 999px; background: rgba(255,255,255,0.18); border: 1px solid rgba(255,255,255,0.35); overflow: hidden; vertical-align: middle; }
  .xpbar i { display: block; height: 100%; width: 0; background: linear-gradient(#8fe07a, #3fae4e); }
  #panel { position: fixed; inset: 0; z-index: 30; display: none; align-items: center; justify-content: center;
    background: rgba(6,24,42,0.72); }
  #panel.show { display: flex; }
  .panel-box { width: min(94vw, 720px); max-height: 86%; display: flex; flex-direction: column; gap: 10px; padding: 18px;
    background: radial-gradient(120% 90% at 50% -10%, #1f5f8f 0%, #123f63 55%, #0c2c48 100%);
    border: 3px solid #7fcdee; border-radius: 18px; box-shadow: 0 12px 40px rgba(0,0,0,0.5); }
  .panel-head { display: flex; align-items: center; gap: 10px; }
  .panel-title { flex: 1; font-weight: 900; font-size: 22px; color: #fff; text-shadow: 0 2px 6px rgba(0,0,0,0.5); }
  .panel-tabs { display: flex; gap: 8px; }
  .panel-body { overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding-right: 4px; }
  /* shop: an animated bomb skin says so on its preview (the picture also blinks) */
  .shop-pic { position: relative; }
  .shop-fx { position: absolute; right: 4px; bottom: 3px; padding: 1px 6px; border-radius: 999px;
    background: linear-gradient(#ff8ad0, #c73bd6); color: #fff; font-size: 9.5px; font-weight: 900;
    letter-spacing: 0.4px; box-shadow: 0 2px 6px rgba(0,0,0,0.25); pointer-events: none; }
  /* 站主專屬的「測試中」: 只有站主看得到的單品 (未上架的品項, 或整個槽還沒上架)。
     刻意跟 .shop-fx 同一個形狀但換成警示色 —— 一眼看得出這張卡不是玩家看到的。 */
  .shop-wip { position: absolute; left: 4px; top: 3px; padding: 1px 6px; border-radius: 999px;
    background: linear-gradient(#ffb648, #f2762b); color: #3a1c00; font-size: 9.5px; font-weight: 900;
    letter-spacing: 0.4px; box-shadow: 0 2px 6px rgba(0,0,0,0.25); pointer-events: none; }
  .shop-card.wip { outline: 2px dashed rgba(242,118,43,0.55); outline-offset: -2px; }
  /* ===== Friend notifications (over any scene, match included) ===== */
  /* top-centre-right, above the HUD but clear of the board's middle; pointer-events
     only on the card so a stray tap never steals a game input */
  #frToasts { position: fixed; top: 8px; right: 10px; z-index: calc(var(--z-replay) + 2); display: flex; flex-direction: column; gap: 6px;
    align-items: flex-end; pointer-events: none; max-width: min(320px, 72vw); }
  /* 全螢幕小提示: replaces the old auto-fullscreen on 開始/準備 — a tappable pill
     at the top; the tap IS the user gesture the fullscreen API needs */
  #fsHint { position: fixed; top: 8px; left: 50%; transform: translateX(-50%); z-index: calc(var(--z-replay) + 2); display: none;
    align-items: center; gap: 7px; padding: 7px 13px; border-radius: 999px; cursor: pointer; user-select: none;
    background: rgba(20, 24, 40, 0.85); color: #ffe14d; font-size: 13px; font-weight: 800;
    border: 1px solid rgba(255, 225, 77, 0.45); box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35); }
  #fsHint.show { display: flex; }
  /* 觀戰橫幅也住在正上方 (見 #specDock): 兩個都在的時候提示往下讓一格 */
  body.spec-top #fsHint { top: 54px; }
  @media (max-width: 600px) { body.spec-top #fsHint { top: 46px; } }
  #fsHint:active { transform: translateX(-50%) translateY(1px); }
  /* ===== 私訊 toast (2026-08-30 重做) =====
     原本 11.5/13px、單行 ellipsis、藍底藍框, 疊在花花綠綠的棋盤上等於隱形, 而且
     一則稍長的訊息只看得到開頭。三件事一起改:
       1. 看得到 —— 金色左邊條 + 更黑的底 + 更重的陰影。金色是這款遊戲的警示色,
          在綠地、木箱、石磚上都跳得出來, 藍色不會。
       2. 讀得完 —— 訊息放大到 15px 並允許兩行 (line-clamp), 一則真的訊息看得完。
       3. 被注意到 —— 進場帶一個彈跳, 圖示閃兩下。靜止的東西在動態畫面裡不會被看見。
     位置分開處理: 桌機留在左下 (跟遊戲內聊天同一角, 眼睛已經在那), 手機直向改到
     正上方 —— 直向時左下角同時有棋盤下緣、聊天、搖桿, 塞不下也擋畫面。 */
  .fr-toast { pointer-events: auto; position: relative; display: flex; align-items: flex-start; gap: 10px;
    padding: 9px 13px 9px 14px; border-radius: 14px; cursor: pointer; overflow: hidden;
    background: linear-gradient(rgba(14,26,42,0.97), rgba(8,18,32,0.97));
    border: 2px solid rgba(255,214,74,0.9);
    box-shadow: 0 8px 26px rgba(0,0,0,0.55), 0 0 0 4px rgba(255,214,74,0.10);
    color: #eaf6ff; max-width: 100%; animation: frToastIn 0.34s cubic-bezier(.2,1.5,.4,1); }
  /* 左邊那條金條: 一眼分辨「這是人傳來的訊息」, 不是系統公告 */
  .fr-toast::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
    background: linear-gradient(#ffe57a, #f2a026); }
  .fr-toast:active { transform: translateY(1px); }
  .fr-toast .ft-icon { flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 9px;
    background: linear-gradient(#ffd64a, #f2a026); color: #3a2c12;
    animation: frIconPop 0.9s ease-out 2; }
  .fr-toast .ft-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; line-height: 1.3; }
  .fr-toast .ft-who { font-size: 12.5px; font-weight: 900; color: #ffd64a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* 兩行: 單行 ellipsis 讓「欸你在哪一間？我進不去欸」只剩「欸你在哪一…」 */
  .fr-toast .ft-text { font-size: 15px; font-weight: 700; color: #fff; overflow: hidden; overflow-wrap: anywhere;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
  @keyframes frToastIn { from { opacity: 0; transform: translateX(18px) scale(0.92); } to { opacity: 1; transform: none; } }
  @keyframes frIconPop { 0%, 100% { transform: scale(1); } 35% { transform: scale(1.18); } }
  .fr-toast.out { opacity: 0; transform: translateX(18px); transition: opacity 0.25s, transform 0.25s; }
  /* 滑鼠停在上面就不要跑掉 —— 正在讀的東西不該被計時器收走 */
  #frToasts:hover .fr-toast { animation-play-state: paused; }
  @media (max-width: 600px) { .fr-toast .ft-text { font-size: 14px; } .fr-toast .ft-who { font-size: 12px; } }
  /* 大廳/房間 (非對戰中) 的觸控裝置: 貼近角落一點, 別壓到瀏海 */
  @media (pointer: coarse) { #frToasts { top: 6px; right: 6px; max-width: 72vw; } }
  /* 對戰中: 桌機維持左下 (跟 #gameChat 同一角), 手機直向改到正上方 */
  #frToasts.ingame { top: auto; right: auto; left: 12px; bottom: 92px; align-items: flex-start; }
  /* 橫向手機: 棋盤幾乎佔滿整個高度, 沒有真正空著的地方 —— 那就選傷害最小的角落。
     左下是唯一沒有 HUD 的角, 搖桿約在 bottom 40px 內, 所以停在 96px 之上。
     窄一點 (40vw) 才不會橫跨到棋盤中央。 */
  @media (pointer: coarse) and (orientation: landscape) {
    #frToasts.ingame { left: 6px; bottom: 96px; max-width: min(320px, 40vw); }
  }
  /* 直向手機: 左下角同時有棋盤下緣、聊天與搖桿 —— 訊息改走頂端, 蓋不到棋盤中央 */
  @media (pointer: coarse) and (orientation: portrait) {
    /* top 需求: 齒輪與計時在 0~44px, 下面是 #gameLeaveBtn (高 42px)。那顆的 top 現在
       跟著 HUD 一起放大 (--hud-leave-top), 直向平板會排到 61px —— 寫死的 100px 會被它
       的下緣穿過去, 所以這裡也用同一個變數算。 */
    #frToasts.ingame { left: 50%; right: auto; bottom: auto; top: calc(var(--hud-leave-top) + 50px); transform: translateX(-50%);
      align-items: stretch; max-width: calc(100vw - 20px); width: calc(100vw - 20px); }
    /* 齊寬: 兩張卡不一樣寬會讀成兩個不同的東西 */
    #frToasts.ingame .fr-toast { width: 100%; box-sizing: border-box; }
    body.spec-top #frToasts.ingame { top: calc(var(--hud-leave-top) + 88px); }   /* 觀戰橫幅在的時候再讓一格 */
  }
  @media (prefers-reduced-motion: reduce) {
    .fr-toast { animation: none; } .fr-toast .ft-icon { animation: none; }
  }
  /* ===== Friends panel (好友): request row, friend rows, DM thread ===== */
  .fr-addrow { flex: none; display: flex; gap: 6px; }
  .fr-addrow input { flex: 1; min-width: 0; box-sizing: border-box; padding: 9px 13px; border-radius: 999px; font-size: 14px; font-weight: 700;
    border: 1.5px solid rgba(150,115,55,0.30); background: rgba(255,255,255,0.85); color: #3a2c12; outline: none; }
  .fr-addrow input::placeholder { color: rgba(110,85,45,0.5); }
  .fr-addrow input:disabled { opacity: 0.55; }
  .fr-addrow .pill { flex: none; padding: 9px 16px; font-size: 14px; }
  .fr-err { flex: none; font-size: 12.5px; }
  .fr-head { flex: none; margin-top: 4px; font-size: 12px; font-weight: 900; letter-spacing: 0.5px; color: #6b5327; text-transform: uppercase; }
  .fr-empty { flex: none; font-size: 12.5px; font-style: italic; color: #93805f; }
  .fr-row { flex: none; display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-radius: 12px;
    background: rgba(255,255,255,0.66); border: 1.5px solid rgba(150,115,55,0.20); }
  .fr-row.dim { opacity: 0.72; }
  .fr-name { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; }
  .fr-name b { font-size: 14px; font-weight: 800; color: #3a2c12; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .fr-name i { flex: none; font-style: normal; font-size: 11px; font-weight: 800; color: #b8790f; }
  .fr-dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: #b9ab90; }
  .fr-dot.on { background: #35d06a; box-shadow: 0 0 0 3px rgba(53,208,106,0.22); }
  .fr-btn { flex: none; position: relative; padding: 6px 12px; font-size: 12.5px; }
  .fr-unread { display: inline-block; margin-left: 5px; min-width: 16px; padding: 0 4px; border-radius: 999px;
    background: #ff3b3b; color: #fff; font-size: 11px; font-weight: 900; line-height: 16px; }
  .fr-dmhead { flex: none; display: flex; align-items: center; gap: 8px; }
  .fr-dmlog { flex: 1; min-height: 120px; overflow-y: auto; display: flex; flex-direction: column; gap: 5px; padding: 8px;
    border-radius: 12px; background: rgba(255,255,255,0.55); border: 1.5px solid rgba(150,115,55,0.18); }
  .dm-line { max-width: 82%; align-self: flex-start; padding: 6px 10px; border-radius: 12px; font-size: 13.5px; line-height: 1.35;
    background: rgba(255,255,255,0.92); border: 1.5px solid rgba(150,115,55,0.22); color: #3d3020; word-break: break-word; }
  .dm-line.mine { align-self: flex-end; background: linear-gradient(#ffe9a8, #ffd45e); border-color: #ffedb0; color: #5a3800; }
  .prog-card { display: flex; align-items: center; gap: 12px; padding: 10px 12px;
    background: rgba(10,40,66,0.55); border: 2px solid #3f7ea8; border-radius: 12px; }
  .prog-card.done { border-color: #3fae4e; }
  .prog-card .picon { flex: none; width: 38px; height: 38px; border-radius: 10px; display: flex; align-items: center; justify-content: center;
    background: rgba(127,205,238,0.15); color: #ffe86e; }
  .prog-card .pmain { flex: 1; min-width: 0; }
  .prog-card .pname { font-weight: 900; color: #fff; font-size: 14px; }
  .prog-card .pdesc { color: #cfeaff; font-size: 12px; margin-top: 1px; }
  .prog-card .pbar { margin-top: 5px; height: 8px; border-radius: 999px; background: rgba(255,255,255,0.14); overflow: hidden; }
  .prog-card .pbar i { display: block; height: 100%; width: 0; background: linear-gradient(#8fe07a, #3fae4e); }
  .prog-card .pcount { color: #cfeaff; font-size: 11px; font-weight: 800; margin-top: 2px; }
  .prog-card .pside { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
  .prog-card .preward { display: flex; align-items: center; gap: 6px; color: #ffe86e; font-weight: 900; font-size: 12px; }
  .lb-row { display: flex; align-items: center; gap: 10px; padding: 8px 12px;
    background: rgba(10,40,66,0.55); border: 2px solid #3f7ea8; border-radius: 12px; }
  .lb-row.mine { border-color: #ffe86e; background: rgba(90,70,10,0.35); }
  .lb-row .lbrank { flex: none; width: 34px; font-weight: 900; color: #ffe86e; font-size: 15px; text-align: center; }
  .lb-row .lbname { flex: 1; min-width: 0; font-weight: 900; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lb-row .lblv { flex: none; padding: 1px 8px; border-radius: 999px; background: linear-gradient(#ffe86e, #f5b21b); color: #6b4a00; font-weight: 900; font-size: 11px; }
  .lb-row .lbval { flex: none; font-weight: 900; color: #8fe07a; min-width: 56px; text-align: right; }
  .lb-mine-note { text-align: center; color: #cfeaff; font-weight: 800; font-size: 12px; padding: 4px; }
  /* claim celebration: flying coins, floating reward tag, one green pulse on the card */
  .claim-coin { position: fixed; z-index: 60; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 50%; pointer-events: none;
    background: radial-gradient(circle at 35% 30%, #fff3b0, #f5b21b 60%, #b97e08); border: 1px solid #8a5e06;
    transition: transform .55s cubic-bezier(.5,-0.25,.65,1), opacity .55s ease-in; }
  .claim-float { position: fixed; z-index: 61; transform: translate(-50%, -50%); pointer-events: none; white-space: nowrap;
    font-weight: 900; font-size: 19px; color: #ffe86e; text-shadow: 0 2px 6px rgba(0,0,0,0.65);
    animation: claimFloat 1.4s ease-out forwards; }
  @keyframes claimFloat { 0% { opacity: 0; margin-top: 0; } 12% { opacity: 1; } 100% { opacity: 0; margin-top: -72px; } }
  .prog-card.just-claimed { animation: claimPulse .8s ease-out; }
  @keyframes claimPulse { 0% { box-shadow: 0 0 0 0 rgba(143,224,122,0.9); } 100% { box-shadow: 0 0 0 20px rgba(143,224,122,0); } }
  .prog-card button.yellow:active { transform: scale(0.92); }
  /* ===== 任務 / 成就 v2 (docs/quest-achievement-v2.md §4) ===== */
  .prog-card.ready { border-color: #ffe86e; box-shadow: 0 0 0 2px rgba(255,232,110,0.25); }
  .prog-card.secret { opacity: 0.78; border-style: dashed; }
  .prog-card.secret .pdesc { font-style: italic; }
  .prog-card .picon.badge { background: radial-gradient(circle at 50% 40%, rgba(255,255,255,0.22), rgba(127,205,238,0.10)); border: 2px solid transparent; width: 44px; height: 44px; }
  .prog-card .picon.badge img { width: 38px; height: 38px; object-fit: contain; }
  .prog-card .picon.badge.locked img { filter: grayscale(1) brightness(0.75); opacity: 0.8; }
  .prog-card .picon.badge.bronze { border-color: #c47b3a; }
  .prog-card .picon.badge.silver { border-color: #cfd8e3; }
  .prog-card .picon.badge.gold { border-color: #ffd23f; box-shadow: 0 0 10px rgba(255,210,63,0.35); }
  .prog-card .picon.badge.diamond { border-color: #8fe7ff; box-shadow: 0 0 12px rgba(143,231,255,0.45); }
  .prog-card.done .picon.badge img { animation: badgeReveal .6s ease-out; }
  @keyframes badgeReveal { 0% { filter: grayscale(1); transform: scale(0.8); } 100% { filter: none; transform: none; } }
  .ptiers { display: inline-flex; gap: 3px; margin-left: 8px; vertical-align: middle; }
  .ptiers i { width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,0.22); display: inline-block; }
  .ptiers i.on { background: #ffe86e; box-shadow: 0 0 4px rgba(255,232,110,0.7); }
  .punlock { font-size: 10.5px; font-weight: 800; color: #b8f0ff; text-align: right; max-width: 150px; }
  .pshow { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
  .pill.pmini { padding: 3px 9px; font-size: 11px; }
  .pill.preroll { margin-top: 6px; padding: 3px 9px; font-size: 11px; display: inline-flex; align-items: center; gap: 4px; }
  .pill.claim-all { align-self: flex-end; padding: 6px 14px; font-size: 13px; }
  .pill.pfold { align-self: center; padding: 5px 14px; font-size: 12px; display: inline-flex; align-items: center; gap: 5px; margin-top: 4px; }
  .panel-tabs { flex-wrap: wrap; }
  .pill.ptab { position: relative; padding: 5px 11px; font-size: 12px; }
  .pill.ptab .qdot { position: absolute; top: -6px; right: -6px; }
  .qhead { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 12px;
    background: rgba(255,232,110,0.10); border: 2px solid rgba(255,232,110,0.35); }
  .qhead-l { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
  .qhead-l b { color: #fff; font-size: 14px; }
  .qbar { height: 8px; border-radius: 999px; background: rgba(255,255,255,0.14); overflow: hidden; }
  .qbar i { display: block; height: 100%; background: linear-gradient(#ffe86e, #f5b21b); }
  .qreset { color: #cfeaff; font-size: 11px; font-weight: 800; }
  .qchest { flex: none; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 10px; border-radius: 12px; cursor: pointer;
    font-family: inherit; color: #fff; background: rgba(10,40,66,0.55); border: 2px solid #3f7ea8; }
  .qchest img { width: 44px; height: 44px; object-fit: contain; filter: grayscale(0.9) brightness(0.8); }
  .qchest span { font-size: 11px; font-weight: 900; }
  .qchest small { font-size: 10px; font-weight: 800; color: #ffe86e; display: inline-flex; align-items: center; gap: 3px; }
  .qchest.ready { border-color: #ffe86e; background: rgba(90,70,10,0.45); animation: chestWobble 1.4s ease-in-out infinite; }
  .qchest.ready img { filter: none; }
  .qchest.opened img { filter: none; opacity: 0.7; }
  .qchest:disabled { cursor: default; }
  @keyframes chestWobble { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-3deg); } 75% { transform: rotate(3deg); } }
  .qweek-head { display: flex; align-items: baseline; justify-content: space-between; margin-top: 8px; padding: 0 4px; color: #fff; }
  .qweek-head b { font-size: 14px; } .qweek-head span { font-size: 11px; font-weight: 800; color: #cfeaff; }
  /* 展示徽章 + 稱號: seats / personal card / shared */
  .sbadges { display: inline-flex; align-items: center; gap: 2px; margin-left: 5px; vertical-align: middle; }
  .sbadge { object-fit: contain; border-radius: 50%; background: rgba(255,255,255,0.2); border: 1.5px solid #c47b3a; }
  .sbadge.silver { border-color: #cfd8e3; } .sbadge.gold { border-color: #ffd23f; } .sbadge.diamond { border-color: #8fe7ff; }
  .ptitle { display: inline-block; font-size: 0.82em; font-weight: 900; color: #ffe27a; text-shadow: 0 1px 2px rgba(0,0,0,0.45); letter-spacing: 0.3px; }
  .slot .slot-title { font-size: clamp(10px, 1.3vmin, 13px); line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sp-shelf { display: flex; align-items: center; gap: 8px; margin-top: 8px; padding: 7px 10px; border-radius: 12px;
    background: rgba(255,255,255,0.14); border: 2px solid rgba(255,255,255,0.35); color: #fff; min-height: 34px; }
  .sp-shelf.mine { cursor: pointer; } .sp-shelf.mine:hover { background: rgba(255,255,255,0.22); }
  .sp-shelf .sbadges { margin: 0; gap: 6px; } .sp-shelf .ptitle { font-size: 13px; }
  .sp-shelf-empty { font-size: 11.5px; font-weight: 800; opacity: 0.8; }
  .sp-shelf-n { margin-left: auto; font-size: 12px; font-weight: 900; color: #ffe86e; }
  /* 有獎勵可領 toast */
  .reward-toast { position: fixed; left: 50%; top: max(12px, env(safe-area-inset-top)); transform: translateX(-50%); z-index: 46;
    display: inline-flex; align-items: center; gap: 8px; padding: 9px 16px; border-radius: 999px; cursor: pointer; font-family: inherit;
    background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; font-weight: 900; font-size: 13.5px; border: 2px solid #ffedb0;
    box-shadow: 0 8px 24px rgba(0,0,0,0.4); animation: frToastIn .34s cubic-bezier(.2,1.5,.4,1); }
  .reward-toast.out { opacity: 0; transition: opacity .3s; }
  @media (max-width: 600px) { .qhead { flex-direction: column; align-items: stretch; } .qchest { flex-direction: row; justify-content: center; gap: 8px; } }
  /* the shop is tapped, not read: kill text selection (the blue reverse-video block
     that showed up when you tapped a name twice) and the mobile tap flash */
  #shop { position: fixed; inset: 0; z-index: 30; display: none; background: radial-gradient(120% 90% at 50% -10%, #6fd3f4 0%, #2ea6e0 45%, #1d7fc4 100%);
    -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; }
  #shop.show { display: block; }
  #shop .arc-screen { width: 100%; height: 100%;
    background: linear-gradient(rgba(10,30,52,0.20), rgba(10,30,52,0.34)), url("assets/shopping.webp") center center / 100% 100% no-repeat; }
  /* no blue navbar — let the Back / title / coins float over the shop scene */
  #shop .arc-header { background: transparent; border-bottom: 0; }
  #shop .arc-title { text-shadow: 0 2px 6px rgba(0,0,0,0.65); }
  .coinbal { font-weight: 900; font-size: clamp(16px, 2.2vw, 22px); color: #fff; background: rgba(0,0,0,0.22); padding: 6px 14px; border-radius: 999px; }
  .shop-body { flex: 1; display: flex; gap: clamp(14px, 3vw, 36px); padding: clamp(16px, 3vh, 32px) clamp(16px, 5vw, 80px); overflow: hidden; width: 100%; max-width: 1200px; margin: 0 auto; box-sizing: border-box; }
  .shop-preview { flex: none; width: clamp(160px, 22vw, 240px); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; background: linear-gradient(#bfe9ff, #8fd0f4); border: 3px solid #fff; border-radius: 18px; box-shadow: inset 0 -8px 16px rgba(0,0,0,0.12); }
  .shop-preview canvas { width: 90%; height: auto; }
  .shop-prevlabel { font-weight: 900; color: #134d77; }
  .shop-chars { display: grid; grid-template-columns: repeat(3, auto); gap: 0; justify-content: center; align-items: center; }
  .shop-char { width: clamp(64px, 8.5vw, 116px); height: clamp(64px, 8.5vw, 116px); margin: -14px; cursor: pointer;
    background: center/contain no-repeat; opacity: 0.55; transition: transform .08s, opacity .08s; }
  .shop-char.sel { position: relative; z-index: 2; }
  .shop-char.sel { opacity: 1; transform: scale(1.12); filter: drop-shadow(0 3px 5px rgba(0,0,0,0.3)); }
  .shop-char:hover { opacity: 0.85; }
  .shop-char.empty { background: none; cursor: default; pointer-events: none; opacity: 0; }
  .shop-main { flex: 1; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
  .shop-tabs { flex: none; display: flex; gap: 10px; }
  .shop-tabs .pill { padding: 8px 20px; font-size: clamp(13px, 1.4vw, 16px); }
  .shop-tabs .pill.sel { outline: 3px solid #ffe14d; }
  .shop-grid { flex: 1; display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: clamp(10px, 1.6vw, 18px); overflow-y: auto; align-content: start; padding: 2px; }
  .shop-card { background: linear-gradient(#fff7e6, #ffe9bf); border: 3px solid #fff; border-radius: 16px; padding: 12px; display: flex; flex-direction: column; align-items: center; gap: 8px; box-shadow: 0 4px 0 rgba(0,0,0,0.12); }
  .shop-pic { width: 100%; height: clamp(80px, 12vh, 120px); display: flex; align-items: center; justify-content: center; background: radial-gradient(circle at 50% 40%, #fff 0%, #ffedc6 75%); border-radius: 12px; }
  .shop-pic img { max-width: 86%; max-height: 92%; object-fit: contain; filter: drop-shadow(0 3px 4px rgba(0,0,0,0.25)); }
  .shop-name { font-weight: 900; color: #6b3b00; font-size: clamp(13px, 1.2vw, 16px); text-align: center; }
  .shop-card .pill { width: 100%; }
  .shop-card .pill.equipped { outline: 3px solid #ffe14d; }
  .shop-card.trying { border-color: #ffe14d; box-shadow: 0 0 0 3px #ffe14d, 0 4px 0 rgba(0,0,0,0.12); }
  .shop-pic { cursor: pointer; }
  .shop-hint { flex: none; color: #eaf7ff; font-size: 13px; text-align: center; text-shadow: 0 1px 3px rgba(0,0,0,0.6); }
  .shop-touch-controls { display: none; }
  .lobby-shopbar { flex: none; display: flex; justify-content: center; padding: 8px 12px 12px; }
  .lobby-shopbar .pill { font-size: clamp(14px, 1.6vw, 18px); padding: 10px 22px; }

  /* These rules intentionally follow the base shop declarations: the previous
     phone rule was overridden by shop-body's later overflow:hidden. */
  @media (max-width: 720px) {
    #shop .arc-screen { min-height: 0; overflow: hidden; }
    #shop .shop-body { flex-direction: column; min-height: 0; overflow-y: auto;
      -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
      padding: 10px 12px calc(18px + env(safe-area-inset-bottom)); gap: 10px; }
    #shop .shop-preview, #shop .shop-main { flex: none; width: 100%; max-width: none; box-sizing: border-box; }
    #shop .shop-preview { flex-direction: row; flex-wrap: wrap; justify-content: center; padding: 10px; }
    #shop .shop-preview canvas { width: min(42vw, 180px); }
    #shop .shop-prevlabel { width: 46%; font-size: 12px; text-align: center; }
    #shop .shop-tabs { flex-wrap: wrap; gap: 6px; }
    #shop .shop-tabs .pill { padding: 7px 12px; }
    #shop .shop-grid { flex: none; overflow: visible; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    #shop .shop-hint { padding-bottom: 4px; }
    .shop-touch-controls { width: min(46%, 170px); display: grid; grid-template-columns: repeat(3, 42px);
      grid-template-rows: repeat(3, 38px); justify-content: center; align-items: center; gap: 3px; touch-action: none; }
    .shop-touch-controls button { width: 42px; height: 38px; padding: 0; border: 2px solid rgba(255,255,255,.9);
      border-radius: 11px; color: #fff; background: linear-gradient(#48bcec,#1686c6); font-size: 22px;
      font-weight: 900; box-shadow: 0 3px 0 rgba(12,77,118,.45); touch-action: none; }
    .shop-touch-controls button:active, .shop-touch-controls button.held { transform: translateY(2px); box-shadow: 0 1px 0 rgba(12,77,118,.45); }
    .shop-fit-dir.up { grid-column: 2; grid-row: 1; }
    .shop-fit-dir.left { grid-column: 1; grid-row: 2; }
    .shop-fit-bomb { grid-column: 2; grid-row: 2; background: linear-gradient(#ffbc55,#f18423) !important; }
    .shop-fit-dir.right { grid-column: 3; grid-row: 2; }
    .shop-fit-dir.down { grid-column: 2; grid-row: 3; }
    #shop .shop-chars { width: 100%; }
  }

  /* 觀戰 */
  .room-card .rwatch { display: inline-flex; align-items: center; justify-content: center; gap: 5px;
    background: #e3f2ff; color: #1c6aa3; border: 2px solid #9fd0ef; border-radius: 8px;
    padding: 4px 8px; font-size: 12px; font-weight: 900; cursor: pointer; font-family: inherit; }
  .room-card .rwatch:hover { background: #cfe9ff; border-color: #5aa9d6; }
  /* 固定開房時段 banner on the channel stage */
  .ch-window { display: none; margin: 2px auto 6px; padding: 5px 14px; border-radius: 999px;
    font-size: 13px; font-weight: 800; letter-spacing: 0.2px; max-width: 92%;
    background: rgba(20,40,62,0.55); border: 1px solid rgba(160,210,245,0.45); color: #dcefff; }
  .ch-window.show { display: inline-block; }
  .ch-window.live { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; }

  /* result-screen hooks — the row of calls to action under the score panel */
  #overHooks { position: fixed; left: 0; right: 0; bottom: max(14px, env(safe-area-inset-bottom));
    z-index: 45; display: none; justify-content: center; flex-wrap: wrap; gap: 8px; padding: 0 12px; }
  #overHooks.show { display: flex; }
  #overHooks button { pointer-events: auto; cursor: pointer; font-family: inherit; font-weight: 900; font-size: 14px;
    padding: 9px 16px; border-radius: 999px; border: 2px solid rgba(255,255,255,0.5);
    background: rgba(20,40,62,0.92); color: #eaf6ff; }
  #overHooks button:hover { background: rgba(38,72,105,0.95); }
  #overHooks button.gold { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; border-color: #ffedb0; }
  #overHooks button.gold:hover { background: linear-gradient(#fff0bb, #ffbe3d); }
  #overHooks button:disabled { opacity: 0.6; cursor: default; }
  /* ===== 觀戰狀態 (2026-08-30 重做) =====
     原本是左下角一顆小徽章。左下角在對戰中是最少被看的角落, 而且遊戲內聊天
     (#gameChat) 與觸控搖桿都住在那裡 —— 三個東西擠一格, 結果就是誰都不明顯。
     改成兩個同時存在、互相補強的訊號:
       1. #specDock  畫面正上方的橫幅 —— HUD 的左上 (齒輪) 與右上 (計時) 都佔著,
                     正中央是唯一還空著、而且離戰場最近的位置。
       2. #specFrame 一圈貼著視窗邊緣的金框 —— 不佔任何版面、不擋任何格子,
                     但用餘光就知道「我不在場上」。
     兩個都是 pointer-events:none 打底, 只有「離開觀戰」那顆按鈕收得到點擊。 */
  #specDock { position: fixed; top: 8px; left: 50%; transform: translateX(-50%); z-index: 41;
    display: flex; flex-direction: column; align-items: center; gap: 5px;
    max-width: min(560px, calc(100vw - 16px)); pointer-events: none; }
  #specBadge { display: none; align-items: center; gap: 8px; max-width: 100%;
    background: linear-gradient(rgba(28,40,60,0.94), rgba(16,26,42,0.94)); color: #ffd34d;
    border: 2px solid rgba(255,211,77,0.85); border-radius: 999px;
    padding: 7px 8px 7px 14px; font-size: 15px; font-weight: 900; letter-spacing: 0.2px;
    box-shadow: 0 6px 22px rgba(0,0,0,0.45), 0 0 0 4px rgba(255,211,77,0.10);
    animation: specIn 0.26s ease-out; }
  #specBadge.show { display: flex; }
  #specBadge .sp-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* 呼吸的紅點: 靜止的徽章會被當成背景, 會動的不會 */
  #specBadge .sp-live { flex: none; width: 9px; height: 9px; border-radius: 50%; background: #ff5a4d;
    box-shadow: 0 0 0 0 rgba(255,90,77,0.7); animation: specPulse 1.9s ease-out infinite; }
  #specLeaveBtn { pointer-events: auto; flex: none; padding: 5px 13px; border-radius: 999px; cursor: pointer;
    background: rgba(255,255,255,0.16); border: 1px solid rgba(255,255,255,0.45); color: #fff;
    font-family: inherit; font-weight: 800; font-size: 13px; white-space: nowrap; }
  #specLeaveBtn:hover { background: rgba(255,255,255,0.30); }
  #specLeaveBtn:active { transform: translateY(1px); }
  /* 入座: 觀戰者能坐下的時機只有等待畫面 + 還有空位 (main.js 決定亮不亮)。
     綠色 = 動作, 跟旁邊中性的「離開觀戰」分得開。 */
  #specJoinBtn { display: none; pointer-events: auto; flex: none; padding: 5px 14px; border-radius: 999px; cursor: pointer;
    background: linear-gradient(#6fdc6f, #2faa4a); border: 1px solid rgba(255,255,255,0.85); color: #fff;
    font-family: inherit; font-weight: 900; font-size: 13px; white-space: nowrap;
    box-shadow: 0 2px 0 rgba(0,0,0,0.20), inset 0 2px 0 rgba(255,255,255,0.30); }
  #specJoinBtn.show { display: block; }
  #specJoinBtn:hover { filter: brightness(1.08); }
  #specJoinBtn:active { transform: translateY(1px); }
  /* 等待畫面的橫幅: 房間畫面自己讓出頂端一條, 橫幅住在那一條裡。
     那一列在房間畫面本來就滿了 (房名在中間、邀請連結與造型在右), 直接 fixed 疊上去
     一定會擋到其中一個 —— 讓出一條才是不會踩到任何人的做法。 */
  body.spec-room #lobbyRoom { box-sizing: border-box; padding-top: 48px; }
  body.spec-room #specDock { top: 7px; }
  #specList { display: none; align-items: center; gap: 6px; max-width: 100%; overflow: hidden;
    background: rgba(20,30,45,0.80); color: #cfe6ff; border: 1px solid rgba(140,190,240,0.5); border-radius: 999px;
    padding: 4px 12px; font-size: 12.5px; font-weight: 700; white-space: nowrap; text-overflow: ellipsis; }
  #specList.show { display: flex; }
  #specList svg { flex: none; }
  #specList #specNames { overflow: hidden; text-overflow: ellipsis; }
  /* 邊框訊號。inset box-shadow 不參與版面, 所以它在任何尺寸、任何方向都不會推擠棋盤 */
  #specFrame { position: fixed; inset: 0; z-index: 39; display: none; pointer-events: none;
    box-shadow: inset 0 0 0 3px rgba(255,211,77,0.55), inset 0 0 34px rgba(255,211,77,0.16);
    animation: specFrameIn 0.3s ease-out; }
  #specFrame.show { display: block; }
  @keyframes specIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }
  @keyframes specFrameIn { from { opacity: 0; } to { opacity: 1; } }
  @keyframes specPulse { 0% { box-shadow: 0 0 0 0 rgba(255,90,77,0.65); }
    70% { box-shadow: 0 0 0 7px rgba(255,90,77,0); } 100% { box-shadow: 0 0 0 0 rgba(255,90,77,0); } }
  /* 手機直向: 頂端那條 HUD 帶已經有齒輪與計時, 橫幅縮一號並讓出寬度 */
  @media (max-width: 600px) {
    /* 窄螢幕的頂端那一列已經被齒輪 (左) 與計時 (右) 佔滿, 正中央塞不下第三個東西。
       往下讓一列 —— 那一列是 #gameLeaveBtn 的位置, 而觀戰者本來就沒有那顆按鈕
       (main.js 的 gameLeave 條件有 !spectating), 所以整條是空的。 */
    #specDock { top: 50px; gap: 4px; max-width: calc(100vw - 12px); }
    #specBadge { font-size: 13px; padding: 5px 6px 5px 11px; gap: 6px; border-width: 1.5px; }
    #specLeaveBtn { font-size: 11.5px; padding: 4px 10px; }
    /* 入座是這條橫幅上唯一的動作, 直向給它比旁邊中性按鈕大一點的觸控面積 */
    #specJoinBtn { font-size: 12.5px; padding: 7px 13px; }
    /* 橫幅放在頂列下面一列, 跟對戰中的排法一致 (那裡的 dock 也在 50px)。
       2026-09-17 拆掉「建議轉橫向」提示後位置刻意不動 */
    body.spec-room #lobbyRoom { padding-top: 95px; }
    body.spec-room #specDock { top: 52px; }
    #specList { font-size: 11.5px; padding: 3px 10px; }
  }
  /* 橫向的矮視窗 (手機轉橫): 垂直空間才是稀缺的, 壓扁高度、不要疊第二行 */
  @media (max-height: 460px) {
    #specDock { top: 4px; flex-direction: row; gap: 6px; }
    #specBadge { padding: 4px 5px 4px 10px; font-size: 12.5px; }
    #specList { max-width: 34vw; }
    body.spec-room #lobbyRoom { padding-top: 38px; }
    body.spec-room #specDock { top: 4px; }
  }
  @media (prefers-reduced-motion: reduce) {
    #specBadge, #specFrame { animation: none; }
    #specBadge .sp-live { animation: none; box-shadow: none; }
  }

  /* in-game chat (Enter to talk when no local 2P) */
  #gameChat { position: fixed; left: 12px; bottom: 46px; z-index: 40; width: min(320px, 42vw);
    display: none; flex-direction: column; align-items: flex-start; gap: 5px; }
  #gameChat.show { display: flex; }
  @media (pointer: coarse) { #gameChat { bottom: 150px; } }   /* clear the touch joystick */
  #gameChatLog { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; width: 100%; }
  .gc-line { background: rgba(16,30,46,0.72); color: #fff; border-radius: 10px; padding: 4px 10px;
    font-size: 13px; max-width: 100%; overflow-wrap: anywhere; animation: gcfade 15s forwards; }
  .gc-line .cwho { color: #ffd34d; font-weight: 700; margin-right: 5px; }
  @keyframes gcfade { 0%, 87% { opacity: 1; } 100% { opacity: 0; } }
  /* Enter open: the feed becomes the PERSISTENT conversation — no fading, scrollable */
  #gameChat.open #gameChatLog { max-height: 42vh; overflow-y: auto; }
  #gameChat.open .gc-line { animation: none; opacity: 1; }
  #gameChatInput { display: none; width: 100%; box-sizing: border-box; background: rgba(10,22,36,0.85);
    border: 1px solid rgba(140,190,240,0.6); border-radius: 999px; color: #fff; padding: 7px 14px;
    font-size: 14px; outline: none; font-family: inherit; }
  #gameChat.open #gameChatInput { display: block; }

  /* powered-by footer */
  /* credit sits in the bottom-RIGHT corner (was centered, overlapping the dock);
     pointer-events:none guarantees it can never intercept a tap on any button —
     the link itself re-enables clicks on just its own text */
  /* z 80: above every page overlay (shop 30 / panel 30 / auth 40 / dialogs 60-70),
     below system layers (announce 90, reload 95, fade) — the credit is on EVERY page */
  /* 版本標籤: practice-only build stamp, bottom-left, out of everything's way
     (specDock also lives bottom-left but only while SPECTATING — never both) */
  #buildTag { position: fixed; left: 10px; bottom: 8px; z-index: 40; display: none; pointer-events: none;
    font-size: 11px; font-weight: 700; letter-spacing: 0.4px; color: rgba(255,255,255,0.65);
    background: rgba(16,38,58,0.45); border-radius: 999px; padding: 2px 9px; }
  #buildTag.show { display: block; }

  #bpFooter { position: fixed; right: 10px; bottom: 8px; z-index: 80; pointer-events: none;
    color: rgba(255,255,255,0.7); font-size: 11.5px; text-decoration: none; letter-spacing: 0.3px;
    background: rgba(16,38,58,0.5); border-radius: 999px; padding: 3px 12px; }
  #bpFooter strong { pointer-events: auto; }
  #bpFooter strong { color: rgba(255,225,120,0.9); font-weight: 700; }
  #bpFooter:hover { color: #fff; }
  #bpFooter:hover strong { color: #ffe14d; }
  #bpFooter.noclick strong { pointer-events: none; }
  /* room-card frames: the art fills the card; text gets a shadow to stay readable */
  .slot.framed { background-size: cover !important; background-position: center; }
  .slot.framed .pname { color: #fff !important; text-shadow: 0 1px 3px rgba(0,0,0,0.75); }
  /* purchase confirmation dialog */
  #buyConfirm, #nickEdit, #guestPrompt { position: fixed; inset: 0; z-index: 70; display: none; align-items: center; justify-content: center; background: rgba(10,30,50,0.55); }
  #buyConfirm.show, #nickEdit.show, #guestPrompt.show { display: flex; }
  /* guest entry: quieter than the login button, still obviously tappable */
  .auth-guest-hint { color: #cfe8f7; font-size: 12px; font-weight: 700; line-height: 1.5; max-width: 260px; margin: 2px auto 0; text-align: center; opacity: 0.85; }
  /* 分級標示 (遊戲軟體分級管理辦法 §11-13): 法定內容, 不隨介面語言改變。
     標識 60x60, 非限級的法定下限是 45x45 px。卡片外、選單畫面內, 所以登入前
     的第一個畫面就看得到。 */
  .rating-mark { display: flex; align-items: center; gap: 10px; margin: 0 0 2px; padding-bottom: 10px; border-bottom: 1px solid rgba(127,205,238,0.3); text-align: left; }
  .rating-mark img { flex: none; width: 60px; height: 60px; }
  .rating-mark p { margin: 0; max-width: 250px; color: #cfe8f7; opacity: 0.8; font-size: 11px; font-weight: 700; line-height: 1.5; text-shadow: 0 1px 3px rgba(0,0,0,0.6); }
  .rating-mark b { color: #ffe14d; font-weight: 800; }
  .rating-mark span { display: block; }
  /* 「或在這裡登入」的分隔線: 通行證是首選路徑, 本地登入退到它下面 */
  .auth-or { display: flex; align-items: center; gap: 8px; width: 100%; max-width: 260px; margin: 6px auto 2px;
             color: #9fc4dc; font-size: 11px; font-weight: 800; letter-spacing: 1px; text-transform: uppercase; }
  .auth-or::before, .auth-or::after { content: ''; flex: 1; height: 2px; background: rgba(255,255,255,0.14); }
  .iconbtn.gold { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; }
  .iconbtn.gold:hover { background: linear-gradient(#fff0bb, #ffbe3d); color: #5a3800; }
  .acct-edit { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; margin: 0 2px;
    border: none; border-radius: 6px; background: rgba(255,255,255,0.16); color: inherit; cursor: pointer; vertical-align: middle; }
  .acct-edit:hover { background: rgba(255,255,255,0.32); }
  .nick-hint { color: #4a7ba0; font-size: 12.5px; font-weight: 700; margin: 2px 0 10px; max-width: 240px; }
  #nickInput { width: 100%; box-sizing: border-box; padding: 9px 12px; font-size: 16px; font-weight: 800; text-align: center;
    border: 2px solid #bfe6f7; border-radius: 10px; margin-bottom: 12px; color: #134d77; background: #fff; }
  .buy-box { background: linear-gradient(#fff, #eaf6ff); border: 4px solid #bfe6f7; border-radius: 18px; padding: 18px 26px; text-align: center; box-shadow: 0 12px 40px rgba(0,0,0,0.4); min-width: 240px; }
  .buy-title { font-weight: 900; color: #1c6aa3; font-size: 17px; margin-bottom: 10px; }
  #buyConfirmImg { height: 84px; max-width: 150px; object-fit: contain; }
  .buy-name { font-weight: 800; color: #134d77; margin-top: 6px; }
  .buy-price { font-weight: 900; color: #f5980b; margin: 4px 0 12px; }
  .buy-err { font-weight: 800; font-size: 13px; color: #c8412b; margin: -6px 0 10px; }
  .buy-err:empty { display: none; }
  .buy-btns { display: flex; gap: 10px; justify-content: center; }
  /* personal space overlay */
  #spaceView { position: fixed; inset: 0; z-index: 60; display: none; align-items: center; justify-content: center; background: rgba(10,30,50,0.55); }
  #spaceView.show { display: flex; }
  .space-box { background: linear-gradient(#39b6ea, #1f8fd0); border: 4px solid #fff; border-radius: 18px; padding: 12px; box-shadow: 0 12px 40px rgba(0,0,0,0.4); max-width: min(92vw, 800px); max-height: 94vh; overflow-y: auto; }
  .space-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; gap: 10px; }
  .space-title { font-weight: 900; color: #fff; font-size: clamp(16px, 2.4vmin, 22px); text-shadow: 0 2px 0 #15598f; }
  #spaceCv { display: block; width: 100%; height: auto; border-radius: 12px; background: #f3e7d3; }
  /* stats card under the space scene: level pill + XP bar, then a tile row */
  .space-stats { display: none; margin-top: 10px; }
  /* 自我介紹 from the park passport. Empty until it arrives (or forever, for a
     seat with no account), and :empty keeps it from reserving a blank band. */
  .space-bio { margin-top: 9px; font-size: 14px; line-height: 1.55; color: #eaf6ff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.45); white-space: pre-wrap; word-break: break-word; }
  .space-bio:empty { display: none; }
  .space-stats.show { display: block; }
  .sp-toprow { display: flex; align-items: center; gap: 10px; }
  .sp-lv { flex: 0 0 auto; background: linear-gradient(#ffe27a, #f5a80b); color: #6b3d00; font-weight: 900; border: 2px solid #fff; border-radius: 999px; padding: 3px 12px; font-size: 15px; box-shadow: 0 2px 0 rgba(0,0,0,0.18); }
  .sp-xp { flex: 1; min-width: 0; }
  .sp-xp-bar { position: relative; height: 16px; background: rgba(8,50,84,0.45); border: 2px solid rgba(255,255,255,0.55); border-radius: 999px; overflow: hidden; }
  .sp-xp-fill { position: absolute; top: 0; bottom: 0; left: 0; width: 0%; background: linear-gradient(#9ef5b3, #2ecc71); border-radius: 999px; transition: width .5s ease; }
  .sp-xp-text { margin-top: 3px; text-align: right; color: #e8f7ff; font-size: 11.5px; font-weight: 800; }
  .sp-tiles { display: flex; gap: 8px; margin-top: 8px; }
  .sp-tile { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px; background: rgba(255,255,255,0.14); border: 2px solid rgba(255,255,255,0.35); border-radius: 12px; padding: 7px 4px 6px; color: #fff; min-width: 0; }
  .sp-tile svg { opacity: 0.95; }
  .sp-tile .v { font-weight: 900; font-size: 17px; text-shadow: 0 1px 0 rgba(0,0,0,0.25); }
  .sp-tile .l { font-size: 10.5px; font-weight: 800; letter-spacing: 0.4px; opacity: 0.85; }
  .sp-tile.gold svg, .sp-tile.gold .v { color: #ffd94d; }
  .space-hint { color: #e8f7ff; font-weight: 700; font-size: 13px; margin-top: 6px; text-align: center; min-height: 16px; }
  .space-replays { display: none; margin-top: 10px; padding: 9px; border-radius: 12px; background: rgba(8,57,94,0.28); color: #fff; }
  .space-replays.show { display: block; }
  .replay-head { display:flex; justify-content:space-between; gap:8px; align-items:center; font-weight:900; margin-bottom:6px; }
  .replay-row { display:grid; grid-template-columns:1fr auto auto auto; gap:6px; align-items:center; padding:6px 0; border-top:1px solid rgba(255,255,255,.18); font-size:12px; }
  .replay-row button { padding:5px 8px; font-size:11px; }
  .replay-note { font-size:11px; opacity:.82; }
  /* --replay-chrome ≈ everything around the 16/9 canvas (title + controls + share row +
     paddings): the canvas width is capped so that stack always fits the viewport height —
     that keeps the controls on-screen in fullscreen/landscape instead of below the fold. */
  .replay-dialog{--replay-chrome:200px;position:fixed;inset:0;z-index:var(--z-replay);display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(2,15,27,.68);backdrop-filter:blur(4px)}
  .replay-dialog.hidden,.replay-editor.hidden{display:none}
  .replay-box{width:min(960px,96vw);max-height:94vh;overflow:auto;box-sizing:border-box;padding:12px;border:2px solid rgba(255,255,255,.55);border-radius:18px;background:rgba(10,29,46,.97);color:#fff;box-shadow:0 16px 50px rgba(0,0,0,.5)}
  .replay-title{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.replay-title strong{font-size:18px}.replay-title-actions{display:flex;align-items:center;gap:7px}.replay-title .pill{min-height:38px}
  #replayCanvas{display:none}
  #replayCanvas.replay-canvas-slot{display:block;width:min(100%,calc((100dvh - var(--replay-chrome))*16/9));margin:0 auto;aspect-ratio:16/9;background:#07131d;border-radius:10px}
  #game.replay-modal-canvas{position:static;display:block;width:min(100%,calc((100dvh - var(--replay-chrome))*16/9))!important;height:auto!important;margin:0 auto;aspect-ratio:16/9;background:#07131d;border-radius:10px;touch-action:none}
  #game.replay-browser-canvas{position:fixed!important;z-index:calc(var(--z-replay) + 1);display:block;max-width:none;max-height:none;margin:0;border-radius:10px;pointer-events:none;touch-action:none;transform:translateZ(0);backface-visibility:hidden}
  /* fullscreen playback: the share/editor rows hide so the canvas takes the reclaimed height */
  .replay-dialog.replay-fs{--replay-chrome:130px;padding:8px}
  .replay-fs .replay-share-row,.replay-fs .replay-share-menu,.replay-fs .replay-editor{display:none}
  .replay-fs .replay-box{width:100%;max-height:100dvh}
  .replay-controls,.replay-editor{box-sizing:border-box;display:flex;align-items:center;gap:8px;padding:9px 0 0;color:#fff}.replay-editor{flex-wrap:wrap}
  .replay-share-row,.replay-share-menu{display:flex;align-items:center;gap:8px;padding-top:8px;flex-wrap:wrap}.replay-share-menu.hidden{display:none}.replay-share-menu span,.replay-share-row span{font-size:12px;color:#bfe6ff;font-weight:800}
  #replayPlay{flex:none;display:flex;align-items:center;justify-content:center;width:46px;height:46px;min-height:46px;padding:0;border-radius:50%}
  #replayPlay svg{display:block}
  #replayPlay .ic-pause,#replayPlay.playing .ic-play{display:none}
  #replayPlay.playing .ic-pause{display:block}
  #replaySeek{flex:1;min-width:70px;touch-action:pan-x;-webkit-appearance:none;appearance:none;height:30px;margin:0;background:transparent;cursor:pointer}
  #replaySeek::-webkit-slider-runnable-track{height:8px;border-radius:999px;background:linear-gradient(to right,#ffd84a var(--p,0%),rgba(255,255,255,.28) var(--p,0%))}
  #replaySeek::-webkit-slider-thumb{-webkit-appearance:none;width:22px;height:22px;margin-top:-7px;border-radius:50%;background:#ffd84a;border:2px solid #fff;box-shadow:0 1px 4px rgba(0,0,0,.4)}
  #replaySeek::-moz-range-track{height:8px;border-radius:999px;background:rgba(255,255,255,.28)}
  #replaySeek::-moz-range-progress{height:8px;border-radius:999px;background:#ffd84a}
  #replaySeek::-moz-range-thumb{width:22px;height:22px;border-radius:50%;background:#ffd84a;border:2px solid #fff;box-sizing:border-box}
  .replay-speed { border-radius:8px; padding:6px; background:#eaf7ff; color:#134d77; font-weight:800; }
  @media (max-width:600px){
    .replay-dialog{padding:4px;align-items:center;overflow:hidden}
    .replay-box{width:100%;max-height:calc(100dvh - 8px);padding:8px;border-radius:12px;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
    .replay-title{margin-bottom:5px}.replay-title strong{font-size:15px}
    .replay-controls{display:grid;grid-template-columns:auto minmax(90px,1fr) auto;gap:6px;padding-top:6px}
    #replayTime{grid-column:2/4;text-align:right;font-size:12px}
    .replay-controls .pill,.replay-speed{min-height:38px}
    .replay-editor,.replay-share-row,.replay-share-menu{gap:5px;padding-top:6px}
    .replay-editor .pill,.replay-share-row .pill,.replay-share-menu .pill{font-size:11px;padding:6px 8px;min-height:36px}
  }
  .slot-activity{margin-top:4px;padding:2px 7px;border-radius:999px;background:#7657b7;color:#fff;font-size:10px;font-weight:900;white-space:nowrap}.slot-activity.shop{background:#c77a16}

  /* ===== Practice mode panel (練習模式) ===== */
  /* in-game settings quartet, dropped below the HUD gear (top-left) */
  /* 對戰中: 面板從齒輪正下方展開, 而「離開對戰」就在那裡 (實測 390x844: 面板
     12,52 289x533 整顆蓋住 10,50 122x42 的離開對戰, 點它的中心點到的是面板標題)。
     對戰中就讓面板落在那顆按鈕下面; 大廳沒有那顆按鈕, 維持原位。 */
  #gameSettings:not(.lobby-mode) { top: calc(var(--hud-leave-top) + 50px);
    max-height: calc(100dvh - var(--hud-leave-top) - 62px); }
  #gameSettings { position: fixed; left: 12px; top: 52px; z-index: 45; display: none; flex-direction: column; gap: 6px; padding: 10px;
    background: rgba(10,40,66,0.92); border: 2px solid #7fcdee; border-radius: 14px; }
  #gameSettings.show { display: flex; }
  #gameSettings .pill { font-size: 13px; padding: 8px 14px; text-align: left; }
  /* volume sliders under their mute pills */
  #gameSettings .gsvol { display: flex; align-items: center; gap: 8px; padding: 0 4px 2px; }
  #gameSettings .gsvol span { font-size: 11px; font-weight: 700; color: #bfe6ff; white-space: nowrap; }
  #gameSettings .gsvol input[type=range] { flex: 1; min-width: 90px; accent-color: #5cc3f2; touch-action: none; }
  #gameSettings .gsvol b { font-size: 11px; color: #fff; min-width: 34px; text-align: right; }
  /* the panel opens from a header gear too, so it has to fit next to a right-hand
     button and stay inside a short screen once the language row is in it */
  #gameSettings { max-width: min(280px, calc(100vw - 24px)); max-height: calc(100dvh - 70px); overflow-y: auto; }
  #gameSettings.at-right { left: auto; right: 12px; }
  #gameSettings .gstitle { font-size: 13px; font-weight: 900; color: #fff; letter-spacing: .04em; padding: 0 2px 2px; }
  #gameSettings .gssec { font-size: 11px; font-weight: 800; color: #bfe6ff; padding: 2px 2px 0; }
  #gameSettings .gs-language-row { display:flex; align-items:center; gap:6px; min-width:0; }
  #gameSettings .gs-language-row .gssec { flex:none; padding:0; }
  #gameSettings .gslangs { display: flex; flex-wrap: nowrap; gap: 3px; min-width:0; padding: 0; }
  #gameSettings .gslang { flex: none; min-width:0; font-size: 11px; padding: 5px 7px; text-align: center; white-space:nowrap; }
  #gameSettings .gslang.sel { background: #ffd84a; color: #0d2b45; border-color: #fff; }
  /* board-only rows (zoom, arrow, nicknames, blast hint, wide view) */
  #gameSettings.lobby-mode [data-gs-ingame] { display: none; }
  /* menu screen: the gear sits in the same row as the mute / sfx pills */
  .setbtn { position: static; }
  /* 浮在棋盤上的按鈕要跟 canvas 畫的 HUD 一起排。HUD 照
     hud.scale = clamp(0.85, min(W,H)/720, 2.4) 放大 (js/hud.js), 所以寫死 px 在大螢幕
     會被蓋到: 齒輪的點擊圓下緣在 50*scale, 1920x1080 (scale 1.5) 是 75px, 而「離開對戰」
     從 56px 開始 —— 對著齒輪下緣按下去的是離開對戰。50*scale 換成 vmin 就是 6.95vmin,
     上下界對應 scale 被夾住的 0.85 與 2.4。 */
  :root { --hud-leave-top: clamp(56px, calc(6.95vmin + 8px), 128px); }
  /* in-match leave button: same spot as the practice Exit (the two never coexist) */
  #gameLeaveBtn { position: fixed; left: 10px; right: auto; top: var(--hud-leave-top); z-index: 40; display: none; align-items: center; gap: 6px; padding: 9px 16px; font-size: 14px; font-weight: 800; }
  #gameLeaveBtn.show { display: inline-flex; }
  /* the /help entry: a real link (crawlable), styled like the header's icon buttons */
  a#helpLink { text-decoration: none; }
  /* CJK breaks between any two characters, which was splitting 利用規約 / 服務條款
     across lines. Keep each link's words whole; the row still wraps between them. */
  .auth-guest-hint a { color: #ffd94d; font-weight: 800; word-break: keep-all; white-space: nowrap; }
  /* 同樣的道理, 右上角: 「已淘汰 — 觀戰中」那行畫在 70*scale, 字高約 ±10*scale,
     所以下緣是 80*scale = 11.2vmin。1920x1080 寫死的 102px 會被那行字穿過去。 */
  #againBtn { position: fixed; right: 10px; top: clamp(102px, calc(11.2vmin + 10px), 202px); z-index: 40; display: none; align-items: center; gap: 6px; padding: 9px 16px; font-size: 14px; font-weight: 800; }
  #againBtn.show { display: inline-flex; }
  /* 嫩芽標記: room cards and seat cards. Deliberately friendly, never a rank badge. */
  .sprout-tag { display: inline-flex; align-items: center; gap: 3px; margin-left: 6px;
    padding: 1px 6px; border-radius: 999px; font-size: 11px; font-weight: 800;
    color: #0e3a1d; background: #9ce6a8; vertical-align: middle; }
  .sprout-tag svg { display: block; }

  /* ===== 新手教學 panel: instruction, not HUD — top-centre, out of the thumbs' way ===== */
  #tutorPanel { position: fixed; left: 50%; transform: translateX(-50%); top: 56px; z-index: 45;
    width: min(92vw, 460px); display: flex; flex-direction: column; gap: 8px; pointer-events: none;
    transition: width 0.2s ease; }
  /* 收合: after a few seconds the card shrinks to a single bar, because the board is
     what the learner needs to look at. Tap it to read the instruction again. */
  #tutorPanel.compact { width: min(78vw, 300px); }
  #tutorPanel.compact .tt-hint,
  #tutorPanel.compact .tt-controls,
  #tutorPanel.compact .tt-legend,
  #tutorPanel.compact .tt-actions { display: none; }
  #tutorPanel.compact .tt-card { padding: 6px 10px; gap: 5px; opacity: 0.9; }
  #tutorPanel.compact .tt-title { font-size: 13px; }
  .tt-card { cursor: pointer; }
  #tutorPanel.hidden { display: none; }
  #tutorPanel > * { pointer-events: auto; }
  .tt-card { background: rgba(18,38,58,0.9); border: 2px solid rgba(255,255,255,0.35); border-radius: 14px;
    padding: 10px 12px; display: flex; flex-direction: column; gap: 7px; color: #fff; box-shadow: 0 6px 20px rgba(0,0,0,0.3); }
  .tt-card.hidden, .tt-clear.hidden { display: none; }
  .tt-head { display: flex; align-items: baseline; gap: 8px; }
  .tt-stage { font-size: 12px; font-weight: 800; color: #ffd94d; letter-spacing: 0.4px; flex: none; }
  .tt-title { font-size: 16px; font-weight: 900; }
  .tt-hint { font-size: 13px; line-height: 1.45; color: rgba(255,255,255,0.9); }
  .tt-controls { font-size: 12px; line-height: 1.35; font-weight: 900; color: #ffe27a;
    border: 1px solid rgba(255,226,122,0.35); border-radius: 7px; padding: 4px 7px; }
  .tt-demo-state { font-size: 13px; font-weight: 900; text-align: center; color: #9fffc5;
    background: rgba(20,90,60,0.55); border-radius: 7px; padding: 5px 7px; }
  .tt-barwrap { position: relative; height: 16px; border-radius: 8px; background: rgba(255,255,255,0.16); overflow: hidden; }
  .tt-bar { position: absolute; inset: 0 auto 0 0; width: 0; background: linear-gradient(90deg,#7fd4ff,#ffd94d); transition: width 0.18s ease-out; }
  .tt-goal { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 11px; font-weight: 900; color: #0d2233; text-shadow: 0 1px 0 rgba(255,255,255,0.35); }
  .tt-legend { font-size: 12px; line-height: 1.4; color: #bfe6ff; }
  .tt-flash { font-size: 12px; font-weight: 800; color: #ffb0a0; }
  .tt-actions { display: flex; gap: 6px; }
  .tt-actions .pill { flex: 1; padding: 7px 10px; font-size: 13px; font-weight: 800; }
  .tt-clear { background: rgba(18,38,58,0.94); border: 2px solid #ffd94d; border-radius: 16px;
    padding: 16px; display: flex; flex-direction: column; align-items: center; gap: 10px; color: #fff; }
  .tt-clear-title { font-size: 20px; font-weight: 900; color: #ffd94d; }
  .tt-clear-reward { font-size: 14px; font-weight: 700; }
  /* 全通 card, lobby side */
  .tut-all { position: fixed; inset: 0; z-index: 96; display: none; align-items: center; justify-content: center;
    background: rgba(6,14,26,0.72); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
  .tut-all.show { display: flex; }
  .tut-all-box { background: linear-gradient(180deg, rgba(30,58,86,0.98), rgba(18,38,58,0.98));
    border: 2px solid #ffd94d; border-radius: 18px; padding: 26px 30px; text-align: center;
    display: flex; flex-direction: column; gap: 12px; color: #fff; max-width: 90vw; }
  .tut-all-title { font-size: 22px; font-weight: 900; color: #ffd94d; }
  .tut-all-body { font-size: 15px; line-height: 1.5; }
  @media (pointer: coarse) { #tutorPanel { top: 6px; width: 94vw; } .tt-hint { font-size: 12px; } }

  #practicePanel { position: fixed; right: 10px; top: 56px; z-index: 40; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
  #practicePanel.hidden { display: none; }
  .pr-top { display: flex; gap: 8px; }
  .pr-top .pill { display: inline-flex; align-items: center; gap: 6px; padding: 9px 16px; font-size: 14px; font-weight: 800; }
  #prExit { background: rgba(18,38,58,0.8); color: #fff; border-color: rgba(255,255,255,0.55); }
  #prBody { width: 210px; max-height: min(72vh, 480px); overflow-y: auto; background: rgba(18,38,58,0.82);
    border: 2px solid rgba(255,255,255,0.35); border-radius: 14px; padding: 10px; display: flex; flex-direction: column; gap: 8px; color: #fff; }
  #practicePanel.closed #prBody { display: none; }
  /* forced-reload overlay (new version / blue-green cutover) */
  #reloadOverlay { position: fixed; inset: 0; z-index: 110; display: none; align-items: center; justify-content: center;
    background: rgba(6,14,26,0.82); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
  #reloadOverlay.show { display: flex; }
  .reload-box { display: flex; flex-direction: column; align-items: center; gap: 16px; color: #eaf4ff; text-align: center; padding: 24px; }
  .reload-spin { width: 44px; height: 44px; border-radius: 50%; border: 4px solid rgba(255,255,255,0.2); border-top-color: #ffcf5a; animation: reloadSpin 0.8s linear infinite; }
  @keyframes reloadSpin { to { transform: rotate(360deg); } }
  .reload-text { font-weight: 800; font-size: 16px; letter-spacing: 0.3px; }

  /* system announcement banner (server-wide, admin-only) */
  #sysAnnounce { position: fixed; top: 0; left: 0; right: 0; z-index: 90; display: none;
    align-items: center; gap: 10px; padding: 10px 14px; box-sizing: border-box;
    background: linear-gradient(180deg, rgba(242,90,70,0.97), rgba(210,60,45,0.97));
    color: #fff; font-weight: 800; font-size: 15px; letter-spacing: 0.3px;
    box-shadow: 0 3px 12px rgba(0,0,0,0.35); text-shadow: 0 1px 0 rgba(0,0,0,0.2); }
  #sysAnnounce.show { display: flex; }
  #sysAnnounce svg { flex: none; opacity: 0.95; }
  #sysAnnounceText { flex: 1; min-width: 0; }
  #sysAnnounceClose { flex: none; display: flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border: none; border-radius: 8px; cursor: pointer;
    background: rgba(255,255,255,0.2); color: #fff; }
  #sysAnnounceClose:hover { background: rgba(255,255,255,0.35); }
  @media (pointer: coarse) { #sysAnnounce { font-size: 13.5px; padding: 8px 12px; } }

  .pr-maps { display: flex; flex-direction: column; }
  .pr-maps .dropdown { margin-top: 4px; padding-top: 7px; padding-bottom: 7px; font-size: 13px; }
  #prStats { display: flex; flex-direction: column; gap: 6px; }
  .pr-row { display: flex; align-items: center; gap: 6px; }
  .pr-name { flex: 1; font-size: 12.5px; font-weight: 800; letter-spacing: 0.3px; }
  .pr-btn { display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 8px;
    background: rgba(255,255,255,0.16); border: 1.5px solid rgba(255,255,255,0.4); color: #fff; cursor: pointer; }
  .pr-btn:active { background: rgba(255,255,255,0.3); }
  .pr-val { min-width: 34px; text-align: center; font-weight: 900; font-size: 13px; }
  .pr-abil { justify-content: space-between; }
  .pr-abbtn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 5px; padding: 5px 4px; border-radius: 10px;
    background: rgba(255,255,255,0.1); border: 2px solid rgba(255,255,255,0.3); color: #fff; font-weight: 800; font-size: 12px; cursor: pointer; opacity: 0.55; }
  .pr-abbtn img { width: 20px; height: 20px; }
  .pr-abbtn.on { opacity: 1; border-color: #ffd94d; background: rgba(255,217,77,0.18); }
  .pr-label { font-size: 11.5px; font-weight: 800; letter-spacing: 0.6px; opacity: 0.8; }
  #prItems { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
  .pr-item { display: flex; align-items: center; justify-content: center; padding: 6px 0; border-radius: 10px;
    background: rgba(255,255,255,0.12); border: 1.5px solid rgba(255,255,255,0.35); cursor: pointer; }
  .pr-item:active { background: rgba(255,255,255,0.3); }
  .pr-item img { width: 26px; height: 26px; object-fit: contain; }
  .pr-actions { display: flex; gap: 6px; }
  .pr-actions .pill { flex: 1; font-size: 12px; padding: 6px 4px; }
  @media (pointer: coarse) { :root { --hud-leave-top: clamp(50px, calc(6.95vmin + 8px), 128px); }
    #practicePanel { top: 50px; } #againBtn { top: clamp(96px, calc(11.2vmin + 10px), 202px); } #prBody { width: 180px; } }

  /* 關卡工坊 */
  .level-editor{position:fixed;inset:0;z-index:90;display:flex;align-items:center;justify-content:center;padding:18px;background:rgba(2,15,27,.82);backdrop-filter:blur(8px);font-family:system-ui,sans-serif;color:#eef8ff}
  .level-editor.hidden,.le-pane.hidden{display:none}
  .le-shell{width:min(1080px,100%);max-height:calc(100dvh - 24px);overflow:auto;border:1px solid #39769a;border-radius:22px;background:linear-gradient(145deg,#123a56,#08263c);box-shadow:0 24px 80px #000a}
  .le-head{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid #ffffff20}.le-head h2{margin:0;font-size:24px}.le-head p{margin:2px 0 0;color:#9fc6dc;font-size:13px}
  .le-icon{width:38px;height:38px;border:0;border-radius:50%;color:white;background:#ffffff18;font-size:28px;cursor:pointer}
  .le-main{display:grid;grid-template-columns:minmax(430px,1fr) 330px;gap:18px;padding:18px}.le-fields{display:flex;gap:8px;margin-bottom:10px}.le-fields input,.le-fields select,.le-side textarea{box-sizing:border-box;border:1px solid #5c8da8;border-radius:10px;background:#071d2c;color:white;padding:9px}.le-fields input{flex:1}
  .le-max{display:flex;align-items:center;gap:5px;white-space:nowrap;font-size:12px;color:#b9d7e8}.le-max select{padding:8px 5px}
  .le-palette{display:grid;grid-template-columns:repeat(6,minmax(70px,1fr));gap:7px;margin-bottom:10px}.le-tool{display:flex;flex-direction:column;align-items:center;gap:3px;min-width:0;border:1px solid #ffffff22;border-radius:10px;padding:5px 4px;background:#ffffff0d;color:white;cursor:pointer;font-size:12px;font-weight:800}.le-tool.on{outline:3px solid #ffd43b;background:#ffffff24}.le-swatch{position:relative;width:42px;height:42px;display:grid;place-items:center;border-radius:8px;overflow:hidden;background:#061b29;box-shadow:inset 0 0 0 1px #0005}.le-tool-img{width:100%;height:100%;object-fit:contain}.le-swatch b{position:absolute;right:1px;bottom:1px;min-width:15px;padding:1px;border-radius:8px;background:#08304be6;color:#fff;font-size:10px;line-height:13px}.le-tool span{overflow:hidden;max-width:100%;text-overflow:ellipsis;white-space:nowrap}
  .le-grid{display:grid;grid-template-columns:repeat(15,1fr);aspect-ratio:15/13;max-height:58vh;touch-action:none;user-select:none;border:3px solid #071722;background:#a9dc7a;overflow:hidden;isolation:isolate}.le-cell{position:relative;border:1px solid #0a2a3528;min-width:0;cursor:crosshair;background:#193847}.le-terrain-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;pointer-events:none}.le-mark{pointer-events:none;position:absolute;inset:4%;display:flex;align-items:center;justify-content:center;border-radius:20%;background:#08304b8f;color:#fff;font-size:clamp(7px,1vw,13px);font-weight:900;filter:drop-shadow(0 1px 2px #000)}.le-mark-img{width:94%;height:94%;object-fit:contain}.le-mark b{position:absolute;right:0;bottom:0;min-width:15px;padding:1px 2px;border-radius:9px;background:#07283de8;text-align:center}.le-tip,.le-muted{font-size:12px;color:#9fc6dc;margin:8px 0 0}
  .le-side{display:flex;flex-direction:column;min-height:430px}.le-tabs{display:flex;margin-bottom:10px}.le-tabs button{flex:1;border:0;border-bottom:2px solid #ffffff25;padding:9px;background:none;color:#9fc6dc;font-weight:800}.le-tabs button.on{color:#ffd43b;border-color:#ffd43b}.le-side textarea{width:100%;height:300px;resize:vertical;font:12px/1.45 ui-monospace,monospace}.le-actions{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-top:8px}.le-actions button:first-child{grid-column:1/-1}.le-actions button,.le-primary,.le-play{border:0;border-radius:10px;padding:10px;background:#245775;color:white;font-weight:800;cursor:pointer}.le-primary,.le-play{background:#ffcf35;color:#173144}.le-play{margin-top:auto;font-size:16px}.le-status{min-height:38px;padding:9px 0;font-size:13px;color:#91e6aa}.level-community .le-status{padding:0 18px 6px;font-weight:800}.le-status.error{color:#ff9b9b}
  @media(max-width:800px){.level-editor{padding:4px}.le-main{grid-template-columns:1fr;padding:10px}.le-grid{max-height:none}.le-side{min-height:360px}.le-side textarea{height:210px}.le-head{padding:10px 14px}.le-palette{grid-template-columns:repeat(4,1fr)}.le-tool{font-size:11px;padding:4px}.le-swatch{width:38px;height:38px}.le-shell{border-radius:14px}}
  .level-community{position:fixed;inset:0;z-index:91;padding:18px;background:rgba(2,15,27,.84);backdrop-filter:blur(8px);color:#eef8ff;font-family:system-ui,sans-serif;overflow:auto}.level-community.hidden{display:none}.lc-shell{width:min(1050px,100%);min-height:min(420px,calc(100dvh - 36px));margin:auto;border:3px solid #7fcdee;border-radius:18px;background:radial-gradient(120% 90% at 50% -10%,#1f5f8f 0%,#123f63 55%,#0c2c48 100%);box-shadow:0 12px 40px rgba(0,0,0,.5);overflow:hidden}.lc-tools{display:flex;gap:8px;padding:14px 18px}.lc-tools input,.lc-tools select,.lc-tools button{border:2px solid #7fcdee;border-radius:999px;background:rgba(255,255,255,.12);color:#fff;padding:9px 15px;font-family:inherit;font-weight:800;font-size:14px}.lc-tools input::placeholder{color:rgba(255,255,255,.6);font-weight:600}.lc-tools select{-webkit-appearance:none;appearance:none;padding-right:34px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center}.lc-tools select option{color:#123f63}.lc-tools button{cursor:pointer;box-shadow:0 3px 0 rgba(0,0,0,.18),inset 0 2px 0 rgba(255,255,255,.35)}.lc-tools button:active{transform:translateY(2px)}.lc-tools #lcMine.on{background:linear-gradient(#ffd84a,#f5a31b);border-color:#fff3c9;color:#6b3b00}.lc-tools #lcCreate{background:linear-gradient(#6fdc6f,#2faa4a);border-color:rgba(255,255,255,.85);color:#fff;font-weight:900;white-space:nowrap}.lc-tools input{flex:1}.lc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px;padding:0 18px 20px;align-items:start}.lc-card{display:flex;flex-direction:column;gap:8px;min-width:0;border:2px solid rgba(127,205,238,.45);border-radius:16px;padding:13px;background:rgba(255,255,255,.09);box-shadow:0 6px 18px rgba(0,0,0,.25)}.lc-preview{display:grid;grid-template-columns:repeat(15,minmax(0,1fr));grid-template-rows:repeat(13,minmax(0,1fr));width:100%;aspect-ratio:15/13;border:2px solid #ffffff38;border-radius:9px;overflow:hidden;background:#193847;box-shadow:0 4px 12px #0005}.lc-preview i{position:relative;display:block;min-width:0;min-height:0;overflow:hidden;background:#193847}.lc-terrain{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}.lc-mark{position:absolute;inset:5%;z-index:1;display:grid;place-items:center;border-radius:25%;background:#082c4670;filter:drop-shadow(0 1px 1px #000)}.lc-mark.item{inset:9%;background:transparent}.lc-mark-img{width:100%;height:100%;object-fit:contain}.lc-mark b{position:absolute;right:-1px;bottom:-1px;padding:0 2px;border-radius:4px;background:#082c46e8;color:#fff;font-size:clamp(5px,.7vw,9px);line-height:1.2}.lc-title{display:flex;justify-content:space-between;gap:8px;font-weight:900}.lc-title span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-title small{flex:none;padding:2px 7px;border-radius:999px;background:#ffd43b;color:#173144}.lc-meta,.lc-desc{font-size:12px;color:#a8c8da}.lc-meta{white-space:normal;line-height:1.45}.lc-desc{min-height:20px}.lc-card-actions{display:flex;flex-wrap:wrap;gap:6px}.lc-card button{border:2px solid rgba(255,255,255,.75);border-radius:999px;padding:6px 13px;background:linear-gradient(#5cc3f2,#2e8fd6);color:#fff;font-weight:800;font-size:13px;cursor:pointer;box-shadow:0 2px 0 rgba(0,0,0,.18),inset 0 2px 0 rgba(255,255,255,.3)}.lc-card button:active{transform:translateY(2px)}.lc-card .play{background:linear-gradient(#ffd84a,#f5a31b);border-color:#fff3c9;color:#6b3b00;text-shadow:0 1px 0 #ffe9a8}.lc-stars{display:flex;align-items:center;gap:2px;padding-top:6px;border-top:1px solid rgba(127,205,238,.3)}.lc-stars .lc-rate-label{margin-right:6px;font-size:12px;font-weight:800;color:#a8c8da}.lc-stars button{flex:0 0 auto;padding:2px 4px;border:0;border-radius:6px;background:none;box-shadow:none;color:#6d8796;font-size:20px;line-height:1}.lc-stars button.on{color:#ffd43b}.lc-stars button:active{transform:none}@media(max-width:600px){.level-community{padding:4px}.lc-shell{border-radius:14px}.lc-tools{flex-wrap:wrap}.lc-tools #lcCreate{order:-2}.lc-tools input{flex-basis:100%;order:-1}.lc-grid{grid-template-columns:1fr;padding:0 10px 15px}.lc-card{padding:10px}}

/* The chat panel's tab switch, last so it wins: [hidden] on its own ties with the
   scoped `.ch-ovbox .chat-row { display: flex }` rules above and would lose on order. */
.chat-log[hidden], .chat-row[hidden], .chat-dm[hidden] { display: none !important; }

/* ===== 關卡工作室 (level studio) =====
   A screen of its own, not a dialog: a stray click outside used to throw away a
   half-drawn level. The editor lives inside it as one tab; the level LIST is the
   entry point, the way Mario Maker's course list is. */
.level-studio { position: fixed; inset: 0; z-index: 90; display: flex; flex-direction: column;
  background: radial-gradient(120% 80% at 50% -10%, #1f5f8f 0%, #123f63 55%, #0a2842 100%);
  color: #eef8ff; font-family: system-ui, sans-serif; overflow: hidden; }
.level-studio.hidden { display: none; }
.ls-head { flex: none; display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 14px 20px; border-bottom: 2px solid rgba(127,205,238,.35); background: rgba(4,22,38,.35); }
.ls-title h2 { margin: 0; font-size: clamp(18px, 2.4vmin, 24px); }
.ls-title p { margin: 2px 0 0; font-size: 12.5px; color: #a8c8da; }
.ls-tabs { display: flex; gap: 8px; margin-left: auto; }
.ls-tab { border: 2px solid #7fcdee; border-radius: 999px; padding: 8px 18px; cursor: pointer;
  background: rgba(255,255,255,.12); color: #fff; font-family: inherit; font-weight: 800; font-size: 14px; }
.ls-tab.on { background: linear-gradient(#ffd84a, #f5a31b); border-color: #fff3c9; color: #6b3b00; }
.ls-saved { min-width: 84px; font-size: 12px; font-weight: 800; color: #8fe3a8; opacity: 0; transition: opacity .2s; }
.ls-saved.on { opacity: 1; }
.ls-pane { flex: 1; min-height: 0; overflow: auto; padding: 18px 20px 26px; }
.ls-pane.hidden { display: none; }

/* the level list */
.ls-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 14px; align-items: start; }
.ls-empty { margin: 0 0 12px; color: #a8c8da; font-size: 13px; }
.ls-empty.hidden { display: none; }
.ls-new { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  min-height: 240px; border: 2px dashed rgba(127,205,238,.6); border-radius: 16px; cursor: pointer;
  background: rgba(255,255,255,.06); color: #cfe8f7; font-family: inherit; font-weight: 800; font-size: 14px; }
.ls-new:hover { background: rgba(255,255,255,.12); }
.ls-new-plus { font-size: 40px; line-height: 1; color: #ffd84a; }
.ls-card { display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 12px;
  border: 2px solid rgba(127,205,238,.45); border-radius: 16px; background: rgba(255,255,255,.09);
  box-shadow: 0 6px 18px rgba(0,0,0,.25); }
.ls-card-head { display: flex; align-items: center; gap: 8px; }
.ls-card-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 900; }
.ls-badge { flex: none; padding: 2px 8px; border-radius: 999px; font-size: 10.5px; font-weight: 900;
  background: rgba(255,255,255,.18); color: #cfe8f7; }
.ls-badge.pub { background: linear-gradient(#6fdc6f, #2faa4a); color: #063b16; }
.ls-card-meta { font-size: 11.5px; color: #a8c8da; }
.ls-card-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.ls-card-actions .pill { padding: 5px 11px; font-size: 12.5px; border-width: 2px; }

/* the AI helper: three numbered steps, in order, with nothing else on screen */
.ls-steps { list-style: none; margin: 0 auto; padding: 0; max-width: 720px; display: flex; flex-direction: column; gap: 16px; }
.ls-step { display: flex; gap: 14px; padding: 14px; border: 2px solid rgba(127,205,238,.35); border-radius: 16px;
  background: rgba(255,255,255,.07); }
.ls-step-n { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
  background: linear-gradient(#ffd84a, #f5a31b); color: #6b3b00; font-weight: 1000; }
.ls-step-body { flex: 1; min-width: 0; }
.ls-step-body h3 { margin: 2px 0 8px; font-size: 15px; }
.ls-step-body textarea { width: 100%; box-sizing: border-box; padding: 10px 12px; border: 2px solid #7fcdee;
  border-radius: 12px; background: rgba(255,255,255,.12); color: #fff; font-family: ui-monospace, monospace;
  font-size: 12.5px; resize: vertical; }
.ls-step-body textarea::placeholder { color: rgba(255,255,255,.55); }
.ls-muted { margin: 0 0 8px; font-size: 12px; color: #a8c8da; }
.ls-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.ls-status { min-height: 20px; margin-top: 8px; font-size: 12.5px; color: #91e6aa; }
.ls-status.error { color: #ff9aa2; }

/* the editor pane fills the page now instead of a boxed dialog */
#levelEditor.ls-pane .le-main { grid-template-columns: minmax(0, 1fr) minmax(300px, 340px); padding: 0; max-width: 1180px; margin: 0 auto; }
@media (max-width: 900px) {
  .ls-head { gap: 8px; padding: 10px 12px; }
  .ls-tabs { width: 100%; margin-left: 0; }
  .ls-tab { flex: 1; padding: 7px 8px; font-size: 13px; }
  .ls-pane { padding: 12px; }
  #levelEditor.ls-pane .le-main { grid-template-columns: 1fr; }
  .ls-grid { grid-template-columns: 1fr; }
}

/* The board is the main event. The palette used to be a 6x4 block stacked above it,
   which pushed the grid below the fold — you had to scroll to see your own level.
   Two rows flowing sideways cut its height in half. */
#levelEditor.ls-pane .le-palette { display: grid; grid-auto-flow: column; grid-template-columns: none;
  grid-template-rows: repeat(2, auto); grid-auto-columns: minmax(72px, 1fr); overflow-x: auto; padding-bottom: 5px; }
#levelEditor.ls-pane .le-tool { font-size: 11.5px; padding: 4px 3px; }
#levelEditor.ls-pane .le-side { display: flex; flex-direction: column; gap: 9px; min-height: 0; height: 100%; }
#levelEditor.ls-pane .le-palette { flex: 1 1 0; min-height: 0; }
#levelEditor.ls-pane .le-holdbar, #levelEditor.ls-pane .le-group-tabs { flex: none; margin-bottom: 0; }
.le-wide { width: 100%; }
.le-hint { margin: 2px 0 0; font-size: 12px; line-height: 1.5; color: #a8c8da; }
.le-adv { margin-top: 6px; border: 1px solid rgba(127,205,238,.35); border-radius: 12px; padding: 8px 10px; background: rgba(255,255,255,.05); }
.le-adv summary { cursor: pointer; font-weight: 800; font-size: 13px; color: #cfe8f7; }
.le-adv[open] summary { margin-bottom: 8px; }
.le-adv textarea { width: 100%; box-sizing: border-box; min-height: 150px; }
@media (max-width: 900px) {
  #levelEditor.ls-pane .le-palette { grid-auto-columns: minmax(66px, 1fr); }
}

/* The palette, one group at a time behind a tab strip. All 47 cell types in a
   single scroller was unreadable; a tab is a page a child can take in at once. */
#levelEditor.ls-pane .le-palette { display: flex; flex-direction: column; gap: 7px; grid-template-columns: none; }
.le-tools { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; align-content: start;
  flex: 1 1 0; min-height: 120px; overflow-y: auto; padding: 1px 2px 4px 1px; }
#levelEditor.ls-pane .le-tool span { white-space: normal; line-height: 1.15; }
/* five tabs in a 372px rail: let them wrap rather than scroll a clipped "Props"
   off the edge, which is exactly the kind of half-visible control a child
   never finds. */
.le-group-tabs { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 7px; }
.le-group-tab { flex: 0 1 auto; border: 2px solid rgba(127,205,238,.45); border-radius: 999px;
  padding: 5px 11px; background: rgba(255,255,255,.07); color: #cfe8f7;
  font-family: inherit; font-weight: 900; font-size: 12.5px; cursor: pointer; white-space: nowrap; }
.le-group-tab.on { border-color: #ffd43b; background: #ffd43b; color: #123f63; }

/* An upright piece is bottom-anchored and grows out of its cell, exactly as the
   canvas draws it — the whole point being that the grid IS the preview. */
.le-obj-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.le-obj-img.small { inset: auto auto 0 50%; width: 80%; height: 80%; object-fit: contain; transform: translateX(-50%); }
.le-obj-img.tall { inset: auto auto 0 50%; width: 118%; height: auto; max-height: 190%;
  object-fit: contain; transform: translateX(-50%); }
.le-hp { pointer-events: none; position: absolute; right: 2%; top: 2%; z-index: 3; min-width: 12px; padding: 0 2px;
  border-radius: 7px; background: #08304be6; color: #ffd43b;
  font-size: clamp(7px, .85vw, 12px); font-weight: 900; line-height: 1.35; text-align: center; }
/* where the current tool would land, mirror copies included */
.le-cell.ghost { box-shadow: inset 0 0 0 2px #ffd43b; }
.le-cell.sel { box-shadow: inset 0 0 0 2px #7fcdee; background: #7fcdee33; }

/* "you are holding X" + undo / redo */
.le-holdbar { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.le-hold-label { font-size: 11px; font-weight: 900; letter-spacing: .5px; color: #8fb8d0; }
.le-hold { display: inline-flex; align-items: center; gap: 7px; border: 2px solid #ffd43b;
  border-radius: 999px; padding: 3px 12px 3px 4px; background: rgba(255,212,59,.14);
  color: #fff; font-weight: 900; font-size: 13px; }
.le-hold i { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  overflow: hidden; background: #061b29; }
.le-hold-img { width: 100%; height: 100%; object-fit: contain; }
.le-holdbar-gap { flex: 1 1 auto; }
.le-step { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
  border: 2px solid rgba(127,205,238,.45); background: rgba(255,255,255,.07); color: #cfe8f7; cursor: pointer; }
.le-step:disabled { opacity: .35; cursor: default; }

/* brush + mirror: how the stroke is applied, kept next to the pieces it applies */
.le-opts { display: flex; flex-direction: column; gap: 5px; }
.le-opt-row { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.le-opt-label { min-width: 44px; font-size: 11px; font-weight: 900; color: #8fb8d0; }
.le-chip { border: 1.5px solid rgba(127,205,238,.4); border-radius: 999px; padding: 3px 10px;
  background: rgba(255,255,255,.06); color: #cfe8f7; font-family: inherit; font-weight: 800;
  font-size: 12px; cursor: pointer; }
.le-chip.on { border-color: #7fcdee; background: #7fcdee; color: #0b3550; }
/* the action buttons belong at the TOP of the side column now that it is a full page —
   margin-top:auto was pinning them to the bottom of a dialog that no longer exists */
#levelEditor.ls-pane .le-play { margin-top: 0; }
@media (max-width: 900px) { .le-tools { grid-template-columns: repeat(auto-fill, minmax(66px, 1fr)); max-height: 22vh; } }

/* The board takes whatever height is left after the name row and the palette, instead
   of a fixed 58vh that cut the bottom row off on a 900px-tall window. flex gives it the
   remainder; aspect-ratio turns that height into the matching width. */
#levelEditor.ls-pane { overflow: hidden; }
#levelEditor.ls-pane .le-main { height: 100%; max-height: 100%; }
#levelEditor.ls-pane .le-canvas-wrap { display: flex; flex-direction: column; min-height: 0; min-width: 0; }
/* The board is a fixed 15:13 box that has to fit BOTH axes of what is left after
   the name row. `flex:1 1 0` alone only sized the HEIGHT, and aspect-ratio then
   derived a width with nothing capping it — on a tall window (1920x1080,
   1680x1050) that width ran 140-210px past the column and the board covered the
   tool rail. The first rule is width-bound and can never overlap; the container
   query refines it so a short window becomes height-bound instead. */
#levelEditor.ls-pane .le-board-fit { flex: 1 1 0; min-height: 0; min-width: 0;
  display: flex; align-items: center; justify-content: center; container-type: size; }
#levelEditor.ls-pane .le-grid { box-sizing: border-box; flex: none; width: 100%; max-width: 100%;
  min-height: 0; max-height: none; margin: 0 auto; }
#levelEditor.ls-pane .le-grid { width: min(100cqw, calc(100cqh * 15 / 13)); }
#levelEditor.ls-pane .le-tip { flex: none; }
/* the name/theme/player-limit row, in the game's own control language */
#levelEditor.ls-pane .le-fields input, #levelEditor.ls-pane .le-fields select {
  border: 2px solid #7fcdee; border-radius: 999px; padding: 8px 14px; background: rgba(255,255,255,.12);
  color: #fff; font-family: inherit; font-weight: 800; font-size: 14px; }
#levelEditor.ls-pane .le-fields select { -webkit-appearance: none; appearance: none; padding-right: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center; }
#levelEditor.ls-pane .le-fields select option { color: #123f63; }
#levelEditor.ls-pane .le-fields input::placeholder { color: rgba(255,255,255,.6); }
@media (max-width: 900px) {
  #levelEditor.ls-pane { overflow: auto; }
  #levelEditor.ls-pane .le-main { height: auto; max-height: none; }
  /* the name/theme/player-limit row does not fit one phone line; unwrapped it set
     a min-content width for the whole column and pushed the board off the screen */
  #levelEditor.ls-pane .le-fields { flex-wrap: wrap; }
  #levelEditor.ls-pane .le-fields input { flex: 1 1 100%; min-width: 0; }
  #levelEditor.ls-pane .le-side { height: auto; }
  #levelEditor.ls-pane .le-board-fit { display: block; container-type: normal; flex: none; height: auto; min-height: 0; }
  /* stacked: the board takes the column width, but never so much height that it
     alone is two screens (a landscape phone is 390px tall). vh keeps the 15:13
     ratio intact — clamping max-height instead would stretch the cells. */
  #levelEditor.ls-pane .le-grid { flex: none; width: min(100%, calc(70vh * 15 / 13));
    max-width: 100%; max-height: none; }
  #levelEditor.ls-pane .le-palette { flex: none; min-height: 0; }
  #levelEditor.ls-pane .le-tools { max-height: 34vh; min-height: 0; flex: none; }
}

/* starting from an official board */
.ls-new-copy .ls-new-plus { font-size: 30px; }
.ls-pick-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; font-weight: 900; color: #cfe8f7; }
.ls-pick-head .pill { padding: 5px 14px; font-size: 13px; }
.ls-pick-thumb { width: 100%; aspect-ratio: 15/13; object-fit: contain; border: 2px solid rgba(127,205,238,.35);
  border-radius: 9px; background: #12263a; }
.ls-pick-card { gap: 7px; }
#lsGrid.hidden, #lsPick.hidden { display: none; }

/* ===== replay cards =====
   The battle-log shape: win/loss badge first and biggest, the numbers that let you
   recognise the match under the map name, actions small and last. Ten rows of
   "date · map · length" were indistinguishable. */
.replay-card { display: flex; align-items: center; gap: 10px; padding: 8px 10px; margin: 6px 0;
  border: 1.5px solid rgba(150,115,55,0.22); border-radius: 13px; background: rgba(255,255,255,0.6); }
.rp-badge { flex: none; display: grid; place-items: center; min-width: 38px; padding: 4px 8px;
  border-radius: 9px; font-weight: 1000; font-size: 13px; color: #fff; }
.rp-badge.win { background: linear-gradient(#6fdc6f, #2faa4a); }
.rp-badge.loss { background: linear-gradient(#b8c6d0, #8fa2b0); }
.rp-thumb { flex: none; width: 54px; height: 47px; object-fit: contain; border-radius: 7px; background: #12263a; }
.rp-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.rp-top { font-weight: 900; font-size: 13px; color: #5a3800; display: flex; align-items: center; gap: 6px; }
.rp-stat { font-size: 12px; font-weight: 700; color: #b8790f; }
.rp-when { font-size: 11px; color: #8d7a55; }
.rp-cloud { color: #6b5327; display: inline-flex; }
.rp-actions { flex: none; display: flex; flex-wrap: wrap; gap: 5px; justify-content: flex-end; max-width: 46%; }
.rp-actions .pill { padding: 4px 10px; font-size: 12px; border-width: 2px; }
@media (max-width: 600px) {
  .replay-card { flex-wrap: wrap; }
  .rp-thumb { width: 44px; height: 38px; }
  .rp-actions { max-width: 100%; width: 100%; justify-content: flex-start; }
}

/* the match log page: cards on the studio's dark full-page shell */
.ml-list { max-width: 820px; margin: 0 auto; }
#matchLog .replay-card { background: rgba(255,255,255,0.92); border-color: rgba(127,205,238,0.35); }
#matchLog .replay-note { color: #a8c8da; text-align: center; padding: 30px 0; }

/* The replay player is a screen, not a dialog: it used to be a floating box you could
   dismiss by clicking beside it, with eight controls in a row. Now it fills the view
   and the clip/share tools sit behind a fold, leaving play / scrub / speed. */
.replay-dialog { background: radial-gradient(120% 80% at 50% -10%, #1f5f8f 0%, #123f63 55%, #0a2842 100%);
  backdrop-filter: none; padding: 0; align-items: stretch;
  /* above the match log (.level-studio is 90) — the player is opened FROM it, so at
     z-index 85 it rendered underneath and looked like nothing had happened.
     The value lives in --z-replay so the Android overlay canvas tracks it. */
  z-index: var(--z-replay); }
.replay-box { width: 100%; max-width: none; max-height: 100dvh; border: 0; border-radius: 0;
  background: transparent; box-shadow: none; display: flex; flex-direction: column; align-items: center; padding: 14px 16px; }
.replay-box > canvas { max-width: min(1100px, 100%); }
.replay-box > .replay-title, .replay-box > .replay-controls, .replay-box > .replay-more { width: min(1100px, 100%); }
.replay-more { margin-top: 10px; border: 1px solid rgba(127,205,238,.35); border-radius: 12px;
  padding: 8px 12px; background: rgba(255,255,255,.06); }
.replay-more.hidden { display: none; }
.replay-more > summary { cursor: pointer; font-weight: 800; font-size: 13px; color: #cfe8f7; }
.replay-more[open] > summary { margin-bottom: 8px; }

/* the speed picker, in the game's control language instead of the browser's */
.replay-speed { -webkit-appearance: none; appearance: none; border: 2px solid #7fcdee; border-radius: 999px;
  padding: 5px 28px 5px 12px; background: rgba(255,255,255,.12); color: #fff; font-family: inherit;
  font-weight: 800; font-size: 13px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center; }
.replay-speed option { color: #123f63; }

/* invite banner on the login page */
.auth-invite { margin: 0 0 10px; padding: 9px 13px; border-radius: 12px; border: 2px solid #ffd94d;
  background: rgba(255,217,77,.16); color: #fff; font-size: 12.5px; font-weight: 800; line-height: 1.5; text-align: center; }
.auth-invite.hidden { display: none; }

/* ===== 戰績卡 ===== */
/* Above the replay player (95) and the match log (90): it is opened from both, and
   from the result screen, which keeps running underneath. */
.sharecard { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center;
  background: rgba(6,20,34,0.82); backdrop-filter: blur(3px); padding: 16px; }
.sharecard.hidden { display: none; }
.sharecard-box { width: min(420px, 100%); max-height: 100dvh; overflow-y: auto; display: flex; flex-direction: column;
  gap: 10px; align-items: center; }
.sharecard-head { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  color: #eaf6ff; font-weight: 900; font-size: 17px; }
.sharecard-img { width: 100%; border-radius: 14px; box-shadow: 0 12px 34px rgba(0,0,0,0.45);
  background: rgba(255,255,255,0.06); aspect-ratio: 1080 / 1350; object-fit: contain; }
.sharecard-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; align-items: center; }
.sharecard-actions #scStatus { color: #cfe6f8; font-size: 13px; font-weight: 700; }
.sharecard-hint { margin: 0; color: rgba(220,239,255,0.7); font-size: 13px; font-weight: 700; text-align: center; }

  /* ===== 造型實驗室 (站主專用, js/lab.js) =====
     刻意樸素: 這是一把尺, 不是一個櫥窗。淺色背景是為了讓角色的白邊與浮空看得出來。 */
  #lab { position: fixed; inset: 0; z-index: 31; display: none; background: #eef3f8;
    -webkit-user-select: none; user-select: none; }
  #lab.show { display: block; }
  #lab .arc-screen { width: 100%; height: 100%; display: flex; flex-direction: column; background: #eef3f8; }
  #lab .arc-header { background: transparent; border-bottom: 1px solid rgba(0,0,0,0.10); }
  #lab .arc-title { color: #1b2b3a; }
  .lab-body { flex: 1; display: flex; gap: 16px; padding: 12px 16px 20px; overflow: hidden; }
  #labCanvas { flex: 1; min-width: 0; background: #fff; border: 1px solid rgba(0,0,0,0.12);
    border-radius: 10px; image-rendering: auto; }
  #labTools { width: 300px; flex: none; overflow-y: auto; display: flex; flex-direction: column; gap: 8px;
    font-size: 13px; color: #1b2b3a; }
  .lab-row { display: flex; align-items: center; gap: 8px; }
  .lab-lab { width: 74px; flex: none; color: #5a6b7c; }
  .lab-sel { flex: 1; min-width: 0; padding: 5px 6px; border-radius: 6px; border: 1px solid rgba(0,0,0,0.18); background: #fff; }
  .lab-seg { display: flex; flex-wrap: wrap; gap: 4px; }
  .lab-seg .pill { padding: 4px 10px; font-size: 12px; }
  .lab-slider { flex: 1; display: flex; align-items: center; gap: 8px; }
  .lab-slider input[type=range] { flex: 1; min-width: 0; }
  .lab-check { display: flex; align-items: center; gap: 6px; }
  .lab-out { flex: none; margin: 4px 0 0; padding: 8px; background: #17212b; color: #d6e6f5;
    border-radius: 8px; font-size: 11px; line-height: 1.5; white-space: pre-wrap; word-break: break-all; }
  @media (max-width: 860px) {
    .lab-body { flex-direction: column; overflow-y: auto; }
    #labTools { width: 100%; }
  }

/* ===== 等級制度 v2: 段位徽章 / 爆米花桶 / 連勝火焰 (docs/level-system-v2.md §4.2) ===== */
.rank { display: inline-flex; align-items: center; gap: 4px; font-weight: 900; border-radius: 999px; padding: 1px 8px 1px 3px; color: #3a2c12; background: #f2e6c8; vertical-align: middle; }
.rank .rank-ic, .slv .rank-ic { width: 18px; height: 18px; object-fit: contain; vertical-align: middle; }
.rank .rank-name { font-size: 0.92em; }
/* 段位色: 飽和底 + 白字 + 深色細邊 —— 淺黃漸層在白色 chip 上完全看不清 (站主 2026-09-03) */
.rank, .slv[class*="rank-"] { color: #fff; text-shadow: 0 1px 0 rgba(0,0,0,0.35); border: 0; }
.rank-raw { background: #8a8172; }
.rank-pop { background: #c98f12; }
.rank-butter { background: #df8a00; }
.rank-caramel { background: #b95a10; }
.rank-cheese { background: #d4491a; }
.rank-gold { background: linear-gradient(#e0a800, #b8810a); }
.rank-master { background: linear-gradient(#8a4fd6, #5f2fa8); }
.rank-legend { background: linear-gradient(90deg, #e3486b, #d97a1e, #2aa876, #2f7fd6, #8a4fd6); }
.slot .slv { display: inline-flex; align-items: center; gap: 3px; padding: 0 7px 0 3px; }
.slot .slv .rank-ic { width: 15px; height: 15px; }
.slot .streak { display: inline-flex; align-items: center; gap: 2px; margin-left: 5px; padding: 0 6px; border-radius: 999px; font-size: clamp(10px, 1.3vmin, 14px); font-weight: 900; color: #fff; background: linear-gradient(#ff8a3d, #e8401a); }
.slot .streak.hot { background: linear-gradient(#ffe066, #ff9d1a); color: #5a2e00; }
#lobbyList .acctchip .acct-rank { display: inline-flex; }
#lobbyList .acctchip .acct-rank .rank { font-size: 12px; padding: 0 7px 0 2px; }
#lobbyList .acctchip .acct-rank .rank .rank-ic { width: 16px; height: 16px; }
.xpbucket { position: relative; display: inline-block; vertical-align: middle; }
.xpbucket img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; }
.xpbucket .xb-full { transition: clip-path .6s ease; }
.xpbucket.mini { width: 30px; height: 30px; margin-left: 4px; }
.xpbucket.big { width: 96px; height: 96px; flex: 0 0 auto; filter: drop-shadow(0 3px 0 rgba(0,0,0,0.18)); }
.sp-rankrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.sp-rankrow .rank { font-size: 14px; padding: 2px 10px 2px 4px; box-shadow: 0 2px 0 rgba(0,0,0,0.18); }
.sp-rankrow .rank .rank-ic { width: 22px; height: 22px; }

/* =========================================================================
   房間頁面的手機版 (站主 2026-09-09 實機回報: 「手機這樣完全看不到」/
   「整個遮蓋住畫面了」)。四個問題, 兩個是 bug 兩個是排版:

   1. (已解決得更徹底) 「建議轉橫向」提示原本 fixed 在頂端正中央壓住標題; 2026-09-17
      整個拆掉 —— 橫向版面比直向更難用, 不再建議。
   2. QR 展開會蓋住下面的內容: #lobbyRoom 是 height:100% + overflow:hidden 的
      flex column, #roomShare 是它的 flex item (預設 flex-shrink:1), 而 QR 撐出
      ~370px 又縮不下去 —— 於是它溢出自己的框, 疊在座位上, 而且它在 .room-body
      的捲動區之外, 捲也捲不到。手機改成置中浮層。
   3. 座位在 390px 硬排 4 欄 = 每格 78px, 名字被截成「電腦（困...」。改 2 欄。
   4. 順序: 座位 → 聊天室(空的, 佔 280px) → 模式/地圖 → 開始。主要動作在摺線
      外好幾個畫面。聊天室移到最後。
   ========================================================================= */

@media (max-width: 720px), (max-width: 1100px) and (orientation: portrait) {
  /* 直向平板 (iPad 768/820 直向) 也走這一套: 721-1100 這帶原本吃桌機兩欄, 於是
     聊天室被拉高成一片 ~950px 的空白面板, 而座位仍是 4 欄、名字仍被截斷。直向的
     視窗比寬還高, 兩欄本來就不是它的形狀。 */
  #lobbyRoom .room-body { flex-direction: column; overflow-y: auto; -webkit-overflow-scrolling: touch; }
  /* .room-left 也要一起放掉 flex —— 它是 flex:2.2 (basis 0), 在直的 flex 容器裡等於
     高度 0, 於是座位跟聊天室整個溢出到 .side 上面, 兩塊疊在一起 (實測 768x1024:
     .room-left 高 0, .slots 佔 84..493, .side 從 107 開始)。<=720px 那一段本來就
     有這行, 721-1100 直向這一段漏了。 */
  #lobbyRoom .room-left { flex: none; width: 100%; max-width: none; min-height: 0; box-sizing: border-box; }
  #lobbyRoom .side { flex: none; width: 100%; max-width: none; box-sizing: border-box; }
  #lobbyRoom .side-main { overflow: visible; }
  /* 上一版的「QR 置中浮層」規則整組刪掉了: 分享面板已經不在房間版面裡, QR 是在
     邀請對話框裡行內展開, sheet 自己會捲, 所以那個浮層與壓暗層都沒有存在理由了。 */

  /* 手機上方瘦身 (站主 2026-09-10: 「手機整個上方都太亂太雜太多內容」)。
     房間標題列本來有七個東西: 離開 / 標題 / 觀戰 / 造型 / 音樂 / 音效 / 設定 ——
     在 390px 寬要排三列。音樂與音效是重複的: 齒輪那張設定面板裡本來就有 #gsMusic
     與 #gsSfx, 而且還多兩條音量滑桿。手機收掉標題列上的那兩顆, 功能一個都沒少。 */
  #lobbyRoom .arc-header #muteBtn3,
  #lobbyRoom .arc-header #sfxBtn3 { display: none; }
  #lobbyRoom .arc-header { gap: 7px; padding: 7px 8px; }
  #lobbyRoom .arc-header .pill { padding: 8px 13px; font-size: 13.5px; border-width: 2px; }
  #lobbyRoom .arc-title { font-size: 17px; letter-spacing: 0; }
  #lobbyRoom .arc-title .rm-invite { margin-left: 8px; padding: 5px 12px; font-size: 13px; }
}

/* 標題自己一列, 按鈕自己一列。讓 flex-wrap 自由斷會斷成三列 —— .arc-title 有
   flex:1, 它的最小寬度 (房名 + 房號 + 邀請鈕) 就吃掉大半列, 於是「離開」單獨一列、
   標題一列、其餘按鈕一列。order:-1 是必要的: 少了它, 第一列會先放「離開」, 標題
   仍然被推到第二列, 還是三列。兩列要是刻意的, 不是撞出來的。 */
@media (max-width: 620px) {
  #lobbyRoom .arc-title { flex: 1 0 100%; order: -1; }

  /* (4) 重新排序。聊天室在 .room-left 裡、side 是它的兄弟, 跨父層沒辦法用 order,
     所以 .room-left 在手機改成 display:contents —— 它的兩個小孩直接變成
     .room-body 的 flex item, 三塊才能一起排。間距由 .room-body 的 gap 給。 */
  #lobbyRoom .room-left { display: contents; }
  #lobbyRoom .slots-area { order: 1; }
  #lobbyRoom .side { order: 2; }
  #lobbyRoom .room-left .chat { order: 3; }
  /* 底部留白, 不要壓住最後一塊 */
  #lobbyRoom .room-body { padding-bottom: 64px; }
}

/* (3) 座位: 2 欄。.slot-cell 把下拉跟座位包在同一格, 所以改欄數下拉會自己跟著走。
   aspect-ratio 從 1 放寬成 4/3, 否則 2 欄會讓每格高到 170px、四排就 700px。 */
/* 欄數只看寬度, 不看方向: 直向平板套 2 欄的話每格會有 ~400px 寬 —— 一張卡放一隻
   角色。它走的是「單欄堆疊 + 4 欄座位」, 788px 全寬 / 4 = 190px, 名字放得下。 */
@media (max-width: 560px) {
  #lobbyRoom .slots { grid-template-columns: repeat(2, 1fr); }
  #lobbyRoom .slot { aspect-ratio: 4 / 3; }
  #lobbyRoom .chat { min-height: 92px; }
}

/* 主要動作固定在底部。.side-foot 的註解本來就寫「START / READY always pinned &
   visible」—— 桌機是釘在 .side 的底部, 但手機整塊 .side 跟著頁面捲, 於是那個原意
   失效了: 實測 390x844 直向, .side 有 993px 高, 開始鈕落在 y=1823 / 總高 2061,
   等於摺線外兩個畫面。房主要按開始得先滑過整疊他根本不用改的設定。
   固定條讓它永遠按得到, 也讓「設定」不必為它讓位。#waitMsg (準備就緒 — 按下開始!)
   跟著進來, 那正是這顆按鈕的狀態說明。 */
/* min-height 守門: 小手機橫向 (667x375 這類) 寬度也 <=720, 但那裡垂直空間才是稀缺
   的 —— 114px 的固定條會吃掉 30% 的畫面高度。矮視窗就讓它留在文件流裡。 */
@media (max-width: 720px) and (min-height: 520px),
       (max-width: 1100px) and (orientation: portrait) and (min-height: 520px) {
  #lobbyRoom .side-foot {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 46;
    display: flex; flex-direction: column; align-items: stretch; gap: 5px;
    padding: 9px 12px calc(9px + env(safe-area-inset-bottom));
    background: linear-gradient(rgba(26,111,176,0), rgba(20,86,140,0.95) 42%);
    box-shadow: 0 -6px 20px rgba(10,50,85,0.30);
  }
  #lobbyRoom .side-foot .pill.big { padding: 11px; font-size: clamp(17px, 4.6vw, 21px); }
  #lobbyRoom .side-foot #waitMsg:empty { display: none; }
  /* 觀戰者兩顆按鈕都是 display:none (panels.js), 固定條就沒有動作可放 —— 收回文件流,
     不要在底部留一條只有背景的空條。 */
  body.spec-room #lobbyRoom .side-foot {
    position: static; background: none; box-shadow: none; padding: 6px 0 0;
  }
  /* 留出固定條的高度, 最後一塊才不會被壓住 */
  #lobbyRoom .room-body { padding-bottom: 132px; }
}

/* 矮視窗 (小手機橫向, 667x375 這類): 固定條照做, 但壓成一列 —— 按鈕與自動準備同排,
   狀態行收掉。垂直空間在這裡是稀缺資源, 132px 的直向版會吃掉三分之一畫面。 */
@media (max-width: 720px) and (max-height: 519px) {
  #lobbyRoom .side-foot {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 46;
    display: flex; flex-direction: row; align-items: center; gap: 8px;
    padding: 5px 10px calc(5px + env(safe-area-inset-bottom));
    background: linear-gradient(rgba(26,111,176,0), rgba(20,86,140,0.95) 50%);
    box-shadow: 0 -5px 16px rgba(10,50,85,0.28);
  }
  #lobbyRoom .side-foot .pill.big { flex: 1; width: auto; padding: 7px; font-size: 16px; }
  #lobbyRoom .side-foot #waitMsg { display: none; }
  #lobbyRoom .side-foot .auto-ready { flex: none; }
  body.spec-room #lobbyRoom .side-foot { position: static; background: none; box-shadow: none; padding: 6px 0 0; }
  #lobbyRoom .room-body { padding-bottom: 64px; }
}

/* =========================================================================
   2026-09-17 大廳重設計 (使用者參考稿 image-12 桌機 / image-13 手機)。
   結構: 深木色左側導覽列 + 中央開放式舞台 (三隻吉祥物站在廣場上, 快速開始在腳下)
   + 右欄三張奶油卡 (好友 / 公告 / 大廳聊天) + 底部 dock。頂列: logo、最新公告
   跑馬燈、帳號 chip (含頭像／Lv／XP)、金幣。
   放在檔尾: 同權重的舊規則 (大廳基底、手機塊) 在前面, 這裡一律後蓋。
   ========================================================================= */
/* ---- 頂列 ---- */
.ch-top { padding: 10px clamp(12px, 2vw, 26px); gap: 10px; }
.ch-logo { height: clamp(44px, 6vh, 64px); max-width: 30vw; }
.ch-ticker { display: inline-flex; align-items: center; gap: 8px; min-width: 0; max-width: min(44vw, 440px);
  padding: 5px 12px 5px 6px; border-radius: 999px; border: 1.5px solid rgba(255,230,160,0.35);
  background: rgba(50,32,14,0.66); color: #fff5dc; font: inherit; font-weight: 800; font-size: 13px; text-align: left; cursor: pointer;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); box-shadow: 0 6px 18px rgba(60,40,20,0.28); }
.ch-ticker[hidden] { display: none; }
.ch-ticker:hover { background: rgba(50,32,14,0.82); }
.ch-ticker .tk-mascot { flex: none; width: 36px; height: 36px; object-fit: contain; filter: drop-shadow(0 2px 3px rgba(0,0,0,0.3)); }
.ch-ticker .tk-text { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.ch-ticker .tk-text b { font-size: 10.5px; letter-spacing: 0.08em; color: #ffd45e; }
.ch-ticker .tk-text span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ch-ticker > svg { flex: none; color: #ffd45e; }
#lobbyList .acctchip { gap: 9px; padding: 4px 12px 4px 4px; border-color: rgba(255,230,160,0.35); color: #fff5dc;
  background: rgba(50,32,14,0.66); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); box-shadow: 0 6px 18px rgba(60,40,20,0.28); }
#lobbyList .acctchip .acct-name { color: #fff; font-size: 14px; }
#lobbyList .acctchip .acct-rating { color: #ffd45e; }
#lobbyList .acctchip .acct-lv { font-size: 11px; font-weight: 900; color: #5a3800; background: linear-gradient(#ffe08a, #f5a91b); padding: 1px 7px; border-radius: 999px; white-space: nowrap; }
#lobbyList .acctchip .acct-lv:empty { display: none; }
#lobbyList .acctchip .acct-avatar { flex: none; width: 36px; height: 36px; border-radius: 50%; overflow: hidden; background: #fff5dc; border: 2px solid #ffe9a8; }
#lobbyList .acctchip .acct-avatar img { display: block; width: 100%; height: 100%; object-fit: contain; }
#lobbyList .acctchip .acct-col { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
#lobbyList .acctchip .acct-row1, #lobbyList .acctchip .acct-row2 { display: flex; align-items: center; gap: 6px; min-width: 0; }
#lobbyList .acctchip .acct-row2 { font-size: 12px; color: #ffe9a8; }
#lobbyList .acctchip .acct-row2 > svg { color: #ffd45e; }
#lobbyList .acct-edit { background: rgba(255,255,255,0.18); color: #fff5dc; }
#lobbyList .acct-edit:hover { background: rgba(255,255,255,0.32); }
.coinpill { display: inline-flex; align-items: center; gap: 6px; height: 40px; padding: 0 14px 0 10px; border-radius: 999px;
  border: 1.5px solid rgba(255,230,160,0.35); background: rgba(50,32,14,0.66); color: #ffd45e; font: inherit; font-weight: 900; font-size: 15px;
  font-variant-numeric: tabular-nums; cursor: pointer; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); box-shadow: 0 6px 18px rgba(60,40,20,0.28); }
.coinpill:hover { background: rgba(50,32,14,0.82); }
.coinpill svg { color: #ffc93c; }
#lobbyList .iconbtn { height: 40px; border-radius: 12px; background: rgba(255,252,244,0.88); border-color: #fff; color: #6b5327; box-shadow: 0 4px 12px rgba(60,40,20,0.2); }
#lobbyList .iconbtn:hover { background: #fff; }
#lobbyList .iconbtn.gold { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; }

/* ---- 舞台列 ---- */
.ch-stage { max-width: 1480px; gap: clamp(12px, 1.4vw, 20px); padding: 4px clamp(12px, 2vw, 26px) 6px; }
.ch-rail { flex: none; align-self: flex-start; width: clamp(176px, 15vw, 224px); display: flex; flex-direction: column; gap: 6px; padding: 10px;
  border-radius: 22px; border: 1.5px solid rgba(255,230,160,0.28);
  background: linear-gradient(rgba(70,44,18,0.80), rgba(45,28,12,0.88));
  box-shadow: 0 14px 40px rgba(50,30,10,0.35), inset 0 1px 0 rgba(255,255,255,0.12); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
.rail-btn { position: relative; display: flex; align-items: center; gap: 11px; padding: 10px 12px; border-radius: 15px; border: 1.5px solid transparent;
  background: transparent; color: #fff1cf; font: inherit; text-align: left; cursor: pointer; transition: background 0.12s, transform 0.08s; }
.rail-btn:hover { background: rgba(255,255,255,0.10); transform: translateX(2px); }
.rail-btn .ricon { flex: none; display: grid; place-items: center; width: 38px; height: 38px; border-radius: 12px; background: rgba(255,255,255,0.12); color: #ffe08a; }
.rail-btn .rtxt { display: flex; flex-direction: column; min-width: 0; line-height: 1.1; gap: 2px; }
.rail-btn .rtxt b { font-size: 15px; font-weight: 900; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rail-btn .rtxt i { font-style: normal; font-size: 10.5px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: rgba(255,241,207,0.62); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rail-btn.primary { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; box-shadow: 0 6px 18px rgba(245,169,27,0.45), inset 0 2px 0 rgba(255,255,255,0.45); }
.rail-btn.primary .ricon { background: rgba(255,255,255,0.35); color: #7a4a00; }
.rail-btn.primary .rtxt i { color: rgba(90,56,0,0.7); }
.rail-btn.primary:hover { transform: translateY(-1px); background: linear-gradient(#fff0bb, #ffbe3d); }
.rail-btn .qdot { position: absolute; top: 6px; right: 8px; min-width: 18px; height: 18px; padding: 0 4px; border-radius: 999px;
  background: #e74c3c; border: 2px solid #fff; color: #fff; font-size: 11px; font-weight: 900; display: flex; align-items: center; justify-content: center; }
.rail-sep { height: 1px; margin: 4px 6px; background: rgba(255,230,160,0.18); }

/* ---- 開放式舞台: 沒有卡, 吉祥物直接站在廣場上 ---- */
.ch-hero { position: relative; container-type: inline-size; flex: none; display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: clamp(150px, 26vh, 250px) 12px 8px; background: none; border: 0; border-radius: 0; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; overflow: visible; }
.ch-cast { position: absolute; left: 0; right: 0; top: 0; height: clamp(150px, 26vh, 250px); pointer-events: none; }
.ch-mascot { position: absolute; bottom: 0; width: auto; max-width: none; object-fit: contain; object-position: bottom center; filter: drop-shadow(0 12px 16px rgba(60,35,10,0.40)); }
.ch-mascot-c { left: 50%; transform: translateX(-50%); height: 100%; z-index: 2; }
.ch-mascot-l { left: calc(50% - clamp(150px, 24cqw, 270px)); height: 66%; transform: rotate(-4deg); }
.ch-mascot-r { right: calc(50% - clamp(150px, 24cqw, 270px)); height: 62%; transform: rotate(4deg); }
.ch-tagline { white-space: pre-line; position: absolute; left: calc(50% - clamp(230px, 36cqw, 400px)); top: 6%; width: clamp(110px, 16cqw, 170px); text-align: center;
  color: #fff; font-weight: 900; font-size: clamp(15px, 2.1cqw, 22px); line-height: 1.25; transform: rotate(-6deg);
  text-shadow: 0 2px 0 rgba(120,70,20,0.6), 0 6px 16px rgba(60,35,10,0.55); }
.ch-count { color: #fff5dc; text-shadow: 0 1px 4px rgba(60,35,10,0.65); }
.ch-count .hs-title { color: #ffe08a; }
.ch-count .hs-hint { color: #fff1cf; }
.ch-cta { z-index: 4; width: min(580px, 96%); gap: 10px; padding: 0; border: 0; background: none; box-shadow: none; }
#quickBtn.ch-play { min-height: 70px; gap: 12px; font-size: 25px; letter-spacing: 2px; border-radius: 22px; border: 3px solid #fff3c9;
  box-shadow: 0 9px 0 #c9871a, 0 18px 34px rgba(120,70,10,0.36), inset 0 2px 0 rgba(255,255,255,0.55); }
#quickBtn.ch-play:active { transform: translateY(4px); box-shadow: 0 5px 0 #c9871a, 0 10px 24px rgba(120,70,10,0.3); }
#quickBtn.ch-play > svg { width: 28px; height: 28px; margin: 0; color: #b8500f; filter: drop-shadow(0 1px 0 #fff3c9); }
.ch-play-txt { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.05; }
.ch-quick-sub { display: block; margin-top: 3px; font-size: 12.5px; font-weight: 800; letter-spacing: 0; color: #8a5a10; }
.ch-quick-sub:empty { display: none; }
.ch-secondary-row { grid-template-columns: 1fr 1.6fr 1fr; gap: 10px; }
/* 主欄自己捲: 舞台 + 按鈕 + 推薦房間在矮視窗放不下時, 底下的 dock 不該把房間卡蓋掉 */
.ch-main { overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; padding-right: 6px; margin-right: -6px; }
.ch-rooms { flex: none; min-height: 200px; }
.room-grid { overflow: visible; }
.room-empty::before { width: clamp(64px, 9vh, 96px); }
.ch-sec { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 50px; padding: 8px 12px; border-radius: 16px;
  border: 2.5px solid #fff; background: rgba(255,252,244,0.94); color: #3a2c12; font-weight: 900; font-size: 15px; text-shadow: none;
  box-shadow: 0 5px 0 rgba(150,110,40,0.22), 0 10px 22px rgba(60,40,20,0.22); }
.ch-sec:hover { background: #fff; transform: translateY(-1px); }
.ch-sec:active { transform: translateY(3px); box-shadow: 0 2px 0 rgba(150,110,40,0.22); }
.ch-sec-create { color: #4a3aa8; } .ch-sec-create svg { color: #6b5ad6; }
.ch-sec-studio { color: #7a4a00; } .ch-sec-studio svg { color: #c98a1a; }
.ch-join-row.ch-sec { display: flex; padding: 5px 6px 5px 12px; border-top: 2.5px solid #fff; cursor: text; }
.ch-sec-join > svg { flex: none; color: #c98a1a; }
.ch-sec-join #codeInput { flex: 1; min-width: 0; width: 100%; padding: 6px 2px; border: 0; background: transparent; text-align: center; font-size: 17px; letter-spacing: 2px; color: #3a2c12; box-shadow: none; }
.ch-sec-join #codeInput:focus { box-shadow: none; }
.ch-sec-join #codeInput::placeholder { color: rgba(110,85,45,0.45); letter-spacing: 0; font-size: 14px; }
.ch-sec-join #joinCodeBtn { flex: none; min-width: 0; min-height: 36px; padding: 6px 13px; border-radius: 11px; border: 2px solid #ffedb0;
  background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; font-size: 13px; box-shadow: none; }
.ch-tutor.big { border-radius: 16px; background: rgba(255,247,222,0.95); border: 2.5px solid #fff; color: #6b4a00; box-shadow: 0 5px 0 rgba(150,110,40,0.22); }
.ch-tutor:not(.big) { color: #fff5dc; text-shadow: 0 1px 4px rgba(60,35,10,0.65); }

/* ---- 卡片: 奶油底、白邊, 在忙碌的背景上要比以前更實 ---- */
.ch-rooms, .ch-panel { background: linear-gradient(rgba(255,253,247,0.95), rgba(255,248,232,0.92)); border: 2.5px solid #fff; border-radius: 22px;
  box-shadow: 0 10px 30px rgba(60,40,20,0.24), 0 3px 0 rgba(184,121,15,0.12), inset 0 2px 0 rgba(255,255,255,0.6); }
.ch-side { min-width: 280px; max-width: 360px; }
.ch-friends { flex: none; gap: 10px; }
.fc-body { display: flex; align-items: center; gap: 12px; }
.fc-faces { display: flex; flex: none; }
.fc-faces img { width: 38px; height: 38px; border-radius: 50%; border: 2.5px solid #fff; background: #ffe9a8; object-fit: cover; margin-left: -10px; box-shadow: 0 2px 6px rgba(60,40,20,0.2); }
.fc-faces img:first-child { margin-left: 0; }
.fc-lines { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.fc-lines b { font-size: 15px; color: #3a2c12; }
.fc-lines span { font-size: 12px; color: #93805f; font-weight: 700; }
.fc-open { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 42px; padding: 8px 14px; font-size: 14px; border-radius: 14px; }
.fc-open .qdot { position: absolute; top: -7px; right: -7px; min-width: 18px; height: 18px; padding: 0 4px; border-radius: 999px;
  background: #e74c3c; border: 2px solid #fff; color: #fff; font-size: 11px; font-weight: 900; display: flex; align-items: center; justify-content: center; }
.fc-open .qdot[hidden] { display: none; }
.ch-main > .ig-cta { width: auto; align-self: center; padding: 6px 12px; border-radius: 999px; background: rgba(50,32,14,0.55); border-color: rgba(255,230,160,0.3); }
.ch-main > .ig-cta .ig-txt b { color: #fff5dc; } .ch-main > .ig-cta .ig-txt i { color: rgba(255,241,207,0.72); } .ch-main > .ig-cta .ig-go { color: #ffd45e; }
#lobbyList .err, #lobbyRoom .err { color: #c0392b; }
.dock-replays .dicon { background: linear-gradient(#b48cff, #7a55e6); }

/* ---- 桌機: dock 收成一條深木色浮條 ---- */
@media (min-width: 821px) {
  /* 房間卡一律橫式 (縮圖在左): 桌機寬度夠, 而直式卡在舞台底下只剩半張 —— 以前只有矮視窗才這樣排 */
  .room-card { display: grid; grid-template-columns: minmax(70px, 38%) minmax(0, 1fr); grid-template-rows: auto auto auto;
    align-items: center; column-gap: 8px; row-gap: 4px; min-height: 84px; padding: 7px; }
  .room-card .thumb { grid-column: 1; grid-row: 1 / -1; align-self: stretch; height: auto; min-height: 78px; }
  .room-card .info, .room-card .rjoin, .room-card .rwatch { grid-column: 2; }
  .room-card .rjoin, .room-card .rwatch { padding-block: 4px; }
  .ch-dock { margin: 0 auto 10px; width: fit-content; max-width: calc(100% - 24px); padding: 8px 14px; border-radius: 22px;
    background: rgba(50,32,14,0.66); border: 1.5px solid rgba(255,230,160,0.28); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); box-shadow: 0 12px 32px rgba(50,30,10,0.35); }
  .dock-btn { background: transparent; border-color: transparent; box-shadow: none; color: #fff1cf; }
  .dock-btn:hover { background: rgba(255,255,255,0.10); border-color: rgba(255,230,160,0.3); color: #fff; box-shadow: none; }
  .dock-btn .qdot { color: #fff; }
}
@media (min-width: 821px) and (max-height: 900px) {
  .ch-hero { padding-top: clamp(110px, 18vh, 170px); gap: 6px; }
  .ch-cast { height: clamp(110px, 18vh, 170px); }
  #quickBtn.ch-play { min-height: 56px; font-size: 21px; }
  .ch-sec { min-height: 42px; }
  .ch-cta { gap: 8px; }
  .ch-rooms { height: auto; }
}
/* 矮視窗: 舞台的吉祥物讓位, 按鈕直接貼頂 */
@media (max-height: 560px) {
  .ch-cast { display: none; }
  .ch-hero { padding-top: 6px; }
}
/* ---- 手機 (image-13): 導覽列收掉, 舞台縮小, 卡片單欄 ---- */
@media (max-width: 820px) {
  .ch-rail { display: none; }
  /* 手機的捲動容器是 .ch-stage (整欄); 桌機給 .ch-main 的 overflow/overscroll-behavior:contain
     在這裡會把觸控捲動吃掉不往外傳 —— 站主實機回報「大廳沒辦法上下滑動」(2026-09-17) */
  .ch-main { overflow: visible; overscroll-behavior: auto; scrollbar-gutter: auto; padding-right: 0; margin-right: 0; }
  .ch-top { padding: 8px 10px; gap: 8px; }
  .ch-logo { height: 42px; }
  .ch-ticker { order: 3; flex: 1 1 100%; max-width: none; }
  .ch-top-right { gap: 6px; }
  #lobbyList .acctchip { padding: 3px 10px 3px 3px; }
  #lobbyList .acctchip .acct-avatar { width: 32px; height: 32px; }
  #lobbyList .acctchip .acct-row2 > svg, #lobbyList .acctchip .acct-rating, #lobbyList .acctchip .acct-rank, #lobbyList .acctchip .acct-bucket { display: none; }
  #lobbyList .acctchip .acct-name { max-width: 84px; }
  .ch-top-right { flex: 1 1 auto; justify-content: flex-end; flex-wrap: nowrap; }
  /* 齒輪那張設定面板裡本來就有音樂／音效／全螢幕; 手機頂列只留設定與登出 (房間頁同一套邏輯) */
  .ch-top-right #helpLink, .ch-top-right #fsBtn2, .ch-top-right #muteBtn2, .ch-top-right #sfxBtn2 { display: none; }
  .coinpill { height: 36px; font-size: 14px; padding: 0 12px 0 9px; }
  #lobbyList .iconbtn { height: 36px; min-width: 36px; padding: 0 10px; font-size: 12px; }
  .ch-hero { padding: clamp(150px, 30vh, 230px) 0 6px; }
  .ch-cast { height: clamp(150px, 30vh, 230px); }
  .ch-mascot-l { left: 1%; height: 58%; }
  .ch-mascot-r { right: 1%; height: 54%; }
  .ch-tagline { left: 3%; top: 0; width: 120px; font-size: 15px; }
  .ch-cta { width: 100%; }
  #quickBtn.ch-play { min-height: 62px; font-size: 22px; }
  .ch-secondary-row { grid-template-columns: 1fr 1fr; gap: 8px; }
  .ch-join-row.ch-sec { grid-column: 1 / -1; }
  .ch-side .ch-panel { height: min(300px, 42vh); }
  .ch-side .ch-friends { height: auto; }
  .ch-main > .ig-cta { width: 100%; align-self: stretch; }
}

/* =========================================================================
   2026-09-17 房間重設計 (image-14 參考稿): 同一座樂園當背景, 木牌房名, 奶油卡片,
   金色開始鍵。座位維持 8 格自由分隊 (我們的隊伍人數不固定, 不做紅藍 1/4)。
   ========================================================================= */
#lobbyRoom { color: #3d3020; }
#lobbyRoom .arc-title { display: flex; justify-content: center; text-shadow: none; }
#lobbyRoom .rm-sign { display: inline-flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; padding: 8px 22px; border-radius: 16px;
  background: linear-gradient(#a8743f, #7a4f26); border: 3px solid #d0a06a; color: #fff5dc; text-shadow: 0 2px 0 rgba(60,35,10,0.6);
  box-shadow: 0 6px 0 #5a3618, 0 12px 26px rgba(60,35,10,0.35), inset 0 2px 0 rgba(255,255,255,0.25); }
#lobbyRoom .rm-sign #roomCode { color: #ffd45e; }
#lobbyRoom .arc-header .pill { border-radius: 14px; }
#lobbyRoom .arc-header #leaveBtn { background: linear-gradient(#a8743f, #7a4f26); border-color: #d0a06a; color: #fff5dc; }
#lobbyRoom .arc-header .pill.blue, #lobbyRoom .arc-header .pill.ghost { background: rgba(255,252,244,0.92); border-color: #fff; color: #6b5327; text-shadow: none; box-shadow: 0 4px 0 rgba(150,110,40,0.22); }
#lobbyRoom .arc-header .pill.yellow { border-color: #ffedb0; box-shadow: 0 4px 0 #c9871a; }
#lobbyRoom .arc-title .rm-invite { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; text-shadow: none; box-shadow: 0 3px 0 #c9871a; }
#lobbyRoom .slot { background: rgba(255,252,244,0.95); border: 2.5px solid #fff; border-radius: 18px; color: #3a2c12; box-shadow: 0 5px 0 rgba(150,110,40,0.18), 0 10px 22px rgba(60,40,20,0.2); }
#lobbyRoom .slot.empty { background: rgba(255,252,244,0.42); border-style: dashed; border-color: rgba(255,255,255,0.9); color: #7a4a00; }
#lobbyRoom .slot .pname { color: #3a2c12; }
#lobbyRoom .slot.team-editing { outline: 3px solid #f5a91b; }
#lobbyRoom .side { background: linear-gradient(rgba(255,253,247,0.95), rgba(255,248,232,0.92)); border: 2.5px solid #fff; border-radius: 22px; box-shadow: 0 10px 30px rgba(60,40,20,0.24); }
#lobbyRoom .room-setting { background: rgba(255,255,255,0.62); border: 1.5px solid rgba(150,115,55,0.18); border-radius: 16px; }
#lobbyRoom .panel-label { color: #6b5327; letter-spacing: 0.04em; }
#lobbyRoom #modeSel .pill { display: inline-flex; align-items: center; justify-content: center; gap: 6px; border: 2px solid rgba(150,115,55,0.2); border-radius: 14px; background: #fff; color: #6b5327; box-shadow: 0 3px 0 rgba(150,110,40,0.14); text-shadow: none; }
#lobbyRoom #modeSel .pill svg { flex: none; }
#lobbyRoom #modeSel .pill.sel { border-color: #f0b926; color: #6b4700; background: linear-gradient(#fff3c4, #ffd95c); box-shadow: 0 3px 0 #d69b17, inset 0 1px #fff; }
#lobbyRoom .rules-toggle, #lobbyRoom .community-map-btn { background: #fff; color: #6b5327; border: 2px solid rgba(150,115,55,0.2); border-radius: 14px; box-shadow: 0 3px 0 rgba(150,110,40,0.14); text-shadow: none; }
#lobbyRoom .rules-panel { background: rgba(255,255,255,0.5); border-color: rgba(150,115,55,0.2); }
#lobbyRoom .rules-sub { color: #6b5327; } #lobbyRoom .rules-hint { color: #93805f; }
#lobbyRoom .dropban { background: #fff; border-color: rgba(150,115,55,0.2); } #lobbyRoom .dropban span { color: #6b5327; }
#lobbyRoom .dropdown, #lobbyRoom select.slotkind { background-color: #fff; color: #6b5327; border-color: rgba(150,115,55,0.2); box-shadow: 0 3px 0 rgba(150,110,40,0.14);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23b8790f' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); }
#lobbyRoom .dropdown:hover, #lobbyRoom select.slotkind:hover, #lobbyRoom .dropdown:focus, #lobbyRoom select.slotkind:focus { border-color: #f0b926; }
#lobbyRoom .dropdown option, #lobbyRoom select.slotkind option { background: #fff; color: #3a2c12; }
#lobbyRoom .map-thumb { border-color: #fff; border-radius: 14px; }
#lobbyRoom .teamblock { border-radius: 14px; border-color: #fff; }
#lobbyRoom .teamblock.sel { outline-color: #f5a91b; }
#lobbyRoom .charblock { border-radius: 14px; border-color: #fff; background-color: #fff; box-shadow: 0 3px 0 rgba(150,110,40,0.14); }
#lobbyRoom .charblock.sel { outline-color: #f5a91b; background-color: #fff8dc; }
#lobbyRoom #charStats { background: linear-gradient(#3b6f9c, #2b567c); border: 2.5px solid #fff; border-radius: 14px; }
#lobbyRoom .side-foot .pill.big { border-radius: 22px; border: 3px solid #fff3c9; letter-spacing: 2px; box-shadow: 0 8px 0 #c9871a, 0 14px 30px rgba(120,70,10,0.35), inset 0 2px 0 rgba(255,255,255,0.55); }
#lobbyRoom .side-foot .pill.big:active { transform: translateY(4px); box-shadow: 0 4px 0 #c9871a; }
#lobbyRoom #readyBtn.pill.big { border-color: #d9f7de; box-shadow: 0 8px 0 #1f7d34, 0 14px 30px rgba(20,80,30,0.35), inset 0 2px 0 rgba(255,255,255,0.4); }
#lobbyRoom #readyBtn.pill.big:active { box-shadow: 0 4px 0 #1f7d34; }
#lobbyRoom .wait-msg.waiting { background: rgba(107,83,39,0.12); color: #6b5327; }
#lobbyRoom .auto-ready { border-color: rgba(150,115,55,0.25); background: rgba(150,115,55,0.08); color: #6b5327; }
#lobbyRoom .auto-ready .box { border-color: rgba(150,115,55,0.4); }
#lobbyRoom .chat { background: linear-gradient(rgba(255,253,247,0.95), rgba(255,248,232,0.92)); border: 2.5px solid #fff; border-radius: 22px; box-shadow: 0 10px 30px rgba(60,40,20,0.24); }
#lobbyRoom .chat-title { color: #6b5327; }
#lobbyRoom .chat .chat-log { color: #6b5327; }
#lobbyRoom .chat-row input { border-color: rgba(150,115,55,0.2); background: #fff; color: #3a2c12; }
#lobbyRoom .chat-log .cwho { color: #b8790f; }
#lobbyRoom .chat-log .cbubble { background: #fff; color: #3a2c12; border: 1.5px solid rgba(150,115,55,0.18); }
#lobbyRoom .chat-log .cmsg.me .cbubble { background: linear-gradient(#ffe79a, #ffd667); color: #6b4a00; border-color: #ffedb0; }
/* 房間聊天可收合 (image-14 的「收合」): 聊天是次要的, 收起來座位跟設定就多一截 */
#lobbyRoom .chat-tog { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; padding: 4px 8px; border: 0; border-radius: 999px; background: none; color: #93805f; font: inherit; font-weight: 800; font-size: 12.5px; cursor: pointer; }
#lobbyRoom .chat-tog:hover { background: rgba(150,115,55,0.1); }
#lobbyRoom .chat-tog svg { transition: transform 0.16s; }
#lobbyRoom .chat.collapsed { flex: none; min-height: 0; }
#lobbyRoom .chat.collapsed .chat-log, #lobbyRoom .chat.collapsed .chat-row { display: none; }
#lobbyRoom .chat.collapsed .chat-tog svg { transform: rotate(180deg); }
/* 手機底部固定動作條: 藍色漸層換成奶油 (媒體條件跟原規則一模一樣, 只換顏色) */
@media (max-width: 720px) and (min-height: 520px), (max-width: 1100px) and (orientation: portrait) and (min-height: 520px) {
  #lobbyRoom .side-foot { background: linear-gradient(rgba(255,248,232,0), rgba(255,248,232,0.96) 42%); box-shadow: 0 -6px 20px rgba(60,40,20,0.22); }
}
@media (max-width: 720px) and (max-height: 519px) {
  #lobbyRoom .side-foot { background: linear-gradient(rgba(255,248,232,0), rgba(255,248,232,0.96) 50%); box-shadow: 0 -5px 16px rgba(60,40,20,0.2); }
}

/* =========================================================================
   2026-09-17 子頁面換皮: 從大廳點進去的每一頁 (關卡工作室 / 社群關卡 / 戰績 / 回放播放器 /
   任務成就 / 商城 / 個人空間 / 購買·改名·訪客對話框 / 設定抽屜 / 園區共用 sheet) 以前各自
   一套深藍玻璃 (#1f5f8f→#0a2842 + #7fcdee 邊), 跟重設計後的樂園大廳像兩款遊戲。
   這裡只換顏色與邊角, 不動排版與任何 id/class —— eval/quest_ach_v2_ui.py 釘著 #panelBody
   / .prog-card / .qchest 那些名字。共用詞彙: 深木頭列 rgba(50,32,14,.66)+#fff5dc 字,
   奶油卡 rgba(255,253,247,.95)+#fff 邊, 主鍵蜂蜜黃, 字 #3a2c12 / #6b5327 / #93805f。
   ========================================================================= */
/* ---- 共用: 全頁式殼 (關卡工作室、戰績) ---- */
.level-studio { color: #3a2c12;
  background: linear-gradient(rgba(255,250,238,0.10), rgba(60,40,20,0.30) 90%), url("assets/scenes/lobby_bg_wide.webp?v=1") center 60% / cover no-repeat; }
@media (orientation: portrait) { .level-studio { background-image: linear-gradient(rgba(255,250,238,0.06), rgba(60,40,20,0.32) 90%), url("assets/scenes/lobby_bg_tall.webp?v=1"); background-position: center top; } }
.level-studio .ls-head, .level-community .le-head, #matchLog .ls-head { background: rgba(50,32,14,0.70); border-bottom: 1.5px solid rgba(255,230,160,0.30); color: #fff5dc;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.level-studio .ls-title p, .level-community .le-head p, .ls-muted, .ls-empty, .ls-card-meta, #matchLog .replay-note { color: #ffe9a8; }
.ls-empty, .ls-muted, .ls-card-meta { color: #93805f; }
.ls-tab { background: rgba(255,252,244,0.90); border: 2px solid #fff; color: #6b5327; }
.ls-tab.on, .ls-tab.sel, .ls-tab[aria-selected="true"] { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; }
.level-studio #lsBack, #matchLog #mlBack { background: linear-gradient(#a8743f, #7a4f26); border: 2px solid #d0a06a; color: #fff5dc; text-shadow: none; box-shadow: 0 4px 0 #5a3618; }
.ls-pane { color: #3a2c12; }
.ls-card, .ls-new { background: rgba(255,253,247,0.95); border: 2.5px solid #fff; border-radius: 18px; color: #3a2c12; box-shadow: 0 8px 22px rgba(60,40,20,0.20); }
.ls-new { border-style: dashed; border-color: rgba(255,255,255,0.95); background: rgba(255,252,244,0.86); color: #7a4a00; }
.ls-empty, .level-studio .ls-pane > p { color: #fff5dc; text-shadow: 0 1px 4px rgba(60,35,10,0.65); }
.ls-new:hover, .ls-card:hover { border-color: #f5a91b; }
.ls-badge { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; }
.ls-step { background: rgba(255,253,247,0.94); border: 2px solid #fff; color: #3a2c12; box-shadow: 0 6px 18px rgba(60,40,20,0.18); }
.ls-step-n { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; }
.ls-status { color: #6b5327; }
.level-studio input, .level-studio textarea, .level-studio select { background: #fff; color: #3a2c12; border: 1.5px solid rgba(150,115,55,0.28); }
.level-studio input::placeholder, .level-studio textarea::placeholder { color: #a08a63; }
/* 編輯器: 棋盤與工具維持深底 (畫格子要看得清), 只把外殼、欄位、按鈕換成木頭與奶油 */
.le-shell { background: linear-gradient(rgba(255,253,247,0.95), rgba(255,248,232,0.92)); border: 2.5px solid #fff; border-radius: 22px; color: #3a2c12; box-shadow: 0 10px 30px rgba(60,40,20,0.24); }
.le-head { color: #3a2c12; border-bottom: 1px solid rgba(150,115,55,0.18); }
.le-head p, .le-muted, .le-tip { color: #93805f; }
.le-icon { background: rgba(245,169,27,0.18); color: #7a4a00; }
.le-fields input, .le-fields select, .le-fields textarea { background: #fff; color: #3a2c12; border: 1.5px solid rgba(150,115,55,0.28); }
.le-actions button, .le-tabs button { background: rgba(255,252,244,0.95); color: #6b5327; border: 2px solid rgba(150,115,55,0.22); }
.le-tabs button.on, .le-tabs button.sel, .le-actions button.primary, .le-play { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; border-color: #ffedb0; }
.le-group-tab { background: rgba(255,252,244,0.9); color: #6b5327; border-color: rgba(150,115,55,0.22); }
.le-group-tab.on { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; }
.le-chip { background: rgba(245,169,27,0.16); color: #7a4a00; }
.le-status { color: #6b5327; }
.le-tool { background: rgba(255,255,255,0.85); border-color: rgba(150,115,55,0.22); }
.le-tool.sel, .le-tool.on { border-color: #f5a91b; box-shadow: 0 0 0 3px rgba(245,169,27,0.25); }
/* ---- 社群關卡 ---- */
.level-community { background: rgba(40,26,12,0.62); color: #3a2c12; }
.lc-shell { background: linear-gradient(rgba(255,253,247,0.97), rgba(255,248,232,0.95)); border: 3px solid #fff; border-radius: 22px; color: #3a2c12; box-shadow: 0 16px 44px rgba(60,40,20,0.35); }
.lc-shell .le-head { background: none; color: #3a2c12; backdrop-filter: none; -webkit-backdrop-filter: none; }
.lc-shell .le-head p { color: #93805f; }
.lc-tools input, .lc-tools select { background: #fff; color: #3a2c12; border: 2px solid rgba(150,115,55,0.22); }
.lc-tools select option { color: #3a2c12; }
.lc-tools button { background: rgba(255,252,244,0.95); color: #6b5327; border: 2px solid rgba(150,115,55,0.22); }
.lc-tools #lcMine.on, .lc-tools #lcCreate { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; border-color: #ffedb0; }
.lc-card { background: rgba(255,255,255,0.75); border: 2px solid #fff; border-radius: 16px; color: #3a2c12; box-shadow: 0 5px 0 rgba(150,110,40,0.14); }
.lc-card:hover { border-color: #f5a91b; }
.lc-title small { background: rgba(245,169,27,0.18); color: #7a4a00; }
.lc-meta, .lc-desc { color: #93805f; }
.lc-card button { background: rgba(255,252,244,0.95); color: #6b5327; border: 2px solid rgba(150,115,55,0.22); }
.lc-card .play { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; border-color: #ffedb0; }
.lc-stars { color: #d9c9a5; } .lc-stars .on { color: #f5a91b; }
.level-community .le-status { color: #c0392b; }
/* ---- 戰績 ---- */
#matchLog .replay-card { background: rgba(255,253,247,0.95); border: 2.5px solid #fff; box-shadow: 0 6px 18px rgba(60,40,20,0.18); }
#matchLog .replay-note { color: #fff5dc; text-shadow: 0 1px 4px rgba(60,35,10,0.6); }
.rp-thumb { background: #2b4a2a; }
/* ---- 回放播放器 / 戰績卡 (全頁) ---- */
.replay-dialog { background: linear-gradient(rgba(255,250,238,0.04), rgba(60,40,20,0.55)), url("assets/scenes/lobby_bg_wide.webp?v=1") center 60% / cover no-repeat; color: #fff5dc; }
.replay-box { background: rgba(50,32,14,0.72); border: 2px solid rgba(255,230,160,0.30); border-radius: 22px; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.replay-more { background: rgba(255,252,244,0.10); border-color: rgba(255,230,160,0.30); }
.replay-more summary, .replay-share-row { color: #ffe9a8; }
.replay-speed { background: rgba(255,252,244,0.92); border: 2px solid #fff; color: #6b5327; }
.replay-speed option { color: #3a2c12; }
#replayPlay { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; border-color: #ffedb0; }
.sharecard { background: rgba(40,26,12,0.84); color: #fff5dc; }
.sharecard p, .sharecard small { color: #ffe9a8; }
/* ---- 任務 / 成就 面板 ---- */
#panel { background: rgba(40,26,12,0.62); }
.panel-box { background: linear-gradient(rgba(255,253,247,0.97), rgba(255,248,232,0.95)); border: 3px solid #fff; border-radius: 22px; color: #3a2c12; box-shadow: 0 16px 44px rgba(60,40,20,0.35); }
.panel-title { color: #3a2c12; text-shadow: none; }
.panel-head .coinbal { background: rgba(50,32,14,0.72); color: #ffd45e; border: 1.5px solid rgba(255,230,160,0.35); }
#panelCloseBtn, .panel-head .pill.ghost { background: linear-gradient(#a8743f, #7a4f26); border-color: #d0a06a; color: #fff5dc; text-shadow: none; box-shadow: 0 3px 0 #5a3618; }
.panel-tabs .ptab { background: rgba(255,252,244,0.95); border: 2px solid rgba(150,115,55,0.22); color: #6b5327; text-shadow: none; box-shadow: none; }
.panel-tabs .ptab.on, .panel-tabs .ptab.sel { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; }
.prog-card { background: rgba(255,255,255,0.78); border: 2px solid #fff; border-radius: 16px; color: #3a2c12; box-shadow: 0 4px 0 rgba(150,110,40,0.12); }
.prog-card.ready { border-color: #f5a91b; box-shadow: 0 0 0 3px rgba(245,169,27,0.25), 0 4px 0 rgba(150,110,40,0.12); }
.prog-card .picon { background: rgba(245,169,27,0.16); color: #b8790f; }
.prog-card .pname { color: #3a2c12; }
.prog-card .pdesc, .prog-card .pcount, .qreset, .lb-mine-note, .ptiers, .punlock { color: #93805f; }
.prog-card .preward, .qchest small, .sp-shelf-n { color: #b8790f; }
.prog-card .pbar, .qbar { background: rgba(150,115,55,0.16); }
.qhead { background: rgba(255,232,150,0.35); border: 2px solid #fff; color: #3a2c12; }
.qhead b, .qweek-head { color: #3a2c12; }
.qchest { background: rgba(255,255,255,0.78); border: 2px solid #fff; color: #3a2c12; }
.qchest.ready { background: linear-gradient(#fff3c4, #ffd95c); border-color: #ffedb0; }
.lb-row { background: rgba(255,255,255,0.78); border: 2px solid #fff; color: #3a2c12; }
.lb-row.mine { background: linear-gradient(#fff3c4, #ffd95c); }
.pshow, .pill.pmini, .pill.preroll, .pill.pfold { background: rgba(255,252,244,0.95); color: #6b5327; border-color: rgba(150,115,55,0.22); text-shadow: none; box-shadow: none; }
.pill.claim-all { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; border-color: #ffedb0; }
.sp-shelf { background: rgba(255,255,255,0.7); border: 2px solid #fff; color: #3a2c12; }
/* ---- 商城: 青藍換成同一座樂園 + 木頭列 ---- */
#shop { background: linear-gradient(rgba(255,250,238,0.06), rgba(60,40,20,0.26) 90%), url("assets/scenes/lobby_bg_wide.webp?v=1") center 60% / cover no-repeat; }
#shop .arc-screen { background: none; }
#shop .arc-header { background: rgba(50,32,14,0.70); border-bottom: 1.5px solid rgba(255,230,160,0.30); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
#shop .arc-title { color: #fff5dc; text-shadow: 0 2px 0 rgba(60,35,10,0.5); }
#shop .arc-header .pill.blue, #shop .arc-header .pill.ghost { background: rgba(255,252,244,0.92); border-color: #fff; color: #6b5327; text-shadow: none; box-shadow: 0 4px 0 rgba(150,110,40,0.22); }
#shop .coinbal { background: rgba(50,32,14,0.72); color: #ffd45e; border: 1.5px solid rgba(255,230,160,0.35); }
.shop-preview { background: linear-gradient(rgba(255,253,247,0.95), rgba(255,248,232,0.92)); border: 2.5px solid #fff; box-shadow: 0 10px 30px rgba(60,40,20,0.24); }
.shop-prevlabel { color: #6b5327; }
.shop-hint { color: #fff5dc; text-shadow: 0 1px 4px rgba(60,35,10,0.65); }
.shop-main { color: #3a2c12; }
.shop-tabs .pill { background: rgba(255,252,244,0.95); color: #6b5327; border-color: #fff; text-shadow: none; box-shadow: 0 3px 0 rgba(150,110,40,0.14); }
.shop-tabs .pill.sel, .shop-tabs .pill.on { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; border-color: #ffedb0; }
/* ---- 個人空間 ---- */
#spaceView { background: rgba(40,26,12,0.62); }
.space-box { background: linear-gradient(rgba(255,253,247,0.97), rgba(255,248,232,0.95)); border: 3px solid #fff; border-radius: 22px; color: #3a2c12; box-shadow: 0 16px 44px rgba(60,40,20,0.35); }
.space-title { color: #3a2c12; text-shadow: none; }
#spaceCloseBtn { background: linear-gradient(#a8743f, #7a4f26); border-color: #d0a06a; color: #fff5dc; text-shadow: none; box-shadow: 0 3px 0 #5a3618; }
.space-bio, .sp-xp-text, .space-hint { color: #6b5327; text-shadow: none; }
.sp-xp-bar { background: rgba(150,115,55,0.16); border-color: rgba(150,115,55,0.25); }
.sp-tile { background: rgba(255,255,255,0.78); border: 2px solid #fff; color: #3a2c12; }
.sp-tile.gold { color: #b8790f; }
.space-replays { background: rgba(255,255,255,0.6); border: 2px solid #fff; color: #3a2c12; }
.replay-head, .replay-row { color: #3a2c12; border-color: rgba(150,115,55,0.18); }
.replay-note { color: #93805f; }
/* ---- 購買 / 改名 / 訪客 對話框 ---- */
#buyConfirm, #nickEdit, #guestPrompt { background: rgba(40,26,12,0.62); }
.buy-box { background: linear-gradient(rgba(255,253,247,0.98), rgba(255,248,232,0.96)); border: 3px solid #fff; border-radius: 22px; color: #3a2c12; box-shadow: 0 16px 44px rgba(60,40,20,0.35); }
.buy-title { color: #3a2c12; } .buy-name { color: #6b5327; } .nick-hint { color: #93805f; }
#nickInput { border: 2px solid rgba(150,115,55,0.25); color: #3a2c12; background: #fff; }
.buy-box .pill.blue, .buy-box .pill.ghost { background: rgba(255,252,244,0.95); border-color: #fff; color: #6b5327; text-shadow: none; box-shadow: 0 3px 0 rgba(150,110,40,0.14); }
/* ---- 設定抽屜 ---- */
#gameSettings { background: rgba(50,32,14,0.92); border: 1.5px solid rgba(255,230,160,0.35); color: #fff5dc; border-radius: 18px; }
#gameSettings .gstitle { color: #fff; }
#gameSettings .gssec, #gameSettings .gsvol label, #gameSettings label { color: #ffe9a8; }
#gameSettings .gslang { background: rgba(255,252,244,0.12); color: #fff5dc; border-color: rgba(255,230,160,0.3); }
#gameSettings .gslang.sel { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; }
#gameSettings .pill.blue, #gameSettings .pill.ghost { background: rgba(255,252,244,0.14); border-color: rgba(255,230,160,0.35); color: #fff5dc; text-shadow: none; }
/* ---- 園區共用 sheet (shared/client/social.js): 它有變數鉤子, 只設變數不改共用預設 ---- */
:root { --soc-sheet: linear-gradient(rgba(255,253,247,0.98), rgba(255,248,232,0.96)); --soc-edge: #fff; --soc-ink: #3a2c12; --soc-secfg: #6b5327;
  --soc-card: linear-gradient(rgba(255,255,255,0.85), rgba(255,250,240,0.85)); --soc-cardfg: #3a2c12; --soc-accent: #f5a91b; }

/* UI system v2 foundation. New screens consume these tokens directly; existing
   screens migrate onto them without changing gameplay-owned ids or event hooks. */
:root {
  --ui-cream-0: #fffdf7; --ui-cream-1: #fff8e8; --ui-cream-2: #f6e8c8;
  --ui-ink: #3a2c12; --ui-muted: #806d4d; --ui-gold: #f5a91b; --ui-gold-dark: #9d6508;
  --ui-blue: #2e8fd6; --ui-green: #35ad58; --ui-danger: #d94b52;
  --ui-radius-sm: 11px; --ui-radius-md: 18px; --ui-radius-lg: 24px;
  --ui-shadow-card: 0 14px 38px rgba(63,42,19,.22), inset 0 1px 0 rgba(255,255,255,.75);
  --ui-speed-fast: 160ms; --ui-speed: 220ms;
}
button, a, input, select, textarea { -webkit-tap-highlight-color: transparent; }
button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 3px solid rgba(46,143,214,.78); outline-offset: 3px;
}
@media (prefers-reduced-motion: no-preference) {
  .panel-box, .buy-box, .space-box, .ch-ovbox { animation: uiEnter var(--ui-speed) cubic-bezier(.2,.75,.2,1) both; }
  @keyframes uiEnter { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: none; } }
}

/* Sign-in is the first product screen, not a utility dialog. */
#menuScreen .menu-card { width: min(88vw, 390px); padding: 20px; gap: 14px;
  background: linear-gradient(rgba(255,253,247,.97), rgba(255,248,232,.94));
  border: 2px solid rgba(255,255,255,.94); border-radius: var(--ui-radius-lg);
  box-shadow: 0 22px 58px rgba(55,35,15,.34), inset 0 1px 0 #fff; color: var(--ui-ink);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); }
#menuScreen .rating-mark { color: var(--ui-ink); background: rgba(255,255,255,.55); border-radius: 14px; padding: 8px; }
#menuScreen .rating-mark p, #menuScreen .auth-guest-hint { color: var(--ui-muted); opacity: 1; }
#menuScreen .auth-or { color: #9a825a; }
#menuScreen .auth-or::before, #menuScreen .auth-or::after { background: rgba(150,115,55,.22); }
#menuScreen #authUser, #menuScreen #authPass, #menuScreen #guestName { color: var(--ui-ink); -webkit-text-fill-color: var(--ui-ink);
  caret-color: var(--ui-blue); background: rgba(255,255,255,.82); border: 1.5px solid rgba(150,115,55,.28); }
#menuScreen #authUser::placeholder, #menuScreen #authPass::placeholder, #menuScreen #guestName::placeholder {
  color: #a49273; -webkit-text-fill-color: #a49273; }
#menuScreen #authUser:focus, #menuScreen #authPass:focus, #menuScreen #guestName:focus {
  border-color: var(--ui-gold); box-shadow: 0 0 0 4px rgba(245,169,27,.14); }
#menuScreen #guestBtn { background: linear-gradient(#fff, #f5ead2); color: #6b5327; border-color: #fff; text-shadow: none; }
#menuScreen .auth-guest-hint a { color: var(--ui-gold-dark); }
@media (max-width: 480px) {
  #menuScreen .menu-card { width: calc(100vw - 20px); box-sizing: border-box; margin-bottom: max(14px, env(safe-area-inset-bottom)); padding: 16px; }
  #menuScreen .rating-mark { padding: 6px; }
}

/* =========================================================================
   2026-09-17 第二輪: 教學／練習面板換皮 (對局 HUD)、商城重設計 (image-18)、任務面板重排
   (image-19)、大廳公告板與聊天泡泡打磨。同樣附在檔尾後蓋, 不動 id/class。
   ========================================================================= */
/* ---- 教學面板 (#tutorPanel) / 練習面板 (#practicePanel): 奶油卡, 棋盤上仍看得清 ---- */
.tt-card { background: rgba(255,253,247,0.95); border: 2.5px solid #fff; border-radius: 18px; color: #3a2c12; box-shadow: 0 8px 24px rgba(60,40,20,0.28); }
.tt-stage { color: #b8790f; }
.tt-title { color: #3a2c12; }
.tt-hint { color: #6b5327; }
.tt-controls { color: #7a4a00; background: rgba(255,232,150,0.45); border: 1.5px solid #ffdf8a; }
.tt-demo-state { color: #1f7d34; background: rgba(111,220,111,0.25); }
.tt-barwrap { background: rgba(150,115,55,0.16); }
.tt-bar { background: linear-gradient(90deg, #ffe08a, #f5a91b); }
.tt-goal { color: #5a3800; text-shadow: none; }
.tt-legend { color: #93805f; }
.tt-flash { color: #c0392b; }
.tt-actions .pill { background: rgba(255,252,244,0.95); border-color: rgba(150,115,55,0.22); color: #6b5327; text-shadow: none; box-shadow: 0 3px 0 rgba(150,110,40,0.14); }
.tt-actions .pill.blue { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; }
.tt-clear { background: rgba(255,253,247,0.97); border: 2.5px solid #ffedb0; border-radius: 22px; color: #3a2c12; box-shadow: 0 12px 34px rgba(60,40,20,0.3); }
.tt-clear-title { color: #b8790f; }
.tut-all { background: rgba(40,26,12,0.68); }
.tut-all-box { background: linear-gradient(rgba(255,253,247,0.98), rgba(255,248,232,0.96)); border: 3px solid #fff; border-radius: 22px; color: #3a2c12; }
.tut-all-title { color: #b8790f; }
#prExit { background: linear-gradient(#a8743f, #7a4f26); border-color: #d0a06a; color: #fff5dc; text-shadow: none; }
#prBody { background: rgba(255,253,247,0.95); border: 2.5px solid #fff; border-radius: 18px; color: #3a2c12; box-shadow: 0 8px 24px rgba(60,40,20,0.28); }
#prBody .pr-label { color: #93805f; opacity: 1; }
#prBody .pr-name, #prBody .pr-val { color: #3a2c12; }
#prBody .pr-btn, #prBody .pr-item, #prBody .pr-abbtn { background: #fff; border-color: rgba(150,115,55,0.25); color: #6b5327; }
#prBody .pr-btn:active, #prBody .pr-item:active { background: #fff3c4; }
#prBody .pr-abbtn.on { border-color: #f5a91b; background: rgba(255,224,138,0.45); }
#prBody .dropdown { background-color: #fff; color: #6b5327; border-color: rgba(150,115,55,0.2); box-shadow: 0 3px 0 rgba(150,110,40,0.14); }
#prBody .pr-actions .pill.blue { background: rgba(255,252,244,0.95); border-color: rgba(150,115,55,0.22); color: #6b5327; text-shadow: none; }

/* ---- 商城 (image-18): 夜晚精品店 + 木牌招牌 + 分頁圖示 + 右側詳情 ---- */
#shop { background: linear-gradient(rgba(20,12,6,0.10), rgba(20,12,6,0.42) 92%), url("assets/scenes/shop_bg_wide.webp?v=1") center 55% / cover no-repeat; }
@media (orientation: portrait) { #shop { background-image: linear-gradient(rgba(20,12,6,0.12), rgba(20,12,6,0.46) 92%), url("assets/scenes/shop_bg_tall.webp?v=1"); background-position: center top; } }
#shop .arc-header { background: transparent; border: 0; backdrop-filter: none; -webkit-backdrop-filter: none; padding: 12px clamp(14px, 3vw, 34px) 4px; }
#shop .arc-title { position: relative; flex: 0 1 auto; margin: 0 auto; display: inline-flex; flex-direction: column; align-items: center; gap: 0; padding: 10px 34px 12px; border-radius: 18px;
  background: linear-gradient(#a8743f, #7a4f26); border: 3px solid #d0a06a; color: #ffe9a8; font-size: clamp(20px, 3vmin, 30px); letter-spacing: 4px;
  text-shadow: 0 2px 0 rgba(60,35,10,0.7), 0 0 14px rgba(255,220,120,0.35); box-shadow: 0 7px 0 #5a3618, 0 14px 30px rgba(20,12,6,0.5), inset 0 2px 0 rgba(255,255,255,0.25); }
#shop .arc-title svg { display: none; }
#shop .arc-title::after { content: 'BONMIPANG SHOP'; display: block; margin-top: 2px; font-size: 10.5px; letter-spacing: 0.24em; color: rgba(255,233,168,0.8); text-shadow: none; }
#shop .arc-header #shopBackBtn { background: linear-gradient(#a8743f, #7a4f26); border: 2px solid #d0a06a; color: #fff5dc; text-shadow: none; box-shadow: 0 4px 0 #5a3618; border-radius: 14px; }
#shop .arc-header #labBtn { background: rgba(255,252,244,0.92); border-color: #fff; color: #6b5327; text-shadow: none; }
#shop .coinbal { background: rgba(50,32,14,0.78); color: #ffd45e; border: 1.5px solid rgba(255,230,160,0.4); box-shadow: 0 6px 18px rgba(20,12,6,0.4); }
#shop .coinbal svg { color: #ffc93c; }
.shop-body { max-width: 1480px; gap: clamp(12px, 1.6vw, 22px); padding: clamp(10px, 2vh, 20px) clamp(14px, 3vw, 40px); }
.shop-preview { width: clamp(180px, 20vw, 260px); background: radial-gradient(ellipse at 50% 0%, rgba(255,214,120,0.35), transparent 60%), rgba(50,32,14,0.60);
  border: 2px solid rgba(255,230,160,0.35); border-radius: 22px; box-shadow: 0 10px 30px rgba(20,12,6,0.45), inset 0 1px 0 rgba(255,255,255,0.12); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.shop-preview canvas { border-radius: 14px; }
.shop-prevlabel { color: #ffe9a8; font-size: 12px; text-align: center; }
.shop-char { opacity: 0.6; } .shop-char.sel { opacity: 1; }
.shop-main { padding: 12px; border-radius: 22px; background: linear-gradient(rgba(255,253,247,0.95), rgba(255,248,232,0.92)); border: 2.5px solid #fff; box-shadow: 0 10px 30px rgba(20,12,6,0.4); }
.shop-tabs { gap: 8px; flex-wrap: wrap; }
.shop-tabs .pill { display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; border-radius: 999px; border: 2px solid rgba(255,230,160,0.35); text-shadow: none;
  background: linear-gradient(rgba(70,44,18,0.92), rgba(45,28,12,0.95)); color: #fff1cf; box-shadow: 0 3px 0 rgba(20,12,6,0.35); }
.shop-tabs .pill svg { flex: none; color: #ffe08a; }
.shop-tabs .pill.sel { outline: 0; background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; box-shadow: 0 3px 0 #c9871a, 0 0 0 3px rgba(255,224,138,0.35); }
.shop-tabs .pill.sel svg { color: #7a4a00; }
.shop-grid { padding: 4px 2px; }
.shop-card { background: linear-gradient(#fffdf7, #fff3d8); border: 2.5px solid #fff; border-radius: 18px; box-shadow: 0 5px 0 rgba(150,110,40,0.14), 0 8px 18px rgba(60,40,20,0.12); }
.shop-card.trying { border-color: #f5a91b; box-shadow: 0 0 0 3px rgba(245,169,27,0.35), 0 5px 0 rgba(150,110,40,0.14); }
.shop-pic { background: radial-gradient(circle at 50% 40%, #fff 0%, #fff0cf 75%); border-radius: 14px; }
.shop-name { color: #3a2c12; }
.shop-card .pill { border-radius: 999px; padding: 8px 10px; font-size: 14px; }
.shop-card .pill.equipped { outline: 0; }
.shop-card.wip .shop-pic img { filter: grayscale(1) opacity(0.35); }
.shop-detail { flex: none; width: clamp(200px, 19vw, 260px); display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 16px 14px; border-radius: 22px;
  background: linear-gradient(rgba(255,253,247,0.95), rgba(255,248,232,0.92)); border: 2.5px solid #fff; box-shadow: 0 10px 30px rgba(20,12,6,0.4); color: #3a2c12; }
.shop-detail[hidden] { display: none; }
.sd-pic { width: 100%; aspect-ratio: 1; display: flex; align-items: center; justify-content: center; border-radius: 18px;
  background: radial-gradient(circle at 50% 35%, #fff 0%, #fff0cf 70%); border: 2px solid #fff; box-shadow: inset 0 -10px 20px rgba(150,110,40,0.12); }
.sd-pic img { max-width: 78%; max-height: 82%; object-fit: contain; filter: drop-shadow(0 8px 10px rgba(60,40,20,0.3)); }
.sd-name { font-weight: 900; font-size: 18px; color: #3a2c12; text-align: center; }
.sd-state { display: inline-flex; align-items: center; gap: 5px; padding: 3px 12px; border-radius: 999px; background: rgba(245,169,27,0.16); color: #7a4a00; font-weight: 800; font-size: 13px; }
.sd-hint { color: #93805f; font-size: 13px; font-weight: 700; text-align: center; line-height: 1.4; }
.shop-detail .pill { width: 100%; border-radius: 999px; }
.shop-hint { color: #93805f; text-shadow: none; }
@media (max-width: 960px) { .shop-detail { display: none; } }
@media (max-width: 720px) {
  #shop .arc-header { flex-wrap: wrap; justify-content: center; }
  #shop .arc-title { order: -1; flex: 1 0 100%; font-size: 20px; padding: 8px 20px 10px; }
  #shop .shop-preview { background: rgba(50,32,14,0.7); }
  .shop-touch-controls button { background: linear-gradient(#a8743f, #7a4f26); border-color: #d0a06a; box-shadow: 0 3px 0 #5a3618; }
  .shop-fit-bomb { background: linear-gradient(#ffe08a, #f5a91b) !important; color: #5a3800; }
}

/* ---- 任務／成就面板 (image-19): 左欄導覽 + 天空色進度橫幅 + 橫列任務 ---- */
.panel-box { width: min(96vw, 1180px); max-height: 90%; flex-direction: row; gap: 14px; padding: 14px; overflow: hidden; }
.panel-nav { flex: none; width: 230px; display: flex; flex-direction: column; gap: 8px; padding: 8px 0 0; }
.panel-content { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.pnav-tab { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-radius: 18px 0 0 18px; border: 2px solid #fff; border-right: 0; margin-right: -14px;
  background: rgba(255,255,255,0.55); color: #6b5327; font: inherit; text-align: left; cursor: pointer; box-shadow: 0 4px 0 rgba(150,110,40,0.10); }
.pnav-tab:hover { background: rgba(255,255,255,0.85); }
.pnav-tab.on { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; box-shadow: 0 5px 0 #c9871a; }
.pnav-ic { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: rgba(255,255,255,0.7); color: #b8790f; }
.pnav-tab.on .pnav-ic { background: rgba(255,255,255,0.45); color: #7a4a00; }
.pnav-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; line-height: 1.15; }
.pnav-tx b { font-size: 16px; font-weight: 900; }
.pnav-tx i { font-style: normal; font-size: 11px; font-weight: 700; opacity: 0.8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pnav-art { margin-top: auto; display: flex; flex-direction: column; align-items: center; gap: 0; padding-bottom: 4px; }
.pnav-art img { width: 150px; height: 150px; object-fit: contain; filter: drop-shadow(0 10px 14px rgba(60,40,20,0.35)); margin-bottom: -18px; z-index: 1; }
.pnav-sign { white-space: pre-line; text-align: center; padding: 12px 18px 10px; border-radius: 14px; background: linear-gradient(#a8743f, #7a4f26); border: 2.5px solid #d0a06a;
  color: #ffe9a8; font-weight: 900; font-size: 15px; line-height: 1.3; transform: rotate(-3deg); box-shadow: 0 5px 0 #5a3618, 0 10px 22px rgba(60,40,20,0.3); }
.panel-head { gap: 10px; }
.panel-title { flex: 1; display: inline-flex; align-items: center; align-self: flex-start; padding: 6px 22px 8px; border-radius: 14px; font-size: 22px; letter-spacing: 3px;
  background: linear-gradient(#a8743f, #7a4f26); border: 2.5px solid #d0a06a; color: #ffe9a8; text-shadow: 0 2px 0 rgba(60,35,10,0.7); box-shadow: 0 5px 0 #5a3618, 0 10px 22px rgba(60,40,20,0.3); flex: 0 1 auto; margin-right: auto; }
.panel-head .coinbal { border-radius: 999px; }
#panelCloseBtn { border-radius: 14px; }
.panel-body { gap: 8px; padding-right: 6px; }
.qhead { padding: 14px 18px; border-radius: 18px; border: 2.5px solid #fff; color: #fff;
  background: linear-gradient(180deg, #8fd0f4 0%, #5aa9e6 100%); box-shadow: 0 6px 18px rgba(60,40,20,0.18), inset 0 2px 0 rgba(255,255,255,0.45); }
.qhead-l b { color: #fff; font-size: 17px; text-shadow: 0 1px 0 rgba(20,60,100,0.35); }
.qhead .qbar { height: 12px; background: rgba(255,255,255,0.35); border: 1.5px solid rgba(255,255,255,0.6); }
.qhead .qbar i { background: linear-gradient(#ffe08a, #f5a91b); }
.qhead .qreset { color: #fff; opacity: 0.95; }
.qhead .qchest { background: rgba(255,255,255,0.18); border: 2px solid rgba(255,255,255,0.55); color: #fff; border-radius: 16px; padding: 6px 14px; }
.qhead .qchest img { width: 64px; height: 64px; }
.qhead .qchest small { color: #fff3c4; }
.qhead .qchest.ready { background: rgba(255,224,138,0.35); border-color: #ffedb0; }
.qsec { display: flex; align-items: center; gap: 10px; margin-top: 6px; padding: 8px 14px; border-radius: 14px; background: rgba(255,232,150,0.38); border: 2px solid #fff; color: #3a2c12; }
.qsec-ic { flex: none; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 8px; background: linear-gradient(#ffe08a, #f5a91b); color: #7a4a00; }
.qsec b { font-size: 16px; }
.qsec-sub { flex: 1; min-width: 0; font-size: 12.5px; color: #6b5327; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qsec-r { flex: none; display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: #93805f; font-weight: 800; }
.qweek-head { margin-top: 10px; }
.qweek-head b { font-size: 16px; } .qweek-head span.qsec-sub, .qweek-head span.qsec-r { color: #6b5327; }
.prog-card .preward { gap: 6px; }
.rw-coin, .rw-xp { display: inline-flex; align-items: center; gap: 4px; padding: 2px 10px; border-radius: 999px; font-size: 12.5px; font-weight: 900; white-space: nowrap; }
.rw-coin { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; }
.rw-coin svg { color: #b8500f; }
.rw-xp { background: linear-gradient(#ffc27a, #f28a1e); color: #5a2a00; }
.rw-xp b { font-size: 9.5px; letter-spacing: 0.06em; padding: 0 4px; border-radius: 6px; background: rgba(255,255,255,0.6); color: #b8500f; }
.prog-card .pside .pill { min-width: 108px; border-radius: 999px; padding: 8px 14px; font-size: 14px; }
.prog-card .pside .pill.pgo { background: linear-gradient(#5cc3f2, #2e8fd6); border-color: #d9f1ff; color: #fff; text-shadow: 0 1px 0 rgba(0,60,120,0.3); box-shadow: 0 4px 0 #1f6fb0; }
.prog-card .pside .pill.ghost:disabled { background: linear-gradient(#e6ded0, #cfc4b2); border-color: #fff; color: #6b5327; opacity: 1; }
/* 橫列 (桌機): 圖示 | 名稱+說明 | 進度條 | 計數 | 獎勵 | 動作 —— DOM 不動, 用 display:contents 攤平成一個 grid */
@media (min-width: 821px) {
  .prog-card { display: grid; grid-template-columns: 46px minmax(140px, 1.1fr) minmax(120px, 1.4fr) auto auto auto; grid-auto-rows: auto; column-gap: 14px; row-gap: 2px; align-items: center; padding: 10px 14px; }
  .prog-card .pmain, .prog-card .pside { display: contents; }
  .prog-card .picon { grid-column: 1; grid-row: 1 / 3; width: 46px; height: 46px; border-radius: 12px; }
  .prog-card .pname { grid-column: 2; grid-row: 1; align-self: end; }
  .prog-card .pdesc { grid-column: 2; grid-row: 2; align-self: start; margin: 0; }
  .prog-card .pbar { grid-column: 3; grid-row: 1 / 3; height: 12px; margin: 0; border: 1.5px solid rgba(150,115,55,0.2); }
  .prog-card .pcount { grid-column: 4; grid-row: 1 / 3; margin: 0; font-size: 13px; color: #3a2c12; min-width: 3.2em; }
  .prog-card .preward { grid-column: 5; grid-row: 1 / 3; }
  .prog-card .pside .pill { grid-column: 6; grid-row: 1 / 3; }
  .prog-card .ptiers { margin-left: 6px; }
  .prog-card .pshow, .prog-card .preroll, .prog-card .punlock { grid-column: 2 / 7; grid-row: 3; justify-self: start; margin-top: 4px; }
  .prog-card.secret .pname { grid-row: 1 / 3; align-self: center; }
  .prog-card.secret .pdesc { display: none; }
}
@media (max-width: 820px) {
  .panel-box { flex-direction: column; gap: 8px; padding: 10px; }
  .panel-nav { width: auto; flex-direction: row; gap: 6px; padding: 0; }
  .pnav-tab { flex: 1; padding: 8px 10px; border-radius: 14px; border-right: 2px solid #fff; margin: 0; gap: 8px; }
  .pnav-ic { width: 30px; height: 30px; } .pnav-tx b { font-size: 13px; } .pnav-tx i { display: none; }
  .pnav-art { display: none; }
  .panel-title { font-size: 18px; letter-spacing: 2px; padding: 5px 14px 7px; }
  .qhead .qchest img { width: 48px; height: 48px; }
}

/* ---- 大廳公告板 / 聊天泡泡 打磨 ---- */
.ch-panel .board-item { background: #fff; border: 1.5px solid rgba(150,115,55,0.16); border-left: 5px solid #f5a91b; border-radius: 12px; padding: 8px 10px 8px 11px; }
.ch-panel .board-item .bwho { align-items: center; }
.ch-panel .board-item .bwho::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: #f5a91b; flex: none; }
.ch-panel .board-item .btime { color: #a08a63; }
.ch-panel .board-item .btext { font-size: 13.5px; }
.ch-panel .board-heart { color: #c9b89a; } .ch-panel .board-heart.on { color: #f2557a; }
.ch-panel .chat-row .pill, .ch-panel .board-row .pill { background: linear-gradient(#ffe08a, #f5a91b); border-color: #ffedb0; color: #5a3800; text-shadow: none; box-shadow: 0 3px 0 #c9871a; border-radius: 999px; }
.ch-panel .chat-row input, .ch-panel .board-row input { background: #fff; border: 2px solid rgba(150,115,55,0.18); }
.ch-panel .chat-row input:focus, .ch-panel .board-row input:focus { border-color: #f5a91b; }
.ch-social-actions .social-art-btn { min-height: 58px; overflow: hidden; justify-content: flex-start; padding: 4px 10px 4px 5px; }
.ch-social-actions .social-art-btn img { width: 46px; height: 46px; flex: none; object-fit: contain; filter: drop-shadow(0 3px 4px rgba(80,45,12,.18)); }
.ch-social-actions #newsOpenBtn { display: none; }
.ch-social-actions #chatOpenBtn { grid-column: 1 / -1; min-height: 38px; }
.board-head { flex: none; display: flex; align-items: center; gap: 9px; min-height: 54px; padding: 1px 5px 7px;
  border-bottom: 1.5px solid rgba(150,115,55,.15); }
.board-head img { width: 56px; height: 56px; flex: none; object-fit: contain; filter: drop-shadow(0 4px 6px rgba(80,45,12,.16)); }
.board-head b { color: #5a3800; font-size: 17px; font-weight: 950; }
.ch-board .board-tabs { padding: 2px; border-radius: 999px; background: rgba(137,92,29,.08); }
.ch-board .board-list { padding: 2px 2px 0; scrollbar-width: thin; scrollbar-color: #e0b663 transparent; }
.ch-board .board-item { padding: 9px 10px; margin-bottom: 7px; border: 1px solid rgba(150,115,55,.14); border-left: 4px solid #f5a91b;
  box-shadow: 0 3px 9px rgba(90,55,18,.07); }
.ch-board .board-item .btext { margin-top: 3px; line-height: 1.48; }
.ch-board .board-item-ann { position: relative; padding-left: 40px; background: linear-gradient(120deg, #fffdf7, #fff7df); }
.ch-board .board-item-ann::before { content: ''; position: absolute; left: 9px; top: 10px; width: 22px; height: 22px; border-radius: 8px;
  background: #fff0b8 url("assets/ui/notice-board-v2.webp") center / 26px no-repeat; box-shadow: 0 2px 5px rgba(90,55,18,.12); }
.ch-board .board-item-ann.is-latest { border-left-color: #e89513; background: linear-gradient(120deg, #fffdf7, #fff1c7); }
.ch-board .board-row { padding-top: 4px; border-top: 1px solid rgba(150,115,55,.12); }
.ch-overlay .board-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.ch-overlay .board-empty::before { content: ''; width: min(180px, 46vw); aspect-ratio: 0.97; background: url("assets/ui/notice-board-v2.webp") center / contain no-repeat; filter: drop-shadow(0 8px 12px rgba(80,45,12,.16)); }
#lobbyList .chat-log .cwho { color: #b8790f; }
#lobbyList .chat-log .cbubble { background: #fff; color: #3a2c12; border: 1.5px solid rgba(150,115,55,0.18); box-shadow: 0 2px 0 rgba(150,110,40,0.08); }
#lobbyList .chat-log .cmsg.me .cbubble { background: linear-gradient(#ffe79a, #ffd667); color: #6b4a00; border-color: #ffedb0; }
#lobbyList .chat-log .cmsg.sys .csys { color: #93805f; }
/* 成就分類分頁上的數字: 以前只有 .dock-btn 的紅點有底色, 在面板裡就是三個裸數字浮在藥丸上 */
.panel-tabs .ptab .qdot { top: -8px; right: -8px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: #e74c3c; border: 2px solid #fff; color: #fff; font-size: 11px; font-weight: 900; display: flex; align-items: center; justify-content: center; }
/* 房間列表 (左欄) 點下去閃一下 —— 名單本來就在畫面內時, 沒有這一下就像沒反應 */
@keyframes roomsFlash { 0% { box-shadow: 0 0 0 0 rgba(245,169,27,0.0), 0 10px 30px rgba(60,40,20,0.24); } 30% { box-shadow: 0 0 0 6px rgba(245,169,27,0.55), 0 10px 30px rgba(60,40,20,0.24); } 100% { box-shadow: 0 0 0 0 rgba(245,169,27,0), 0 10px 30px rgba(60,40,20,0.24); } }
.ch-rooms.flash { animation: roomsFlash 0.9s ease-out; }

/* IG 追蹤條: 跟 dock 同一個置中 (以前在 .ch-main 裡, 被左欄推偏) */
.ch-foot { flex: none; display: flex; justify-content: center; padding: 2px 12px 0; position: relative; z-index: 1; }
.ch-foot .ig-cta { width: auto; padding: 6px 12px; border-radius: 999px; background: rgba(50,32,14,0.55); border: 1px solid rgba(255,230,160,0.3); }
.ch-foot .ig-cta .ig-txt b { color: #fff5dc; } .ch-foot .ig-cta .ig-txt i { color: rgba(255,241,207,0.72); } .ch-foot .ig-cta .ig-go { color: #ffd45e; }
@media (max-width: 820px) { .ch-foot { display: none; } }
/* 公告 / 大廳聊天 浮層 (UI v2): 卡片是從右欄搬進來的同一張, 這裡只給它尺寸與關閉鍵 */
.ch-overlay { background: rgba(40,26,12,0.55); z-index: 34; }
.ch-overlay .ch-ovbox { position: relative; width: min(94vw, 560px); max-height: 84vh; padding: 0; background: none; border: 0; box-shadow: none; }
.ch-overlay .ch-ovslot { display: flex; flex-direction: column; min-height: 0; }
.ch-overlay .ch-ovslot .ch-panel { flex: 1; height: min(72vh, 620px); max-height: none; }
.ch-ovclose { position: absolute; top: -14px; right: -14px; z-index: 2; width: 38px; height: 38px; border-radius: 50%; border: 2.5px solid #fff;
  background: linear-gradient(#a8743f, #7a4f26); color: #fff5dc; cursor: pointer; display: grid; place-items: center; box-shadow: 0 4px 0 #5a3618, 0 8px 18px rgba(60,40,20,0.35); }
.ch-ovclose:active { transform: translateY(2px); box-shadow: 0 2px 0 #5a3618; }
@media (max-width: 820px) { .ch-social-actions { display: grid; } }

/* Compact desktops: audio, SFX and fullscreen already live in Settings. Keeping
   their duplicates here was squeezing the account and currency into one strip. */
@media (max-width: 1200px) {
  .ch-top { flex-wrap: wrap; }
  .ch-top-right { min-width: 0; }
  .ch-top-right #helpLink,
  .ch-top-right #fsBtn2,
  .ch-top-right #muteBtn2,
  .ch-top-right #sfxBtn2 { display: none; }
  #lobbyList .acctchip { min-width: 0; max-width: min(52vw, 300px); }
  #lobbyList .acctchip .acct-name,
  #lobbyList .acctchip .acct-rank { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #lobbyList .acctchip .acct-rank { max-width: 92px; }
}
@media (max-width: 820px) {
  .ch-top-right { flex: 1 1 100%; display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; }
  #lobbyList .acctchip { max-width: none; }
  #lobbyList .acctchip .acct-rank { display: none; }
  .ch-side .ch-board { display: flex; height: min(390px, 52vh); min-height: 310px; }
}

/* ---- 戰績: 載入中 (以前是空白 + 卡住) ---- */
.ml-loading { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 40px 12px; color: #fff5dc; font-weight: 800; font-size: 14px; text-shadow: 0 1px 4px rgba(60,35,10,0.6); }
.ml-spin { width: 26px; height: 26px; border-radius: 50%; border: 4px solid rgba(255,245,220,0.35); border-top-color: #ffd45e; animation: mlSpin 0.8s linear infinite; }
@keyframes mlSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ml-spin { animation: none; } }
/* ---- 返回 / 離開 一律靠右上 (站主: 「不要一下左邊一下右邊」) ---- */
#matchLog .ls-head #mlBack { margin-left: auto; }
#shop .arc-header #shopBackBtn { order: 9; }
#lab .arc-header #labBackBtn { order: 9; margin-left: auto; }
#lobbyRoom .arc-header #leaveBtn { order: 9; }

/* =========================================================================
   2026-09-17 手機修正 (站主實機: 「寬度不一致」「橫向很多遮蓋」)
   1. 直向: .ch-side 被桌機的 max-width:360px 綁住, 比舞台／房間卡窄 6px。
   2. 橫向 (844x390 / 667x375): 寬度 > 820 被當桌機 —— 導覽列、右欄、dock、IG 條全擠進
      100 多 px 的可用高度。規則: 高度 <= 520px 一律走手機版面, 頂列一排, dock 縮小。
   3. 工作室／戰績標題列在窄寬或矮高會斷成三行 —— 改 grid: 標題+返回一排, 分頁一排。
   全部追加在檔尾後蓋, 不動前面 (另一個 session 正在改公告板那一段)。
   ========================================================================= */
@media (max-width: 820px), (max-height: 520px) {
  .ch-side { max-width: none; min-width: 0; width: 100%; flex: none; }
}
@media (max-height: 520px) {
  /* ---- 手機版面 ---- */
  .ch-rail, .ch-foot, .ch-tagline, .ch-ticker { display: none; }
  .ch-stage { flex-direction: column; overflow-y: auto; -webkit-overflow-scrolling: touch; max-width: none;
    gap: 8px; padding: 0 10px calc(64px + env(safe-area-inset-bottom)); }
  .ch-main { flex: none; overflow: visible; overscroll-behavior: auto; scrollbar-gutter: auto; margin: 0; padding: 0; gap: 8px; }
  .ch-rooms { flex: none; min-height: 140px; height: auto; }
  .ch-side .ch-panel { flex: none; height: auto; min-height: 0; max-height: 60vh; }
  .ch-side .ch-board { height: min(260px, 60vh); min-height: 0; }
  .ch-dock { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; width: auto; max-width: none; margin: 0; border-radius: 0; border: 0;
    flex-wrap: nowrap; gap: 4px; padding: 3px 8px calc(3px + env(safe-area-inset-bottom));
    background: linear-gradient(rgba(50,32,14,0.82), rgba(40,26,12,0.94)); border-top: 1.5px solid rgba(255,230,160,0.28); box-shadow: 0 -6px 18px rgba(20,12,6,0.35); }
  .dock-btn { flex: 1; width: auto; min-width: 0; flex-direction: column; justify-content: center; gap: 2px; padding: 3px 2px; border: 0; border-radius: 10px; background: none; box-shadow: none; color: #fff1cf; }
  .dock-btn:hover { transform: none; box-shadow: none; }
  .dock-btn .dicon { width: 24px; height: 24px; border-radius: 8px; }
  .dock-btn .dicon svg { width: 16px; height: 16px; }
  .dock-btn .dlabel { font-size: 10px; white-space: nowrap; }
  .dock-btn .qdot { top: 0; right: calc(50% - 22px); min-width: 15px; height: 15px; font-size: 9.5px; }
  body:has(#lobby.show) #bpFooter { display: none; }
  /* ---- 頂列一排: logo、帳號、金幣、設定、登出 ---- */
  .ch-top { flex-wrap: nowrap; padding: 5px 10px; gap: 8px; }
  .ch-logo { height: 34px; max-width: 26vw; }
  .ch-top-right { flex: 1 1 auto; display: flex; flex-wrap: nowrap; justify-content: flex-end; gap: 6px; min-width: 0; }
  .ch-top-right #helpLink, .ch-top-right #fsBtn2, .ch-top-right #muteBtn2, .ch-top-right #sfxBtn2 { display: none; }
  #lobbyList .acctchip { padding: 2px 10px 2px 2px; gap: 6px; max-width: none; min-width: 0; }
  #lobbyList .acctchip .acct-avatar { width: 28px; height: 28px; }
  #lobbyList .acctchip .acct-row2 > svg, #lobbyList .acctchip .acct-rating, #lobbyList .acctchip .acct-rank, #lobbyList .acctchip .acct-bucket { display: none; }
  #lobbyList .acctchip .acct-name { max-width: 140px; font-size: 13px; }
  .coinpill { height: 32px; font-size: 13px; padding: 0 10px 0 8px; }
  #lobbyList .iconbtn { height: 32px; min-width: 32px; padding: 0 9px; font-size: 12px; }
  /* ---- 舞台縮成一排能看完的高度 ---- */
  .ch-hero { padding: clamp(78px, 24vh, 120px) 0 4px; gap: 6px; }
  .ch-cast { display: block; height: clamp(78px, 24vh, 120px); }
  .ch-mascot-l { left: 6%; height: 62%; }
  .ch-mascot-r { right: 6%; height: 58%; }
  #playWindow.ch-window { font-size: 12px; padding: 4px 10px; margin: 0 auto 2px; }
  .ch-count { min-height: 0; }
  .ch-cta { width: min(600px, 100%); gap: 6px; }
  #quickBtn.ch-play { min-height: 46px; font-size: 18px; letter-spacing: 1px; }
  .ch-quick-sub { font-size: 11px; margin-top: 1px; }
  .ch-secondary-row { grid-template-columns: 1fr 1.4fr 1fr; gap: 6px; }
  .ch-sec { min-height: 38px; font-size: 13.5px; padding: 6px 10px; }
  .ch-sec-join #codeInput { font-size: 15px; }
  .ch-tutor.big { min-height: 36px; }
  .ch-friends .fc-open { min-height: 36px; }
  /* ---- 任務／成就面板: 左欄變一列 ---- */
  .panel-box { flex-direction: column; gap: 6px; padding: 8px; max-height: 96%; width: min(96vw, 1180px); }
  .panel-nav { width: auto; flex-direction: row; gap: 6px; padding: 0; }
  .pnav-tab { flex: 1; padding: 5px 10px; border-radius: 12px; border-right: 2px solid #fff; margin: 0; gap: 8px; }
  .pnav-ic { width: 26px; height: 26px; } .pnav-tx b { font-size: 13px; } .pnav-tx i { display: none; }
  .pnav-art { display: none; }
  .panel-title { font-size: 17px; letter-spacing: 2px; padding: 4px 12px 6px; }
  .qhead { padding: 8px 12px; } .qhead .qchest img { width: 40px; height: 40px; }
  .prog-card { padding: 6px 10px; }
}
/* 工作室／戰績 標題列: 標題＋返回一排、分頁一排, 不再斷成三行 */
@media (max-width: 900px), (max-height: 520px) {
  .level-studio .ls-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; row-gap: 8px; column-gap: 8px; padding: 8px 12px; }
  .level-studio .ls-title { grid-column: 1; grid-row: 1; min-width: 0; }
  .level-studio .ls-title h2 { font-size: 18px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .level-studio .ls-title p { display: none; }
  .level-studio .ls-tabs { grid-column: 1 / -1; grid-row: 2; width: 100%; margin: 0; }
  .level-studio .ls-saved { grid-column: 1; grid-row: 3; }
  .level-studio #lsBack, #matchLog #mlBack { grid-column: 2; grid-row: 1; margin-left: 0; justify-self: end; }
  .level-studio .ls-tab { padding: 6px 8px; font-size: 13px; }
}

/* ===== 小空間布置 (2026-09-28, js/space-editor.js) =====
   選物抽屜緊接在房間下方; 選中 = 蜂蜜黃, 次要鍵 = 奶油 (園區 UI 標準 §2.1) */
.space-head .space-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#spaceEditBtn { flex: none; min-height: 44px; padding: 8px 18px; }
#spaceEditBtn[hidden], .space-drawer[hidden], .space-toast[hidden] { display: none !important; }
#spaceCv { touch-action: manipulation; }
.space-hint { margin: 8px 0 0; font-size: 14px; font-weight: 800; }
/* 布置模式: 房間縮到 52vh, 桌機 768 高也看得到抽屜第一列 (codex 審查第 1 條) */
.space-box.editing #spaceCv { max-height: 52vh; width: auto; max-width: 100%; margin: 0 auto; }
/* 小空間開著時收起右下角的 powered-by 浮條, 它會蓋住彈窗底緣 (手機) */
body:has(#spaceView.show) #bpFooter { display: none; }
.space-toast { display: flex; align-items: center; justify-content: center; gap: 10px; margin: 8px auto 0; padding: 6px 8px 6px 14px; width: fit-content; max-width: 100%;
  border-radius: 999px; background: rgba(50,32,14,.78); color: #fff5dc; font-size: 13px; font-weight: 800; animation: uiEnter 220ms cubic-bezier(.2,.75,.2,1) both; }
.space-toast .spd-undo { min-height: 36px; padding: 5px 14px; background: rgba(255,252,244,.95); color: #6b5327; border: 2px solid rgba(150,115,55,.22); box-shadow: 0 3px 0 rgba(150,110,40,.14); text-shadow: none; }
.space-drawer { margin-top: 10px; padding: 12px; border-radius: 18px; background: linear-gradient(rgba(255,253,247,.95), rgba(255,248,232,.92));
  border: 2.5px solid #fff; box-shadow: 0 6px 18px rgba(60,40,20,.16), inset 0 2px 0 rgba(255,255,255,.6); }
.spd-spots { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.spd-spot { min-height: 44px; padding: 6px 12px; border-radius: 11px; font: inherit; font-size: 13px; font-weight: 800; cursor: pointer;
  background: rgba(255,252,244,.95); color: #6b5327; border: 2px solid rgba(150,115,55,.22); box-shadow: 0 3px 0 rgba(150,110,40,.14); }
.spd-spot.sel { background: linear-gradient(#ffe08a, #f5a91b); color: #5a3800; border-color: #ffedb0; box-shadow: 0 3px 0 #c9871a; }
.spd-title { font-size: 15px; font-weight: 900; color: #3a2c12; margin: 0 2px 8px; }
.spd-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; }
.spd-card { display: flex; flex-direction: column; align-items: center; gap: 3px; min-height: 44px; padding: 8px 6px; border-radius: 14px; cursor: pointer; font: inherit;
  background: #fffdf7; border: 2px solid rgba(150,115,55,.18); color: #6b5327; box-shadow: 0 3px 0 rgba(150,110,40,.12); transition: transform 160ms, box-shadow 160ms; }
.spd-card:active { transform: translateY(2px); box-shadow: 0 1px 0 rgba(150,110,40,.12); }
.spd-card.here { border-color: #f5a91b; box-shadow: 0 0 0 3px rgba(245,169,27,.35), 0 3px 0 #c9871a; }
.spd-pic { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; color: #93805f; }
.spd-pic img { max-width: 100%; max-height: 100%; object-fit: contain; }
.spd-name { font-size: 13px; font-weight: 800; color: #3a2c12; text-align: center; line-height: 1.2; }
.spd-state { font-size: 11px; font-weight: 700; color: #93805f; min-height: 13px; text-align: center; }
.spd-card.here .spd-state { color: #b8790f; }
.spd-empty { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px; padding: 10px; color: #6b5327; font-weight: 800; font-size: 14px; }
.spd-empty .spd-shop { min-height: 44px; background: rgba(255,252,244,.95); color: #6b5327; border: 2px solid rgba(150,115,55,.22); box-shadow: 0 3px 0 rgba(150,110,40,.14); text-shadow: none; }
.spd-spot:focus-visible, .spd-card:focus-visible, .spd-undo:focus-visible, .spd-shop:focus-visible, #spaceEditBtn:focus-visible { outline: 3px solid rgba(46,143,214,.78); outline-offset: 2px; }
.shop-fit { font-size: 11px; font-weight: 700; color: #93805f; margin-top: -2px; }
@media (prefers-reduced-motion: reduce) { .space-toast { animation: none; } .spd-card { transition: none; } }

/* ===== 房間列表: 一排 + 翻頁 (2026-09-28, js/panels.js renderRoomGrid) =====
   站主: 盡量不要有上拉下滑的捲軸。房間區固定一排高, 多的翻頁; 沒房間整塊收起。 */
.ch-rooms.is-empty { display: none; }                 /* 手機也收起 (桌機本來就有) */
#lobbyList .ch-rooms { flex: none; height: auto; min-height: 0; }
#lobbyList .ch-rooms-head { margin-bottom: 6px; gap: 6px; }
#lobbyList .ch-rooms-head > .room-count::before { display: none; }
#lobbyList .ch-rooms-head .room-count { margin-right: auto; font-size: 12px; font-weight: 800; color: #93805f; letter-spacing: 0; }
.room-pager { display: inline-flex; align-items: center; gap: 4px; }
.room-pager[hidden] { display: none; }
.room-pager .iconbtn { min-width: 40px; height: 40px; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.room-pager .iconbtn:disabled { opacity: .35; cursor: default; }
.room-pager .rp-num { min-width: 42px; text-align: center; font-size: 13px; font-weight: 900; color: #6b5327; font-variant-numeric: tabular-nums; }
#roomGrid { display: grid; grid-template-columns: repeat(var(--room-cols, 3), minmax(0, 1fr)); gap: 8px; overflow: hidden; }
#roomGrid .room-card { display: grid; grid-template-columns: 52px minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: 8px; row-gap: 4px;
  align-items: center; padding: 7px; min-height: 0; }
#roomGrid .room-card .thumb { grid-column: 1; grid-row: 1 / span 2; width: 52px; height: 52px; min-height: 0; align-self: center; }
#roomGrid .room-card .info { grid-column: 2 / span 2; grid-row: 1; }
#roomGrid .room-card .rjoin { grid-column: 2; grid-row: 2; padding: 3px 6px; font-size: 12px; }
#roomGrid .room-card .rwatch { grid-column: 3; grid-row: 2; padding: 3px 8px; }
#lobbyList #listError:empty { display: none; }   /* 空的錯誤列原本也佔 22px */
#roomGrid .room-card .sprout-tag { font-size: 10px; white-space: nowrap; }
#roomGrid .room-empty { padding: 10px; }
#roomGrid .room-empty::before { display: none; }
/* 有房間時吉祥物舞台讓出一點高度, 一排房卡才完整放得下 (桌機) */
@media (min-width: 821px) {
  .ch-main:has(.ch-rooms:not(.is-empty)) .ch-hero { padding-top: clamp(130px, 21vh, 205px); }
  .ch-main:has(.ch-rooms:not(.is-empty)) .ch-cast { height: clamp(130px, 21vh, 205px); }
}
@media (min-width: 821px) and (max-height: 900px) {
  .ch-main:has(.ch-rooms:not(.is-empty)) .ch-hero { padding-top: clamp(78px, 13vh, 130px); }
  .ch-main:has(.ch-rooms:not(.is-empty)) .ch-cast { height: clamp(78px, 13vh, 130px); }
}
@media (min-width: 821px) {
  .ch-main:has(.ch-rooms:not(.is-empty)) #roomStatus { display: none; }   /* 數字已在房間區標題旁 */
}
@media (min-width: 821px) and (max-height: 760px) {
  .ch-main:has(.ch-rooms:not(.is-empty)) .ch-hero { padding-top: clamp(64px, 10vh, 100px); }
  .ch-main:has(.ch-rooms:not(.is-empty)) .ch-cast { height: clamp(64px, 10vh, 100px); }
}
@media (max-width: 820px) {
  .room-pager .iconbtn { min-width: 44px; height: 44px; }
  #roomGrid .room-card { grid-template-columns: 44px minmax(0, 1fr) auto; padding: 6px; column-gap: 6px; }
  #roomGrid .room-card .thumb { width: 44px; height: 44px; }
  /* 手機的房間數已在舞台上那一行 (#roomStatus 手機沒收), 標題旁不重複, 標題才不會斷成兩行 */
  #lobbyList .ch-rooms-head .room-count { display: none; }
  #lobbyList .ch-rooms-head > span:first-child { white-space: nowrap; margin-right: auto; }
  #roomGrid .room-card .rjoin { white-space: nowrap; font-size: 11px; }
  /* 手機卡窄: 觀戰只留眼睛圖示 (字級 0, 螢幕閱讀器仍讀得到「觀戰」) */
  #roomGrid .room-card .rwatch { font-size: 0; gap: 0; padding: 3px 7px; }
}

/* ===== 手機大廳一屏 (2026-09-28, 站主: 手機大廳也重新排版, 盡量一屏看完) =====
   原況 390x844: 頂列 166 + 舞台 230 + 同樂時段兩行 48 + 按鈕區 302 + 好友卡 198 + 公告板 418,
   可視只有 605px。收法: 頂列一排、右欄收起 (好友走 dock, 公告/聊天改成一列按需浮層)、
   舞台與按鈕依高度縮。桌機不受影響 (.ch-mstrip 只在手機出現)。 */
.ch-mstrip { display: none; }
@media (max-width: 820px) {
  #lobbyList .ch-top { padding: 6px 10px; gap: 8px; flex-wrap: nowrap; align-items: center; }
  #lobbyList .ch-logo { height: 34px; flex: none; }
  #lobbyList .ch-top .ch-ticker { display: none; }            /* 公告改在下面的精簡列 */
  #lobbyList .ch-top-right { min-width: 0; }
  #lobbyList .acctchip { min-width: 0; flex: 0 1 auto; }
  #lobbyList .acctchip .acct-name { max-width: 70px; }
  #lobbyList .ch-side { display: none; }                      /* 好友卡 + 攤開的公告板 */
  #lobbyList .ch-main { gap: 8px; }
  #lobbyList .ch-hero { padding: clamp(92px, 17vh, 150px) 0 2px; gap: 6px; }
  #lobbyList .ch-cast { height: clamp(92px, 17vh, 150px); }
  #lobbyList .ch-tagline { font-size: 12px; width: 96px; }
  #playWindow.ch-window { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; box-sizing: border-box; font-size: 12px; padding: 5px 12px; }
  #lobbyList .ch-cta { gap: 8px; }
  #lobbyList #tutorBtn.ch-tutor { min-height: 44px; padding-block: 6px; font-size: 15px; }
  #lobbyList #quickBtn.ch-play { min-height: 56px; }
  #lobbyList .ch-secondary-row { grid-template-columns: 1fr 1fr; gap: 8px; }
  #lobbyList .ch-sec-create, #lobbyList .ch-sec-studio { order: 1; min-height: 44px; }   /* 兩顆並排一列 */
  #lobbyList .ch-join-row.ch-sec { order: 2; grid-column: 1 / -1; min-height: 44px; padding-block: 3px; }
  #lobbyList .ch-mstrip { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
  /* 有房卡時「n 個房間開放中」是重複的 (快速開始副標與房卡都看得到) */
  .ch-main:has(.ch-rooms:not(.is-empty)) #roomStatus { display: none; }
  #lobbyList .ch-rooms { padding: 8px 10px; }
  #lobbyList .ch-rooms-head { margin-bottom: 4px; }
  .ch-mnews, .ch-mchat { min-height: 44px; display: flex; align-items: center; gap: 8px; border-radius: 16px; cursor: pointer; font: inherit;
    background: linear-gradient(rgba(255,253,247,.95), rgba(255,248,232,.92)); border: 2px solid #fff; color: #6b5327; box-shadow: 0 4px 14px rgba(60,40,20,.16); }
  .ch-mnews { min-width: 0; padding: 3px 10px 3px 4px; text-align: left; }
  .ch-mnews img { flex: none; width: 36px; height: 36px; object-fit: contain; }
  .ch-mnews .mn-text { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
  .ch-mnews .mn-text b { font-size: 11px; color: #b8790f; }
  .ch-mnews .mn-text span { font-size: 13px; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .ch-mnews .mn-text span:empty { display: none; }
  .ch-mnews > svg { flex: none; color: #b8790f; }
  .ch-mchat { padding: 0 14px; font-size: 14px; font-weight: 900; white-space: nowrap; }
  .ch-mchat > span { display: inline-flex; align-items: center; gap: 6px; }
  .ch-mnews:focus-visible, .ch-mchat:focus-visible { outline: 3px solid rgba(46,143,214,.78); outline-offset: 2px; }
}
/* 矮手機 (iPhone SE / 8 這一級): 再收一點 */
@media (max-width: 820px) and (max-height: 700px) {
  #lobbyList .ch-hero { padding-top: clamp(52px, 9vh, 80px); }
  #lobbyList .ch-cast { height: clamp(52px, 9vh, 80px); }
  #lobbyList .ch-tagline { display: none; }
  #lobbyList #quickBtn.ch-play { min-height: 50px; }
}
@media (max-width: 820px) and (max-height: 760px) {
  #lobbyList .ch-main, #lobbyList .ch-cta, #lobbyList .ch-secondary-row { gap: 6px; }
  #lobbyList .ch-hero { gap: 4px; }
  #lobbyList #quickBtn.ch-play { min-height: 50px; }
}
/* 手機沒有房間: 房間區收起後空出來的高度還給吉祥物 (場景是主角) */
@media (max-width: 820px) {
  #lobbyList .ch-main:has(.ch-rooms.is-empty) .ch-hero { padding-top: clamp(96px, 26vh, 240px); }
  #lobbyList .ch-main:has(.ch-rooms.is-empty) .ch-cast { height: clamp(96px, 26vh, 240px); }
}
@media (max-width: 820px) and (max-height: 700px) {
  #lobbyList .ch-main:has(.ch-rooms.is-empty) .ch-hero { padding-top: clamp(80px, 22vh, 150px); }
  #lobbyList .ch-main:has(.ch-rooms.is-empty) .ch-cast { height: clamp(80px, 22vh, 150px); }
  #lobbyList .ch-main:has(.ch-rooms.is-empty) .ch-tagline { display: block; }
}
