/* ── Spin the Bottle — Telegram Mini App theme ─────────────────────────── */
/* Honey-orange on warm espresso. The variable names (--pink, --violet …) are
   left over from the first purple/pink palette and kept so every rule that
   uses them re-themes at once; the values are what matter. */
:root{
  --bg:#1d130a; --bg2:#27190d; --card:#2b1d11; --card2:#38261a;
  --line:rgba(255,236,210,.10);
  --text:#fff3e2; --muted:#d0b899; --dim:#9c8567;
  --pink:#ff9422; --pink2:#ffb865; --violet:#ff6a1a; --cyan:#39d7ff;
  --gold:#ffc857; --green:#3ddc97; --red:#ff5f5f;
  --heart:#ff4d6d; --gem:#5ec6ff;
  --radius:18px; --radius-sm:12px;
  --safe-b:env(safe-area-inset-bottom,0px);
  --safe-t:env(safe-area-inset-top,0px);
  /* Height of the playing field (wood + the player tiles + the bottle). The
     chat below it takes whatever is left, so a small phone shrinks the field
     before it ever shrinks the chat input off the screen. */
  --field-h:clamp(280px,40dvh,430px);
}

/* ── background atmospheres ───────────────────────────────────────────────
   --atm-bg     the page behind everything (tabs, sheets…)
   --atm-field  what the table area is painted with; falls back to --atm-bg.
   Wood is the default and the only one with its own field art. */
body{background:var(--atm-bg)}
body[data-atm="wood"]{
  --atm-bg:
    radial-gradient(120% 60% at 50% 0%, rgba(255,170,80,.10), transparent 60%),
    #1d130a;
  --atm-field:url('/assets/wood.svg') center/cover no-repeat, #d98f42;
}
body[data-atm="velvet"]{
  --atm-bg:
    radial-gradient(1200px 600px at 50% -10%, #2a1b4d 0%, transparent 60%),
    radial-gradient(800px 500px at 100% 100%, #3a1030 0%, transparent 55%),
    #0d0a17;
}
body[data-atm="neon"]{
  --atm-bg:
    radial-gradient(90% 60% at 20% 0%, rgba(255,0,140,.30), transparent 60%),
    radial-gradient(90% 60% at 90% 20%, rgba(0,220,255,.24), transparent 60%),
    repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 26px),
    #07030f;
}
body[data-atm="beach"]{
  --atm-bg:
    linear-gradient(180deg, #123a5e 0%, #1f6f93 38%, #37a2a6 60%, #d9b477 61%, #c79c5c 100%);
}
body[data-atm="garden"]{
  --atm-bg:
    radial-gradient(90% 60% at 50% -10%, rgba(190,255,190,.14), transparent 60%),
    repeating-linear-gradient(122deg, rgba(0,0,0,.10) 0 3px, transparent 3px 14px),
    linear-gradient(180deg, #12341d, #0b2114);
}
body[data-atm="casino"]{
  --atm-bg:
    radial-gradient(90% 60% at 50% -10%, rgba(255,200,87,.16), transparent 60%),
    radial-gradient(70% 50% at 50% 110%, rgba(0,0,0,.6), transparent 60%),
    linear-gradient(180deg, #2a0d12, #16060a);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{height:100%}
body{
  margin:0;
  color:var(--text);
  font:15px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  overscroll-behavior:none;
}
button,input,textarea{font:inherit;color:inherit}
button{border:0;background:none;cursor:pointer}
input{border:0;outline:0}
h1,h2,h3{margin:0 0 8px;font-weight:800;letter-spacing:-.02em}
h2{font-size:20px}
.muted{color:var(--muted)}
.dim{color:var(--dim)}
.hidden{display:none !important}
.brand{background:linear-gradient(90deg,var(--pink),var(--violet));-webkit-background-clip:text;background-clip:text;color:transparent}
.pad{padding:14px 14px 28px}

/* ── boot ─────────────────────────────────────────────────────────────── */
.boot{position:fixed;inset:0;display:grid;place-content:center;justify-items:center;gap:14px;z-index:60;background:var(--bg)}
.boot-bottle{width:64px;animation:bootspin 1.6s cubic-bezier(.4,0,.2,1) infinite}
.boot p{color:var(--muted);margin:0}
@keyframes bootspin{0%{transform:rotate(0)}100%{transform:rotate(720deg)}}

/* ── onboarding ───────────────────────────────────────────────────────── */
.onboarding{position:fixed;inset:0;overflow:auto;display:grid;place-items:center;padding:20px;z-index:40}
.ob-card{width:100%;max-width:420px;background:linear-gradient(160deg,var(--card2),var(--card));
  border:1px solid var(--line);border-radius:24px;padding:22px 20px 18px;box-shadow:0 24px 60px rgba(0,0,0,.5)}
.ob-emoji{font-size:44px;text-align:center}
.ob-card h1{text-align:center;font-size:24px;margin-top:6px}
.ob-card>.muted{text-align:center;margin:0 0 18px}
.field{display:block;margin-bottom:16px}
.field>span{display:block;font-weight:600;margin-bottom:8px;font-size:14px}
.field input[type=text],.field input[type=number]{
  width:100%;background:rgba(0,0,0,.28);border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px 14px}
.age-row{display:flex;align-items:center;gap:10px}
.age-row input{text-align:center;font-size:22px;font-weight:800;flex:1}
.age-step{width:46px;height:46px;border-radius:14px;background:rgba(255,255,255,.07);font-size:22px;font-weight:700}
.age-step:active{background:rgba(255,255,255,.14)}
.hint{display:block;margin-top:6px;color:var(--red);min-height:16px}
.chips{display:flex;gap:8px;flex-wrap:wrap}
.chip{flex:1;min-width:96px;padding:12px 10px;border-radius:14px;background:rgba(255,255,255,.06);
  border:1px solid transparent;font-weight:600;transition:.15s}
.chip.on{background:linear-gradient(120deg,rgba(255,148,34,.3),rgba(255,106,26,.3));border-color:var(--pink)}
.fineprint{text-align:center;color:var(--dim);font-size:11.5px;margin:10px 0 0}

/* ── buttons ──────────────────────────────────────────────────────────── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:14px;
  padding:11px 16px;font-weight:700;transition:transform .12s,filter .2s}
.btn:active{transform:scale(.97)}
.btn[disabled]{opacity:.45;pointer-events:none}
.btn-primary{background:linear-gradient(180deg,#ffa63c,#f27d10);color:#fff;text-shadow:0 1px 2px rgba(120,50,0,.45);
  box-shadow:0 6px 18px rgba(255,148,34,.30),inset 0 1px 0 rgba(255,255,255,.35)}
.btn-ghost{background:rgba(255,255,255,.08);color:var(--text)}
.btn-gold{background:linear-gradient(120deg,#ffd76e,#e0a020);color:#2a1c00}
.btn-danger{background:rgba(255,95,95,.16);color:#ff9b9b}
.btn-lg{width:100%;padding:15px;font-size:16px}
.btn-sm{padding:7px 11px;font-size:13px;border-radius:11px}
.icon-btn{width:40px;height:40px;border-radius:12px;background:rgba(255,255,255,.07);display:grid;place-items:center;font-size:18px}
.icon-btn.send{background:linear-gradient(180deg,#ffa63c,#f27d10);color:#fff;border-radius:50%}

/* ── app frame ────────────────────────────────────────────────────────── */
/* --app-h (set by tg.js from Telegram's own viewportHeight / visualViewport)
   overrides 100dvh once JS has run — see tg.js#trackViewport for why. */
.app{display:flex;flex-direction:column;height:var(--app-h,100dvh);padding-top:var(--safe-t)}
.topbar{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:5px 10px;
  border-bottom:1px solid var(--line);background:rgba(29,19,10,.86);backdrop-filter:blur(12px);position:sticky;top:0;z-index:12}
.topbar-title{font-weight:700;opacity:.85;font-size:13px}
/* The round orange buttons with a thin white ring — wallet, daily spin and
   profile all share the look so the bar reads as one set of controls.
   Round 14: shrunk across the board — on a short viewport this whole bar
   plus the Music/Theme/All row below it was eating the space the chat
   log needed. */
.wallet{display:flex;gap:8px;padding:4px 10px;border-radius:999px;font-size:12px;color:#fff;
  background:linear-gradient(180deg,#ffa63c,#ee7a0c);border:1.5px solid rgba(255,255,255,.88);
  box-shadow:0 2px 6px rgba(0,0,0,.4);text-shadow:0 1px 2px rgba(120,50,0,.45)}
.w-item b{font-weight:800}
.topbar-right{display:flex;align-items:center;gap:6px}
.avatar-btn img{width:28px;height:28px;border-radius:50%;object-fit:cover;background:var(--card2);display:block;
  border:1.5px solid rgba(255,255,255,.88);box-shadow:0 2px 6px rgba(0,0,0,.4)}
/* Always-visible daily-spin entry point — glows gold once the free spin
   is ready, same idea as the tab bar's unread-DM dot. */
.wheel-btn{position:relative;width:28px;height:28px;border-radius:50%;
  background:linear-gradient(180deg,#ffa63c,#ee7a0c);border:1.5px solid rgba(255,255,255,.88);
  box-shadow:0 2px 6px rgba(0,0,0,.4);display:grid;place-items:center;font-size:14px}
.wheel-btn.ready{background:linear-gradient(180deg,#ffd76e,#f0a020);
  animation:wheelGlow 2s ease-in-out infinite}
@keyframes wheelGlow{0%,100%{box-shadow:0 2px 8px rgba(0,0,0,.4),0 0 0 0 rgba(255,200,87,.6)}
  50%{box-shadow:0 2px 8px rgba(0,0,0,.4),0 0 0 7px rgba(255,200,87,0)}}
.wheel-dot{position:absolute;top:1px;right:1px;width:8px;height:8px;border-radius:50%;
  background:var(--gold);box-shadow:0 0 0 2px var(--bg)}
.views{flex:1;overflow:hidden;position:relative}
.view{position:absolute;inset:0;overflow-y:auto;display:none;-webkit-overflow-scrolling:touch}
.view.active{display:flex;flex-direction:column}
.tabbar{display:flex;border-top:1px solid var(--line);background:rgba(29,19,10,.9);backdrop-filter:blur(12px);
  padding-bottom:var(--safe-b)}
.tabbtn{flex:1;padding:8px 2px 9px;display:grid;justify-items:center;gap:2px;font-size:10.5px;color:var(--dim);position:relative}
.tabbtn span{font-size:19px;line-height:1.1}
.tabbtn.active{color:var(--pink2)}
.dot{position:absolute;top:6px;right:calc(50% - 20px);width:8px;height:8px;border-radius:50%;background:var(--pink)}

/* ── the table ────────────────────────────────────────────────────────── */
/* The table view never scrolls as a page: the wood is a fixed-height field
   and the chat underneath takes whatever is left and scrolls on its own. */
.view[data-view="table"]{overflow:hidden}
/* The wood is painted under the heading, the tiles and the SPIN button alike,
   so the whole top of the screen reads as one tabletop. */
.table-wrap{position:relative;flex:0 0 auto;padding:6px 10px 0;background:var(--atm-field,var(--atm-bg))}
.table-head{position:relative;z-index:2;display:flex;align-items:flex-start;justify-content:space-between;gap:6px;margin-bottom:2px}
.table-head h2{font-size:14px;margin:0;color:#fff;text-shadow:0 1px 3px rgba(80,30,0,.75)}
.table-head small{font-size:10px;color:rgba(255,255,255,.92);text-shadow:0 1px 3px rgba(80,30,0,.75)}
.table-actions{display:flex;gap:4px}
.table-actions .btn-ghost{color:#fff;padding:3px 8px;border-radius:999px;text-shadow:0 1px 2px rgba(120,50,0,.45);
  font-size:10.5px;background:linear-gradient(180deg,#ffa63c,#ee7a0c);border:1.5px solid rgba(255,255,255,.88);
  box-shadow:0 2px 6px rgba(70,30,0,.4)}
.felt{position:relative;width:100%;height:var(--field-h)}
.bottle-holder{position:absolute;inset:0;display:grid;place-items:center;pointer-events:none}
/* Round 9: tapping the bottle itself spins it — no separate SPIN button.
   `.bottle-holder` stays pointer-events:none (it spans the whole felt, just
   to center its child) so it never steals taps meant for the seat tiles
   around it; `.bottle-tap` is the actual hit target, shrink-wrapped to the
   bottle + hint so it only ever eats taps genuinely on the bottle. */
.bottle-tap{pointer-events:auto;display:grid;justify-items:center;gap:6px;cursor:pointer;
  padding:14px 22px;-webkit-tap-highlight-color:transparent;touch-action:manipulation;
  transition:transform .12s ease}
.bottle-tap:active{transform:scale(.94)}
.bottle-tap.disabled{cursor:default;pointer-events:none}
.bottle-tap.disabled .bottle{filter:drop-shadow(0 7px 8px rgba(70,30,0,.5)) saturate(.55) brightness(.82)}
.spin-hint{padding:4px 12px;border-radius:999px;font-size:11.5px;font-weight:600;color:#fff;
  background:rgba(30,14,2,.55);text-shadow:0 1px 2px rgba(0,0,0,.4);backdrop-filter:blur(2px);
  white-space:nowrap}
/* Counting down to an automatic spin — a soft halo breathes behind the
   bottle so it is obvious a spin is about to start without anyone tapping. */
.bottle-tap.auto .bottle{animation:autopulse 1s ease-in-out infinite}
@keyframes autopulse{0%,100%{filter:drop-shadow(0 7px 8px rgba(70,30,0,.5)) drop-shadow(0 0 0 rgba(255,255,255,0))}
  50%{filter:drop-shadow(0 7px 8px rgba(70,30,0,.5)) drop-shadow(0 0 16px rgba(255,214,120,.85))}}
/* Deliberately NOT a percentage: `height:38%` on a replaced element (img)
   whose containing block gets its size from `aspect-ratio` (not an explicit
   height) resolves inconsistently — it once measured out to a share of the
   SVG's own intrinsic 360px height instead of the field, pushing the bottle
   off-centre. Computing straight from the same --field-h token the field
   itself uses sidesteps that percentage-resolution path entirely. */
.bottle{height:calc(var(--field-h) * .38);transform-origin:50% 50%;
  filter:drop-shadow(0 7px 8px rgba(70,30,0,.5));will-change:transform}
/* Player tiles sit round the edge of the wood (positions come from
   table.js#seatLayout); the middle is left clear for the bottle. */
.seats{position:absolute;inset:0;--seat-w:20%}
.seat{position:absolute;width:var(--seat-w);translate:-50% -50%;display:grid;justify-items:center;
  gap:3px;text-align:center;line-height:1.1}
/* Plain photo tiles — no border ring by default, just a soft drop shadow so
   they read as sitting slightly above the wood. VIP/me/target still get a
   ring, but only when there is something to signal. */
.seat .face{width:100%;aspect-ratio:1;border-radius:12px;object-fit:cover;background:#9a6535;
  box-shadow:0 4px 10px rgba(40,18,0,.55);transition:.2s}
.seat.empty .face{display:grid;place-items:center;font-size:24px;color:rgba(255,255,255,.85);
  border:2px dashed rgba(255,255,255,.6);background:rgba(255,255,255,.10);box-shadow:none}
.seat .nm{font-size:11px;font-weight:600;color:#fff;max-width:125%;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;text-shadow:0 1px 3px rgba(0,0,0,.85)}
.seat.empty .nm{color:rgba(255,255,255,.8);font-weight:500}
/* Past 8 seats the tiles are too narrow for the "free" caption; the dashed
   "+" already reads as an empty chair. */
.seats[data-dense="1"] .seat.empty .nm{display:none}
.seat.empty{cursor:pointer}
.seat.empty:active .face{background:rgba(255,255,255,.28)}
.seat.vip .face{box-shadow:0 0 0 2px var(--gold),0 4px 12px rgba(40,18,0,.55)}
.seat.vip .nm{color:#ffe9a8}
.seat.me .face{box-shadow:0 0 0 2px #3ddc97,0 4px 10px rgba(40,18,0,.55)}
.seat .crown{position:absolute;top:-10px;left:4%;font-size:15px;rotate:-18deg;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))}
.seat.target .face{animation:pulse 1s ease-in-out infinite;
  box-shadow:0 0 0 3px #ff3b5c,0 0 18px rgba(255,59,92,.85)}
.seat.online-off .face{filter:grayscale(.4) brightness(.8)}
@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.09)}}

/* ── DJ music bar ─────────────────────────────────────────────────────── */
/* A track anyone paid hearts for (or VIP, free) plays for the whole table —
   see public/js/music.js. No skip/pause for anyone: the progress bar below
   is a read-only "how far in" display, not a scrubber, and the only tap
   target that does anything is the mute toggle (purely local — it never
   touches anyone else's playback). */
.music-bar{display:flex;align-items:center;gap:10px;margin:6px 10px 8px;padding:8px;
  border-radius:16px;background:rgba(30,14,2,.6);color:#fff;font-size:12px;font-weight:600;
  text-shadow:0 1px 2px rgba(0,0,0,.4);backdrop-filter:blur(3px);box-shadow:0 4px 14px rgba(0,0,0,.35)}
.music-thumb{position:relative;flex:0 0 auto;width:52px;height:52px;border-radius:13px;overflow:hidden;background:#000}
.music-yt{position:absolute;inset:0}
.music-yt iframe{width:92px!important;height:92px!important;position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);pointer-events:none}
/* Audio-only mode: the YouTube player stays mounted and playing (some
   browsers throttle/pause a display:none iframe, so it's shrunk to
   nothing rather than removed) and a plain note icon fills the thumbnail. */
.music-bar .music-note{display:none;position:absolute;inset:0;place-items:center;font-size:20px;
  background:linear-gradient(160deg,var(--pink),var(--violet));animation:musicbeat 1.1s ease-in-out infinite}
.music-bar[data-video="0"] .music-yt{width:0;height:0}
.music-bar[data-video="0"] .music-note{display:grid}
@keyframes musicbeat{0%,100%{transform:scale(1)}50%{transform:scale(1.18)}}
/* Decorative — shown while muted as a "there's sound here" affordance, not
   a real playback control; tapping it does the same local unmute as the
   speaker button below. */
.music-play{position:absolute;inset:0;margin:auto;width:28px;height:28px;border-radius:50%;
  border:none;background:rgba(20,120,255,.88);color:#fff;font-size:12px;cursor:pointer;
  display:grid;place-items:center;box-shadow:0 2px 8px rgba(0,0,0,.4)}
.music-info{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:6px}
.music-text{display:flex;align-items:baseline;gap:5px;min-width:0}
.music-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.music-by{flex:0 0 auto;opacity:.8;font-weight:500;font-size:11px}
.music-controls{display:flex;align-items:center;gap:7px}
.music-speaker{flex:0 0 auto;border:none;background:none;color:#fff;font-size:13px;padding:0;
  cursor:pointer;display:grid;place-items:center;opacity:.9}
.music-speaker:active{opacity:.6}
.music-track{flex:1 1 auto;height:4px;border-radius:99px;background:rgba(255,255,255,.22);overflow:hidden}
.music-fill{height:100%;width:0%;border-radius:99px;background:var(--green);transition:width .9s linear}

/* ── music picker sheet (round 14) ───────────────────────────────────────
   Popular/Favorites/Recent/Search tabs above the existing paste-a-link
   field — tapping a row just fills that field, so the single 🎬/🎵 confirm
   step at the bottom stays the one and only "play this" action. */
.music-tabs{display:flex;gap:6px;margin-top:10px}
.music-tab{flex:1;padding:7px 0;border-radius:11px;border:none;background:rgba(255,255,255,.06);
  color:var(--muted);font-size:17px;cursor:pointer}
.music-tab.on{background:var(--pink);color:#fff}
#music-search-row{display:flex;gap:6px;margin-top:8px}
#music-search-row input{flex:1;background:rgba(255,255,255,.06);border:1px solid var(--line);border-radius:11px;
  padding:8px 10px;color:var(--text);font-size:13px}
.music-list{max-height:34vh;overflow-y:auto;margin-top:8px;display:flex;flex-direction:column;gap:5px}
.music-row{display:flex;align-items:center;gap:9px;width:100%;padding:6px;border-radius:12px;
  border:1px solid transparent;background:rgba(255,255,255,.04);text-align:left;cursor:pointer}
.music-row.sel{border-color:var(--pink);background:rgba(255,148,34,.12)}
.music-row-thumb{flex:0 0 auto;width:44px;height:44px;border-radius:9px;object-fit:cover;background:#000}
.music-row-thumb-empty{display:grid;place-items:center;font-size:16px;background:linear-gradient(160deg,var(--pink),var(--violet))}
.music-row-title{flex:1 1 auto;min-width:0;font-size:12.5px;font-weight:600;overflow:hidden;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.music-row-star{flex:0 0 auto;font-size:17px;padding:4px;opacity:.75}
.music-row-star.on{opacity:1}

/* ── chat ─────────────────────────────────────────────────────────────── */
/* The chat is the flexible half: it takes everything the table leaves and
   shrinks internally, so the input row is always on screen. It is the one
   light surface in the app (cream, white bubbles, orange send button). */
.chat{flex:1 1 auto;display:flex;flex-direction:column;min-height:0;border-top:3px solid #e58a1f;
  background:#fbf1e2;color:#33230f}
.chat-log{flex:1 1 auto;min-height:0;overflow-y:auto;padding:10px 12px;display:flex;
  flex-direction:column;gap:8px}
.chat-input{flex:0 0 auto}
.msg{display:flex;gap:8px;align-items:flex-start}
.msg img{width:30px;height:30px;border-radius:10px;object-fit:cover;flex:0 0 auto;background:#e9d3b4}
.msg .bub{background:#fff;border:1px solid rgba(120,70,20,.10);box-shadow:0 1px 2px rgba(120,70,20,.10);
  border-radius:4px 14px 14px 14px;padding:7px 11px;max-width:78%}
.msg .who{font-size:11.5px;font-weight:700;color:#e07a10;margin-bottom:1px}
.msg.mine{flex-direction:row-reverse}
.msg.mine .bub{background:#ffe3bd;border-color:rgba(230,138,31,.35);border-radius:14px 4px 14px 14px}
.msg.mine .who{color:#a65400;text-align:right}
.msg .txt{word-break:break-word;white-space:pre-wrap}
.sysmsg{align-self:center;font-size:12px;color:#8a6a48;background:rgba(120,70,20,.08);
  padding:5px 12px;border-radius:999px;max-width:90%;text-align:center}
.sysmsg.kiss{color:#b3261e;background:rgba(255,90,60,.14);font-weight:600}
.sysmsg.gift{color:#8a5a00;background:rgba(255,190,60,.30)}
.typing{height:14px;font-size:11px;color:#a68b6a;padding:0 14px}
.chat-input{display:flex;gap:8px;padding:8px 10px calc(8px + var(--safe-b));border-top:1px solid rgba(120,70,20,.14);
  background:#fff8ee;align-items:center}
.chat-input input{flex:1;min-width:0;background:#f3e4cd;color:#33230f;border-radius:999px;padding:11px 16px}
.chat-input input::placeholder{color:#a68b6a}
.chat .icon-btn:not(.send){background:#ffe9cf;border-radius:50%}

/* ── stickers ─────────────────────────────────────────────────────────── */
.msg .stick{font-size:46px;line-height:1.05;padding:2px 4px;
  filter:drop-shadow(0 6px 12px rgba(0,0,0,.45))}
.msg.mine .bub.sticker,.msg .bub.sticker{background:none;border:0;padding:0;box-shadow:none}
.stk-packs{display:flex;gap:6px;overflow-x:auto;padding:2px 0 8px}
.stk-pack{display:grid;justify-items:center;gap:2px;min-width:60px;padding:7px 8px;border-radius:14px;
  background:rgba(255,255,255,.06);font-size:11px;color:var(--muted);white-space:nowrap;position:relative}
.stk-pack .pe{font-size:22px;line-height:1}
.stk-pack.on{background:linear-gradient(120deg,rgba(255,148,34,.30),rgba(255,106,26,.30));color:var(--text)}
.stk-pack.locked .pe{filter:grayscale(1) brightness(.7)}
.stk-pack .lk{position:absolute;top:2px;right:4px;font-size:10px}
.stk-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;max-height:44vh;overflow-y:auto;padding:2px}
.stk{background:rgba(255,255,255,.05);border-radius:14px;padding:8px 2px;font-size:32px;line-height:1.1}
.stk:active{background:rgba(255,255,255,.13)}
.stk-locked{text-align:center;padding:16px 8px}
.stk-locked .big{font-size:44px}

/* ── tables list ──────────────────────────────────────────────────────── */
.tables-list{display:grid;gap:10px;margin-top:12px}
.trow{display:flex;align-items:center;gap:12px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);padding:12px 14px}
.trow .no{font-weight:800;font-size:17px;min-width:44px}
.trow .faces{display:flex;flex:1}
.trow .faces img{width:28px;height:28px;border-radius:9px;object-fit:cover;margin-left:-8px;
  border:2px solid var(--card);background:var(--card2)}
.trow .faces img:first-child{margin-left:0}
.trow .cap{font-size:12.5px;color:var(--muted);min-width:44px;text-align:right}
.trow.full{opacity:.55}
.trow.here{border-color:var(--pink)}

/* ── leaderboard ──────────────────────────────────────────────────────── */
.tabs{display:flex;gap:6px;margin:10px 0 12px;overflow-x:auto;padding-bottom:2px}
.tab{padding:8px 12px;border-radius:12px;background:rgba(255,255,255,.06);font-size:13px;font-weight:600;white-space:nowrap}
.tab.active{background:linear-gradient(120deg,var(--pink),var(--violet));color:#fff}
.lb-list{display:grid;gap:8px}
.lb-row{display:flex;align-items:center;gap:11px;background:var(--card);border:1px solid var(--line);
  border-radius:15px;padding:9px 12px}
.lb-row .pl{font-weight:800;width:26px;text-align:center;color:var(--muted)}
.lb-row img{width:38px;height:38px;border-radius:12px;object-fit:cover;background:var(--card2)}
.lb-row .nm{flex:1;min-width:0}
.lb-row .nm b{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lb-row .nm small{color:var(--muted)}
.lb-row .sc{font-weight:800;color:var(--pink2)}
.lb-row.top1{background:linear-gradient(120deg,rgba(255,200,87,.16),var(--card));border-color:rgba(255,200,87,.4)}
.lb-row.mine{border-color:var(--pink)}
.lb-me{position:sticky;bottom:0;padding:8px 14px calc(10px + var(--safe-b));background:rgba(29,19,10,.92);
  backdrop-filter:blur(10px);border-top:1px solid var(--line)}
.online-pip{width:8px;height:8px;border-radius:50%;background:var(--green);display:inline-block}

/* ── cards / shop ─────────────────────────────────────────────────────── */
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px;margin-bottom:12px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.pack{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px;text-align:center;position:relative}
.pack .amt{font-size:19px;font-weight:800}
.pack .cost{color:var(--muted);font-size:13px;margin:4px 0 10px}
.pack .ribbon{position:absolute;top:-9px;left:50%;translate:-50% 0;background:var(--gold);color:#2a1c00;
  font-size:10px;font-weight:800;padding:2px 9px;border-radius:999px;white-space:nowrap}
.pack.best{border-color:var(--gold)}
.perk{display:flex;gap:10px;align-items:flex-start;padding:6px 0;font-size:13.5px}
.bottle-card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:10px;text-align:center;position:relative}
.bottle-card img{height:78px;margin:4px 0}
.bottle-card .bn{font-size:12px;font-weight:700}
.bottle-card .bu{font-size:11px;color:var(--muted);min-height:14px}
.bottle-card.equipped{border-color:var(--pink);box-shadow:0 0 0 1px rgba(255,148,34,.35)}
.bottle-card.locked img{filter:grayscale(1) brightness(.65)}
.lockpill{position:absolute;top:8px;right:8px;font-size:10px;background:rgba(0,0,0,.5);padding:2px 7px;border-radius:999px}

/* ── gift grid ────────────────────────────────────────────────────────── */
/* Each gift sits in a glossy round badge (a radial highlight + a rarity-
   tinted glow behind it) instead of a plain emoji floating on a flat card —
   reads as a "sticker" the way a real gift-shop grid does, using nothing but
   CSS on top of the emoji already there (no new art to fetch or license). */
.gifts{display:grid;grid-template-columns:repeat(4,1fr);gap:9px;max-height:52vh;overflow-y:auto;padding:2px}
.gift{--rc:var(--muted);background:var(--card);border:1px solid var(--line);border-radius:16px;
  padding:10px 4px 9px;text-align:center;display:grid;gap:3px;justify-items:center;position:relative}
.gift .g-badge{width:52px;height:52px;border-radius:50%;display:grid;place-items:center;margin-bottom:1px;
  background:
    radial-gradient(circle at 32% 28%, rgba(255,255,255,.9), rgba(255,255,255,0) 42%),
    radial-gradient(circle at 50% 55%, color-mix(in srgb, var(--rc) 55%, var(--card2)), color-mix(in srgb, var(--rc) 22%, var(--bg)) 76%);
  box-shadow:inset 0 -3px 6px rgba(0,0,0,.25), inset 0 2px 3px rgba(255,255,255,.5), 0 3px 8px rgba(0,0,0,.35)}
.gift .g-em{font-size:27px;line-height:1;filter:drop-shadow(0 2px 2px rgba(0,0,0,.35))}
.gift .g-nm{font-size:10px;color:var(--muted);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gift .g-pr{font-size:11px;font-weight:800;color:#fff;background:linear-gradient(180deg,#ff6a7a,#e8394f);
  padding:1px 9px;border-radius:999px;display:inline-flex;align-items:center;gap:2px}
.gift.sel{border-color:var(--rc);box-shadow:0 0 0 2px color-mix(in srgb, var(--rc) 55%, transparent)}
.gift.sel .g-badge{box-shadow:inset 0 -3px 6px rgba(0,0,0,.25), inset 0 2px 3px rgba(255,255,255,.5), 0 0 0 3px color-mix(in srgb, var(--rc) 65%, transparent), 0 3px 10px rgba(0,0,0,.4)}
.showcase{display:flex;flex-wrap:wrap;gap:6px}
.showcase .sg{background:rgba(255,255,255,.06);border-radius:11px;padding:5px 8px;font-size:14px}
.showcase .sg small{font-size:10px;color:var(--muted);margin-left:2px}

/* ── sheets & modals ──────────────────────────────────────────────────── */
.sheet{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:50;display:flex;align-items:flex-end;
  backdrop-filter:blur(3px);animation:fade .18s}
.sheet-body{width:100%;max-height:92dvh;overflow-y:auto;background:linear-gradient(180deg,var(--card2),var(--card));
  border-radius:24px 24px 0 0;padding:16px 16px calc(20px + var(--safe-b));border-top:1px solid var(--line);
  animation:up .24s cubic-bezier(.2,.9,.3,1)}
.modal{position:fixed;inset:0;background:rgba(14,7,2,.82);z-index:55;display:grid;place-items:center;padding:18px;
  backdrop-filter:blur(6px);animation:fade .18s}
.modal-body{width:100%;max-width:400px;background:linear-gradient(160deg,var(--card2),var(--card));
  border:1px solid var(--line);border-radius:24px;padding:20px;text-align:center;animation:pop .24s cubic-bezier(.2,.9,.3,1)}
@keyframes fade{from{opacity:0}}
@keyframes up{from{transform:translateY(24px);opacity:.4}}
@keyframes pop{from{transform:scale(.9);opacity:0}}
.sheet-grab{width:38px;height:4px;border-radius:9px;background:rgba(255,255,255,.2);margin:0 auto 12px}

/* profile modal — pops from the center (round 11), not a bottom sheet */
.pf-card{position:relative;text-align:left}
.pf-x{position:absolute;top:-14px;right:-14px;width:32px;height:32px;border-radius:50%;
  border:none;background:var(--green);color:#0b2a1e;font-size:14px;font-weight:800;
  display:grid;place-items:center;cursor:pointer;box-shadow:0 4px 10px rgba(0,0,0,.4);z-index:2}
.pf-x:active{transform:scale(.92)}
.pf-head{display:flex;gap:14px;align-items:center;margin-bottom:12px}
.pf-head img{width:82px;height:82px;border-radius:22px;object-fit:cover;background:var(--card2);border:2px solid var(--line)}
.pf-head.vip img{border-color:var(--gold)}
.pf-name{font-size:20px;font-weight:800;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.pf-meta{color:var(--muted);font-size:13px;margin-top:2px}
.pf-bio{background:rgba(0,0,0,.22);border-radius:12px;padding:10px 12px;font-size:13.5px;margin:10px 0}
.pf-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin:12px 0}
.pf-stat{background:rgba(255,255,255,.05);border-radius:13px;padding:9px 4px;text-align:center}
.pf-stat b{display:block;font-size:17px}
.pf-stat small{color:var(--muted);font-size:10.5px}
.pf-actions{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:6px}
.pf-actions .full{grid-column:1/-1}
.badge{font-size:10.5px;font-weight:800;padding:2px 8px;border-radius:999px;background:rgba(255,255,255,.1)}
.badge.gold{background:linear-gradient(120deg,#ffd76e,#e0a020);color:#2a1c00}
.badge.rank{background:linear-gradient(120deg,rgba(255,148,34,.35),rgba(255,106,26,.35))}

/* kiss modal */
.kiss-pair{display:flex;align-items:center;justify-content:center;gap:14px;margin:6px 0 14px}
.kiss-pair img{width:88px;height:88px;border-radius:24px;object-fit:cover;background:var(--card2);border:2px solid var(--line)}
.kiss-heart{font-size:34px;animation:beat 1s ease-in-out infinite}
@keyframes beat{0%,100%{transform:scale(1)}50%{transform:scale(1.22)}}
.kiss-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:14px}
.timer{height:5px;border-radius:9px;background:rgba(255,255,255,.12);overflow:hidden;margin-top:14px}
.timer i{display:block;height:100%;background:linear-gradient(90deg,var(--pink),var(--violet));width:100%}
.waiting{color:var(--muted);font-size:13px;margin-top:12px}
.result-big{font-size:56px;margin:6px 0}

/* ── daily free-spin wheel ─────────────────────────────────────────────── */
.wheel-wrap{position:relative;width:min(78vw,280px);margin:10px auto 4px;aspect-ratio:1}
/* The dedicated page has more room than the old popup did. */
.wheel-wrap-page{width:min(84vw,360px);margin:18px auto 8px}
.wheel-pointer{position:absolute;top:-6px;left:50%;translate:-50% 0;font-size:20px;z-index:2;
  color:var(--gold);filter:drop-shadow(0 2px 4px rgba(0,0,0,.5))}
.wheel{position:absolute;inset:4%;border-radius:50%;border:4px solid rgba(255,255,255,.16);
  box-shadow:0 10px 34px rgba(0,0,0,.5),inset 0 0 0 2px rgba(0,0,0,.25);transform:rotate(0deg)}
.wheel-lbl{position:absolute;translate:-50% -50%;display:flex;flex-direction:column;align-items:center;
  gap:1px;font-size:15px;line-height:1;text-shadow:0 1px 3px rgba(0,0,0,.6);color:#1a1030}
.wheel-lbl b{font-size:10px;font-weight:800}
/* .hidden (global utility, display:none !important) already covers this. */
.wheel-result{min-height:26px;text-align:center;font-size:15px;margin-top:10px}

/* toasts + fx */
.toasts{position:fixed;left:0;right:0;top:calc(var(--safe-t) + 8px);z-index:70;display:grid;gap:6px;
  justify-items:center;pointer-events:none;padding:0 12px}
.toast{background:rgba(43,29,17,.96);border:1px solid var(--line);border-radius:14px;padding:9px 15px;
  font-size:13.5px;max-width:92%;box-shadow:0 10px 30px rgba(0,0,0,.45);animation:up .2s}
.toast.err{border-color:rgba(255,95,95,.5)}
.toast.ok{border-color:rgba(61,220,151,.5)}
.fx{position:fixed;inset:0;pointer-events:none;z-index:52;overflow:hidden}
.fx .heart{position:absolute;font-size:26px;animation:float 2.2s ease-out forwards}
@keyframes float{0%{transform:translateY(0) scale(.4);opacity:0}
  15%{opacity:1}100%{transform:translateY(-70vh) scale(1.3) rotate(20deg);opacity:0}}

/* ── gift-flies-to-recipient animation ──────────────────────────────────── */
/* Driven frame-by-frame from JS (table.js), not a CSS animation — its
   transform is written directly on every rAF tick, so no keyframes here. */
.gift-fly{position:fixed;top:0;left:0;z-index:75;font-size:44px;line-height:1;pointer-events:none;
  filter:drop-shadow(0 10px 20px rgba(0,0,0,.6))}
/* The comet-tail left behind along the flight path — a scatter of small
   colourful stars (not a repeat of the gift icon), each with its own drift
   and spin so the trail reads as sparkle rather than a row of copies. */
.fx .gift-trail{position:fixed;top:0;left:0;z-index:73;font-size:15px;line-height:1;pointer-events:none;
  transform:translate(-50%,-50%) rotate(var(--r,0deg));animation:giftTrailFade 650ms ease-out forwards}
@keyframes giftTrailFade{0%{opacity:.85;transform:translate(-50%,-50%) translate(0,0) rotate(var(--r,0deg)) scale(.9)}
  100%{opacity:0;transform:translate(-50%,-50%) translate(var(--dx,0),var(--dy,14px)) rotate(var(--r2,0deg)) scale(.3)}}
.fx .spark{position:fixed;top:0;left:0;z-index:74;font-size:16px;pointer-events:none;
  animation:sparkFloat 900ms ease-out forwards}
@keyframes sparkFloat{0%{transform:translate(-50%,-50%) scale(.5) rotate(0deg);opacity:0}
  20%{opacity:1}100%{transform:translate(-50%,-170%) scale(1.1) rotate(90deg);opacity:0}}
/* The recipient's avatar pulses gold the instant the gift lands on it. */
.seat .face.gift-hit{animation:giftHit .9s ease}
@keyframes giftHit{0%{box-shadow:0 5px 12px rgba(70,30,0,.5)}
  25%{transform:scale(1.2);box-shadow:0 0 0 10px rgba(255,200,87,.45),0 6px 22px rgba(255,200,87,.4)}
  100%{transform:scale(1);box-shadow:0 5px 12px rgba(70,30,0,.5)}}

.threads{display:grid;gap:8px;margin-top:10px}
.thread{display:flex;gap:11px;align-items:center;background:var(--card);border:1px solid var(--line);
  border-radius:15px;padding:10px 12px}
.thread img{width:42px;height:42px;border-radius:13px;object-fit:cover;background:var(--card2)}
.thread .tb{flex:1;min-width:0}
.thread .tb b{display:block}
.thread .tb small{color:var(--muted);display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.thread .un{background:var(--pink);color:#fff;font-size:11px;font-weight:800;border-radius:999px;padding:1px 7px}
.dm-log{max-height:52vh;overflow-y:auto;display:flex;flex-direction:column;gap:7px;margin:10px 0;padding:2px}
.dm{max-width:80%;padding:8px 12px;border-radius:14px;background:var(--card2);align-self:flex-start;font-size:14px}
.dm.mine{align-self:flex-end;background:linear-gradient(120deg,rgba(255,148,34,.32),rgba(255,106,26,.32))}
.dm-form{display:flex;gap:8px}
.dm-form input{flex:1;background:rgba(255,255,255,.07);border-radius:14px;padding:11px 14px}
.empty{text-align:center;color:var(--dim);padding:30px 10px}
.rank-bar{height:7px;border-radius:9px;background:rgba(255,255,255,.1);overflow:hidden;margin-top:8px}
.rank-bar i{display:block;height:100%;background:linear-gradient(90deg,var(--pink),var(--gold))}
.kv{display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--line);font-size:14px}
.kv:last-child{border-bottom:0}


/* ── language picker ──────────────────────────────────────────────────── */
.lang-chips .chip{min-width:0;display:flex;align-items:center;justify-content:center;gap:6px}
.lang-row{display:grid;gap:8px;margin-top:6px}
.lang-row .chip{width:100%;text-align:left;justify-content:flex-start;padding:13px 14px}

/* ── atmosphere picker ────────────────────────────────────────────────── */
.atm-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin:12px 0 4px}
.atm{border-radius:16px;padding:10px;border:1px solid var(--line);font-weight:700;font-size:13px;
  display:grid;gap:8px;justify-items:stretch;text-align:left;background:rgba(255,255,255,.05)}
.atm .swatch{height:46px;border-radius:12px;border:1px solid rgba(255,255,255,.14)}
.atm.on{border-color:var(--pink);box-shadow:0 0 0 1px rgba(255,148,34,.4)}
.atm[data-atm="wood"] .swatch{background:url('/assets/wood.svg') center/cover, #d98f42}
.atm[data-atm="velvet"] .swatch{background:radial-gradient(circle at 40% 30%,#3b2a63,#1d1436 75%)}
.atm[data-atm="neon"] .swatch{background:
  radial-gradient(70% 90% at 15% 0%, rgba(255,0,140,.5), transparent 60%),
  radial-gradient(70% 90% at 90% 20%, rgba(0,220,255,.45), transparent 60%), #07030f}
.atm[data-atm="beach"] .swatch{background:linear-gradient(180deg,#1f6f93,#37a2a6 58%,#d9b477 59%)}
.atm[data-atm="garden"] .swatch{background:linear-gradient(180deg,#2f6b3c,#0b2114)}
.atm[data-atm="casino"] .swatch{background:radial-gradient(circle at 50% 30%,#1f5d3a,#16060a 80%)}

/* ── invite-a-friend sheet (tapping a free seat) ──────────────────────── */
.invite-link{display:block;width:100%;background:rgba(0,0,0,.3);border:1px solid var(--line);
  border-radius:var(--radius-sm);padding:11px 13px;font-size:12.5px;word-break:break-all;
  color:var(--muted);margin:10px 0 12px;text-align:left}

/* Tab bar labels are wrapped in <i> so they can be translated in place. */
.tabbtn i{font-style:normal}
.tabbtn i.dot{position:absolute}
