*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}
:root{--font:'Roboto',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;--accent:rgb(95,95,148);--accent2:rgba(68,68,111,0.6);--green:rgb(88,190,140)}
::selection{background:rgba(255,255,255,0.25);color:#fff}
html{scrollbar-width:none;scroll-behavior:smooth}
html::-webkit-scrollbar{display:none}
body{background:#000;color:#fff;font-family:var(--font);letter-spacing:-0.011em;overflow-x:hidden;min-height:100vh;user-select:none;-webkit-user-select:none}
input,textarea{user-select:text;-webkit-user-select:text}
img{-webkit-user-drag:none;user-drag:none;-khtml-user-drag:none;-moz-user-drag:none;-o-user-drag:none}

#topo-canvas{position:fixed;inset:0;z-index:0;pointer-events:none;opacity:0.25}
#bg-canvas{position:fixed;inset:0;z-index:0;pointer-events:none}

/* ── Boot loading screen ── */
.loading-screen{position:fixed;inset:0;z-index:500;background:#0d0f0d;font-family:var(--font);text-transform:uppercase;opacity:1;transition:opacity .45s ease}
.loading-screen.hiding{opacity:0;pointer-events:none}
/* The bar is a fixed 820px block (not full-width): its gradient fades in from the left and
   ends exactly at CANCEL's right edge, which sits 250px right of screen center like the
   reference. Content is right-aligned inside, so a longer tip grows LEFT into the bar and
   the button never shifts. */
.loading-bar{position:absolute;top:50%;right:calc(50% - 250px);transform:translateY(-50%);width:min(820px,100vw);height:150px;display:flex;align-items:center;justify-content:flex-end;background:linear-gradient(270deg,#1a1e1a,transparent)}
.loading-text{flex:1;min-width:0;text-align:right;padding-right:26px;white-space:nowrap}
.loading-title{font-size:54px;font-weight:800;line-height:1;color:#fff;letter-spacing:0.01em}
.loading-tip{margin-top:6px;font-size:18px;font-weight:700;color:#606460;letter-spacing:0.02em}
.loading-cancel{flex-shrink:0;height:100%;width:160px;padding:0;border:none;background:#7b271a;color:#e39c8e;font-size:20px;font-weight:600;text-transform:uppercase;letter-spacing:0.02em;font-family:var(--font);cursor:pointer;transition:background .15s}
@media (max-width:900px){.loading-bar{right:0;width:100%}}
.loading-cancel:hover{background:#8c2d1e}
.loading-logo{position:absolute;left:50%;bottom:9%;transform:translateX(-50%);width:240px;height:auto}

header{position:fixed;top:0;left:0;right:0;z-index:100;display:flex;justify-content:center;padding:14px 24px;pointer-events:none}
.nav-inner{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;max-width:1180px;height:52px;padding:0 12px 0 18px;background:rgba(10,10,10,0.88);backdrop-filter:blur(32px);-webkit-backdrop-filter:blur(32px);border:1px solid rgba(255,255,255,0.07);border-radius:18px;box-shadow:0 4px 32px rgba(0,0,0,0.5);pointer-events:all}
/* Desktop: game links dead-center in the pill regardless of how wide the logo or the
   wallet/user side are. Mobile keeps its dropdown panel (see the 768px block). */
@media (min-width:769px){
  .nav-links{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}
}
/* Signed-in identity, far right: name then avatar (a Rust item pic on a soft chip). */
.nav-user:hover{background:rgba(255,255,255,0.07)}
.nav-user-name{font-size:14px;font-weight:600;color:rgba(255,255,255,0.9)}
/* Red dropdown arrow; hovering anywhere on the username/arrow (or the menu itself)
   reveals the logout menu below. The menu's top padding doubles as a hover bridge. */
.nav-user{display:flex;align-items:center;gap:4px;padding:3px 3px 3px 9px;border-radius:8px;transition:background .15s;position:relative;cursor:default}
.nav-user-menu-wrap{display:flex;align-items:center}
.nav-user-arrow{display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;border-radius:8px;background:transparent;color:#eb4d4b;cursor:pointer;transition:background .15s,transform .2s}
.nav-user-arrow svg{width:18px;height:18px}
.nav-user:hover .nav-user-arrow{transform:rotate(180deg)}
.nav-user-menu{position:absolute;top:100%;right:0;padding-top:16px;display:none;z-index:120}
.nav-user:hover .nav-user-menu{display:block}
.nav-logout-btn{display:flex;align-items:center;gap:9px;white-space:nowrap;padding:11px 18px 11px 14px;border:1px solid rgba(255,255,255,0.08);border-radius:12px;background:rgba(10,10,10,0.96);backdrop-filter:blur(32px);-webkit-backdrop-filter:blur(32px);box-shadow:0 12px 32px rgba(0,0,0,0.5);color:#eb4d4b;font-size:14px;font-weight:600;font-family:var(--font);cursor:pointer;transition:background .15s}
.nav-logout-btn:hover{background:rgba(235,77,75,0.1)}
.nav-logout-btn svg{width:16px;height:16px;flex-shrink:0}
.nav-brand-wrap{position:relative;flex-shrink:0}
/* Deliberately taller than the bar — the sign hanging past the header edge is the look. */
/* Full strength at rest; on hover it pops out and fades slightly — signals it's clickable. */
.nav-logo{height:45px;width:auto;display:block;margin:-4px 0;transition:transform .16s ease,opacity .16s ease}
.nav-brand:hover .nav-logo{transform:scale(1.07);opacity:0.75}
.nav-brand{display:flex;align-items:center;gap:10px;font-size:15px;font-weight:700;color:#fff;letter-spacing:-0.01em;cursor:pointer}

/* Logged-out home hero: welcome text left, live player count right — both pulled in
   toward the center of the bar rather than hugging the page edges. */
.home-hero-guest{display:flex;align-items:center;justify-content:space-between;gap:28px;max-width:1000px;margin:0 auto;padding:72px 4px 10px;flex-wrap:wrap;font-family:var(--font)}
.home-welcome{font-size:15px;font-weight:700;letter-spacing:0.02em;color:rgb(239,239,239)}
.home-title{margin:2px 0 0;font-size:32px;font-weight:900;letter-spacing:0.01em;color:rgb(215,103,85);line-height:1.1;font-family:var(--font)}
.home-subtitle{margin:8px 0 0;font-size:14.5px;color:rgba(255,255,255,0.7)}
.home-online{display:flex;align-items:center;gap:9px}
.home-online-icon{width:22px;height:22px;color:rgb(215,103,85);flex-shrink:0}
.home-online-text{font-size:14.5px;font-weight:700;color:rgb(239,239,239);white-space:nowrap}
/* Logged-in variant: same centered band, just a greeting on the left. */
/* min-height matches the guest hero's content (3 text lines) so the page below doesn't
   jump up or down when login swaps which hero is showing. */
.home-hero-auth{display:flex;align-items:center;justify-content:space-between;gap:28px;max-width:1000px;margin:0 auto;padding:72px 4px 10px;min-height:163px;flex-wrap:wrap;font-family:var(--font)}
.home-welcome-back{margin:0;font-size:26px;font-weight:800;color:rgb(239,239,239);line-height:1.2;font-family:var(--font)}
/* No heading on the home feed, and it lines up with the hero's centered 820px band.
   Doubled class beats the later .live-wins-section{max-width:1180px} base rule. */
.live-wins-section.home-live-wins{max-width:1000px;margin:14px auto 0}
/* Rewards banner: same centered band as the hero and feed. */
.home-rewards{position:relative;max-width:1000px;margin:14px auto 0;border-radius:14px;overflow:hidden;border:1px solid rgba(255,255,255,0.07)}
/* Slide strip: all banners side by side, the track glides between them. */
.home-rewards-track{display:flex;transition:transform .35s cubic-bezier(.22,1,.36,1);touch-action:pan-y;user-select:none;-webkit-user-select:none;cursor:grab}
.home-rewards-track.dragging{cursor:grabbing}
.home-rewards-bg{-webkit-user-drag:none;display:block;width:100%;height:auto;flex-shrink:0}
/* A slide with copy over its art: the art still sets the height, the copy floats centred. */
.home-rewards-slide{position:relative;flex-shrink:0;width:100%}
.home-levelup-copy{position:absolute;inset:0;display:flex;flex-direction:column;align-items:flex-start;justify-content:center;padding-left:6%;pointer-events:none}
/* The block stays left; inside it the label and chip centre on the headline's width. */
.home-levelup-copy>*{align-self:auto}
.home-levelup-block{display:flex;flex-direction:column;align-items:center;gap:4px;text-align:center}
.home-levelup-label{font-size:18px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#fff;text-shadow:0 2px 10px rgba(0,0,0,0.5)}
.home-levelup-title{font-size:30px;font-weight:800;letter-spacing:.02em;text-transform:uppercase;color:#fff;line-height:1.05;text-shadow:0 2px 12px rgba(0,0,0,0.55)}
.home-levelup-chip{pointer-events:auto;display:inline-flex;align-items:center;gap:7px;margin-top:10px;padding:8px 16px;border:none;border-radius:999px;background:#66852f;color:#eef8dc;font:700 13.5px/1 "Roboto",sans-serif;cursor:pointer;box-shadow:0 3px 10px rgba(0,0,0,0.35);transition:filter .15s}
.home-levelup-chip:hover{filter:brightness(1.08)}
.home-levelup-chip[hidden]{display:none} /* the class's inline-flex would otherwise beat the hidden attribute */
.home-levelup-chip svg{width:15px;height:15px;display:block}
/* Level gauge: a fixed 200×200 block. Two circles in a 43.48-unit viewBox (r=20, stroke 3.48,
   circumference 125.664 as the dash length), rotated 185° so the fill starts low-left; the dim
   track is a full ring, the orange fill's dash offset is the progress; glow on the whole SVG. */
.home-levelup-gauge{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:200px;height:200px;pointer-events:none}
.home-levelup-gauge svg{position:absolute;inset:0;top:30px;width:100%;height:100%;overflow:visible;transform:rotate(180deg);filter:drop-shadow(rgba(255,198,92,0.5) 0 0 24px)}
.level-gauge-track,.level-gauge-fill,.level-gauge-mask{fill:transparent;stroke-width:3.48;stroke-dasharray:125.664}
.level-gauge-track{stroke:rgba(158,158,158,0.4);stroke-dashoffset:62.832;stroke-linecap:round;opacity:.6} /* half the circumference: the top 180° only */
.level-gauge-fill{stroke:#ff9800;stroke-linecap:round;stroke-dashoffset:125.664;opacity:1}
/* white = visible; flat caps; starts 1 arc unit before the fill (rotation of 1/20 rad) */
.level-gauge-mask{stroke:#fff;stroke-linecap:butt;stroke-dashoffset:125.664} /* its head start (LEVEL_CAP_HEAD) is the rotate() attribute in the markup, about the circle centre */
.level-gauge-center{position:absolute;left:50%;top:51%;transform:translate(-50%,-50%);text-align:center;line-height:1}
.level-gauge-num{font-size:48px;font-weight:800;color:#fff}
.level-gauge-label{margin-top:4px;font-size:16px;font-weight:600;text-transform:uppercase;color:#ff9800}
.level-gauge-tier{position:absolute;top:78%;width:28px;height:28px;transform:translate(-50%,-50%);pointer-events:auto;cursor:default}
.level-gauge-tier img{display:block;width:28px;height:28px;object-fit:contain}
/* hover tooltip: "Tier N", above the icon */
.level-gauge-tier::after{content:attr(data-tip);position:absolute;left:50%;bottom:calc(100% + 7px);transform:translateX(-50%) translateY(3px);padding:8px 14px;border-radius:7px;background:rgba(70,70,74,0.82);color:#fff;font-size:14.5px;font-weight:700;line-height:1;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .14s ease,transform .14s ease}
.level-gauge-tier:hover::after{opacity:1;transform:translateX(-50%) translateY(0)}
.level-gauge-tier.cur{left:3%}
.level-gauge-tier.next{left:97%}
/* Next Reward panel: pinned to the right third, stacked and centred */
.home-levelup-reward{position:absolute;right:5%;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;align-items:center;gap:6px;pointer-events:none}
.home-reward-label{font-size:13px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#fff;position:relative;top:5px}
.home-reward-img{width:252px;height:194px;margin-bottom:-32px;object-fit:contain;display:block}
.home-reward-line{display:flex;align-items:center;gap:7px;font-size:15px;line-height:1;white-space:nowrap}
.home-reward-qty{color:#8cc2e7;font-weight:900}
.home-reward-tier{padding:4px 10px;border-radius:999px;background:#265c81;color:#d9ebf7;font-size:12px;font-weight:600}
.home-reward-text{color:#fff;font-weight:400}
.level-gauge-remaining{position:absolute;left:50%;bottom:30px;transform:translateX(-50%);white-space:nowrap;font-size:12px;font-weight:400;color:rgba(255,255,255,0.7)}
/* Same recipe as .wheel-stacks-arrow — round dark chevrons at the banner's edges. */
.home-rewards-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;display:flex;align-items:center;justify-content:center;padding:0;width:38px;height:38px;border-radius:50%;border:none;background:rgba(20,20,20,0.85);color:rgba(255,255,255,0.8);cursor:pointer;transition:all .16s;box-shadow:0 2px 8px rgba(0,0,0,0.5)}
.home-rewards-arrow:hover{background:rgba(45,45,45,0.95);color:#fff}
.home-rewards-arrow svg{width:26px;height:26px;display:block}
.home-rewards-arrow.left{left:12px}
.home-rewards-arrow.right{right:12px}
/* Slide indicator dots, bottom center — active one lights up. */
.home-rewards-dots{position:absolute;bottom:10px;left:50%;transform:translateX(-50%);z-index:2;display:flex;gap:15px}
.home-rewards-dot{width:9px;height:9px;padding:0;border:none;border-radius:50%;background:rgba(255,255,255,0.4);cursor:pointer;transition:background .18s,transform .18s}
.home-rewards-dot:hover{background:rgba(255,255,255,0.65)}
.home-rewards-dot.active{background:#fff}
/* Games section header — a step below the welcome-back heading (26px). */
.home-games-heading{max-width:1000px;margin:34px auto 0;font-size:18px;font-weight:800;color:rgb(239,239,239);font-family:var(--font)}
.home-games-grid{max-width:1000px;margin:16px auto 0;display:flex;gap:16px}
/* Game card: bg art fills the card; on hover the card lifts, a dark overlay drops in,
   and the icon/title drift upward. Overlay lives in ::after so opacity can transition. */
/* Sized to match a /cases grid card at desktop width. --color is the per-card accent
   (swap it per game); the hover glow reads from it. */
.home-game-card{--color:#e67e22;position:relative;display:block;flex:1 1 0;min-width:0;height:264px;border-radius:12px;overflow:hidden;background-color:#1e1e1e;background-size:cover;background-position:center;box-shadow:0 4px 14px rgba(0,0,0,0.35);transition:transform .3s;text-decoration:none}
.home-game-card::after{content:"";position:absolute;inset:0;background:rgba(0,0,0,0.5);opacity:0;transition:opacity .3s;z-index:0}
/* Accent glow: rises from the bottom on hover, above the darkening overlay. */
.home-game-card::before{content:"";position:absolute;inset:0;background:linear-gradient(0deg,var(--color),transparent);opacity:0;transition:opacity .3s;z-index:1}
.home-game-card:hover{transform:translateY(-4px)}
.home-game-card:hover::after{opacity:1}
.home-game-card:hover::before{opacity:0.5}
.home-game-icon{position:absolute;left:50%;top:42%;transform:translate(-50%,-50%);width:72px;height:72px;z-index:2;transition:transform .3s}
.home-game-card:hover .home-game-icon{transform:translate(-50%,-60%)}
.home-game-title{position:absolute;left:0;right:0;top:70%;z-index:2;text-align:center;color:#fff;font-size:26px;font-weight:800;text-transform:uppercase;line-height:1.15;font-family:var(--font);transition:transform .3s}
.home-game-card:hover .home-game-title{transform:translateY(-5%)}
.home-game-ribbon{position:absolute;top:12px;left:0;z-index:2;padding:5px 10px;border-radius:0 6px 6px 0;transform:rotate(-3deg);transform-origin:left center;background:#265c81;color:#8fc4ec;font-size:12px;font-weight:700;text-transform:uppercase;font-family:var(--font)}
.nav-menu-btn{display:none;align-items:center;justify-content:center;width:34px;height:34px;flex-shrink:0;border:none;background:transparent;color:rgba(255,255,255,0.7);cursor:pointer;border-radius:9px;transition:background .15s,color .15s}
.nav-menu-btn:hover{background:rgba(255,255,255,0.06);color:#fff}
.nav-menu-btn svg{width:19px;height:19px}
.nav-links{display:flex;align-items:center}
.nav-link{padding:8px 16px;border-radius:10px;font-size:14.5px;font-weight:400;color:rgba(255,255,255,0.34);transition:color .15s;background:transparent;cursor:pointer;border:none;font-family:var(--font)}
.nav-link:hover{color:rgba(255,255,255,0.7)}
.nav-link.active{font-weight:500;color:#fff}
.nav-right{display:flex;align-items:center;gap:10px}
.wallet{display:flex;align-items:center;gap:8px;padding:8px 14px;border:1px solid rgba(255,255,255,0.08);border-radius:11px;background:rgba(255,255,255,0.03);transition:border-color .18s}
.wallet:hover{border-color:rgba(255,255,255,0.16)}
/* Logged-out replacement for the wallet: scrap icon + LOG IN on one warm red chip. */
.nav-login-btn{display:flex;align-items:center;gap:8px;padding:8px 14px;border:none;border-radius:11px;background:#7b271a;color:#ebb3aa;font-size:13.5px;font-weight:700;letter-spacing:0.02em;font-family:var(--font);cursor:pointer;transition:filter .15s,transform .15s}
.nav-login-btn:hover{filter:brightness(1.15)}
.nav-login-btn .scrap-icon{width:18px;height:18px}


/* Its own backdrop/panel rather than reusing .crate-modal-backdrop — that one's built for a
   1100px-wide browse grid, and a login form riding on those same base rules is what made it
   read as an oversized, generic box. This one is sized and paced for exactly what it holds. */
.auth-modal-backdrop{position:fixed;inset:0;z-index:210;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0);backdrop-filter:blur(0px);-webkit-backdrop-filter:blur(0px);opacity:0;pointer-events:none;transition:opacity .3s ease,background .3s ease,backdrop-filter .3s ease}
.auth-modal-backdrop.open{opacity:1;pointer-events:auto;background:rgba(4,4,6,0.72);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.auth-modal{position:relative;width:min(300px,88vw);padding:34px 24px 24px;background:rgba(13,13,16,0.98);border:1px solid rgba(255,255,255,0.09);border-radius:18px;box-shadow:0 24px 64px rgba(0,0,0,0.55);overflow:hidden;transform:translateY(14px) scale(.96);opacity:0;transition:transform .32s cubic-bezier(.16,1,.3,1),opacity .28s ease}
.auth-modal-backdrop.open .auth-modal{transform:translateY(0) scale(1);opacity:1}
/* Soft radial glow bleeding down from the top edge, purely decorative — echoes the item-card
   rarity glow used elsewhere so the modal doesn't feel like a bare system dialog dropped in. */
.auth-modal-glow{position:absolute;top:-90px;left:50%;transform:translateX(-50%);width:260px;height:180px;background:radial-gradient(ellipse at center, rgba(120,205,145,0.22) 0%, rgba(120,205,145,0) 70%);pointer-events:none}
.auth-modal-close{position:absolute;top:12px;right:12px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:9px;border:none;background:rgba(255,255,255,0.04);color:rgba(255,255,255,0.45);cursor:pointer;transition:background .15s,color .15s}
.auth-modal-close:hover{background:rgba(255,255,255,0.08);color:rgba(255,255,255,0.85)}
.auth-modal-close svg{width:15px;height:15px}
.auth-modal-icon{position:relative;display:block;width:34px;height:34px;object-fit:contain;margin:0 auto 14px;filter:drop-shadow(0 0 14px rgba(120,205,145,0.45))}
.auth-modal-tabs{position:relative;display:flex;margin-bottom:22px;border-bottom:1px solid rgba(255,255,255,0.08)}
.auth-modal-tab{flex:1;padding:0 0 12px;border:none;background:none;color:rgba(255,255,255,0.45);font-size:13.5px;font-weight:700;font-family:var(--font);cursor:pointer;transition:color .18s}
.auth-modal-tab.active{color:#fff}
/* A single absolutely-positioned bar slides between tabs instead of each tab drawing its own
   underline — one element animating its transform reads as a deliberate motion, whereas two
   independent underlines swapping opacity just looks like a flicker. */
.auth-modal-tab-indicator{position:absolute;bottom:-1px;left:0;width:50%;height:2px;background:var(--green);border-radius:2px;transition:transform .28s cubic-bezier(.65,0,.35,1)}
.auth-modal-tabs:has(.auth-modal-tab[data-auth-tab="signup"].active) .auth-modal-tab-indicator{transform:translateX(100%)}
.auth-modal-form{position:relative;display:flex;flex-direction:column;gap:14px}
.auth-modal-field{display:flex;flex-direction:column;gap:6px}
.auth-modal-field label{font-size:11px;font-weight:700;letter-spacing:.06em;color:rgba(255,255,255,0.45);text-transform:uppercase}
.auth-modal-field input{padding:11px 13px;border-radius:10px;border:1px solid rgba(255,255,255,0.09);background:rgba(255,255,255,0.025);color:#fff;font-size:14px;font-family:var(--font);outline:none;transition:border-color .18s,background .18s}
.auth-modal-field input:focus{border-color:rgba(120,205,145,0.5);background:rgba(255,255,255,0.04)}
.auth-modal-error{display:none;padding:10px 12px;border-radius:9px;background:rgba(220,90,80,0.12);border:1px solid rgba(220,90,80,0.3);color:rgb(235,140,130);font-size:12.5px;font-weight:600;line-height:1.4;animation:authErrorIn .22s cubic-bezier(.16,1,.3,1) both}
.auth-modal-error.visible{display:block}
@keyframes authErrorIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
.auth-modal-submit{margin-top:4px;padding:12.5px;border-radius:11px;border:none;background:var(--green);color:#0c1a12;font-size:14px;font-weight:800;font-family:var(--font);letter-spacing:.02em;cursor:pointer;transition:filter .16s,transform .1s}
.auth-modal-submit:hover{filter:brightness(1.1)}
.auth-modal-submit:active{transform:scale(.98)}
.auth-modal-submit:disabled{opacity:.55;cursor:default;filter:none;transform:none}
/* The icon is the tallest thing in the wallet, so its height drives the pill's height. Scaling
   it up visually with a transform instead of a bigger box keeps the layout box at 18px — the
   art renders larger without the wallet growing or anything shifting. */
.scrap-icon{width:18px;height:18px;flex-shrink:0;object-fit:contain;transform:scale(1.111)}
.wallet-amt{font-size:13.5px;font-weight:700;color:#fff;font-variant-numeric:tabular-nums;letter-spacing:0.01em}

#app{position:relative;z-index:2}
.wrap{max-width:1180px;margin:0 auto;padding:104px 32px 70px}
@keyframes fadeUp{from{opacity:0;transform:translate3d(0,14px,0)}to{opacity:1;transform:translate3d(0,0,0)}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.fade{animation:fadeUp .55s cubic-bezier(.22,1,.36,1) both}

.page{display:none}
.page.active{display:block}
.wrap.page-transition{animation:pageOut .18s cubic-bezier(.4,0,1,1) both}
@keyframes pageOut{from{opacity:1;transform:translate3d(0,0,0)}to{opacity:0;transform:translate3d(0,-10px,0)}}

.searchbar{position:relative;max-width:400px;margin:36px auto 0}
.searchbar input{width:100%;padding:14px 18px 14px 46px;border-radius:999px;border:1px solid rgba(255,255,255,0.09);background:rgba(255,255,255,0.03);color:#fff;font-size:14px;font-family:var(--font);outline:none;transition:border-color .18s,box-shadow .18s,background .18s}
.searchbar input::placeholder{color:rgba(255,255,255,0.3)}
.searchbar input:focus{border-color:rgba(255,255,255,0.35);box-shadow:0 0 0 4px rgba(255,255,255,0.08);background:rgba(255,255,255,0.05)}
.search-ico{position:absolute;left:17px;top:50%;transform:translateY(-50%);width:17px;height:17px;color:rgba(255,255,255,0.32);transition:color .18s;pointer-events:none}
.searchbar:focus-within .search-ico{color:rgba(255,255,255,0.75)}

.filterbar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:28px;flex-wrap:wrap}
.filter-chips{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.chip{display:flex;align-items:center;gap:7px;padding:9px 15px;border-radius:11px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.5);font-size:13px;font-weight:500;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap}
.chip svg,.chip i{width:15px;height:15px;flex-shrink:0;color:rgba(255,255,255,0.4);font-size:14px;display:flex;align-items:center;justify-content:center;transition:color .16s}
.chip:hover{color:rgba(255,255,255,0.85);border-color:rgba(255,255,255,0.16);background:rgba(255,255,255,0.05)}
.chip.active{color:#fff;border-color:rgba(255,255,255,0.24);background:rgba(255,255,255,0.11)}
.chip.active svg,.chip.active i{color:rgb(120,205,145)}
.chip-icon-only{padding:9px 11px}
.chip-icon-only svg{width:18px;height:18px}
.chip-icon-only.active svg{color:rgb(255,165,80)}

.dropdown{position:relative;flex-shrink:0}
.dd-btn{display:flex;align-items:center;gap:9px;padding:9px 15px;border-radius:11px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.8);font-size:13px;font-weight:500;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap}
.dd-btn:hover{border-color:rgba(255,255,255,0.16);background:rgba(255,255,255,0.05)}
.dd-icon-slot{display:flex;align-items:center;justify-content:center;flex-shrink:0}
.dd-icon-slot svg{width:15px;height:15px;color:rgba(255,255,255,0.55)}
.dd-icon-slot i{font-size:14px;color:rgba(255,255,255,0.55)}
.dd-chev{width:14px;height:14px;opacity:.55;transition:transform .2s;flex-shrink:0}
.dropdown.open .dd-btn{border-color:rgba(255,255,255,0.2);background:rgba(255,255,255,0.06)}
.dropdown.open .dd-chev{transform:rotate(180deg)}
.dd-menu{position:absolute;top:calc(100% + 6px);right:0;min-width:200px;background:rgba(16,16,16,0.98);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border:1px solid rgba(255,255,255,0.1);border-radius:13px;padding:6px;box-shadow:0 16px 48px rgba(0,0,0,0.6);z-index:60;opacity:0;pointer-events:none;transform:translateY(-8px) scale(.98);transform-origin:top right;transition:opacity .2s cubic-bezier(.22,1,.36,1),transform .2s cubic-bezier(.22,1,.36,1)}
.dropdown.open .dd-menu{opacity:1;pointer-events:auto;transform:translateY(0) scale(1)}
.dd-item{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:9px;font-size:13px;font-weight:500;color:rgba(255,255,255,0.55);cursor:pointer;transition:background .12s,color .12s;border:1px solid transparent}
.dd-item svg,.dd-item i{width:15px;height:15px;display:flex;align-items:center;justify-content:center;font-size:14px;flex-shrink:0;opacity:.65;color:rgba(255,255,255,0.7)}
.dd-item:hover{background:rgba(255,255,255,0.05);color:#fff}
.dd-item.active{background:rgba(255,255,255,0.1);color:#fff;border-color:rgba(255,255,255,0.16)}
.dd-item.active svg{opacity:1;color:#fff}

.placeholder{margin-top:18px;padding:60px 32px;border:1px dashed rgba(255,255,255,0.1);border-radius:18px;background:rgba(255,255,255,0.014);text-align:center}
.placeholder h3{font-size:16px;font-weight:600;color:rgba(255,255,255,0.5);margin-bottom:6px}
.placeholder p{font-size:13px;color:rgba(255,255,255,0.28)}

#loadMoreSentinel{height:1px}
.load-more-btn{display:block;margin:24px auto 0;padding:11px 26px;border-radius:11px;border:1px solid rgba(255,255,255,0.1);background:rgba(255,255,255,0.04);color:rgba(255,255,255,0.75);font-size:13.5px;font-weight:600;font-family:var(--font);cursor:pointer;transition:all .16s}
.load-more-btn:hover{background:rgba(255,255,255,0.08);border-color:rgba(255,255,255,0.2);color:#fff}

.case-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-top:18px}
.case-card{--glow:120,205,145;position:relative;display:flex;flex-direction:column;align-items:center;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.08);border-radius:12px;padding:8px 8px 24px;cursor:pointer;overflow:hidden;transition:transform .6s cubic-bezier(.16,1,.3,1),border-color .3s ease,background .3s ease;animation:fadeIn .4s ease both}
.case-card:hover{transform:translateY(-3px);border-color:rgba(255,255,255,0.18);background:rgba(255,255,255,0.05);z-index:2}
.case-art{width:100%;aspect-ratio:1/1;display:flex;align-items:center;justify-content:center;position:relative;top:-8px}
.case-glow{position:absolute;left:50%;top:50%;width:115%;height:115%;transform:translate(-50%,-50%);background:radial-gradient(circle, rgba(var(--glow),0.2) 0%, rgba(var(--glow),0.1) 45%, rgba(var(--glow),0) 72%);opacity:0;transition:opacity .5s ease;pointer-events:none;z-index:0}
.case-card:hover .case-glow{opacity:1}
.case-art img{position:relative;z-index:1;width:80%;height:80%;object-fit:contain}
.case-fav{position:absolute;top:6px;right:6px;width:28px;height:28px;background:none;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:0;transition:opacity .15s;z-index:5}
.case-card:hover .case-fav{opacity:1}
.case-fav.active{opacity:1}
.case-fav svg{width:22px;height:22px;color:rgba(255,255,255,0.55);transition:color .15s;filter:drop-shadow(0 1px 2px rgba(0,0,0,0.8))}
.case-fav:hover svg{color:rgba(255,255,255,0.9)}
.case-fav.active svg{color:rgb(255,165,80);fill:rgb(255,165,80)}
.case-name{font-size:15.5px;font-weight:600;color:rgba(255,255,255,0.82);margin-top:8px;position:relative;top:-18px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center;width:100%}
.case-slider{width:65%;margin-left:auto;margin-right:auto;height:4px;display:flex;gap:3px;margin-top:8px;position:relative;top:-15px}
.case-slider .seg{flex:1;height:100%;border-radius:3px;background:rgba(255,255,255,0.12)}
.case-slider .seg.lit:nth-child(1){background:rgb(120,205,145)}
.case-slider .seg.lit:nth-child(2){background:rgb(240,160,55)}
.case-slider .seg.lit:nth-child(3){background:rgb(235,80,70)}
.case-slider .pin{position:absolute;top:-2.5px;width:3px;height:9px;border-radius:2px;background:#fff;transform:translateX(-50%)}
.case-price{display:flex;align-items:center;justify-content:center;gap:6px;width:65%;margin:auto auto 0;top:4px;position:relative;font-size:13.5px;font-weight:600;color:rgba(255,255,255,0.6);background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.08);border-radius:9px;padding:6px 12px}
.case-price img{width:18px;height:18px;object-fit:contain}
@media (max-width:1300px){.case-grid{grid-template-columns:repeat(4,1fr)}}
@media (max-width:700px){.case-grid{grid-template-columns:repeat(2,1fr)}}

.case-detail-bar{display:grid;grid-template-columns:1fr auto 1fr;align-items:start;margin-top:32px}
.case-detail-back,.case-detail-demo{display:flex;align-items:center;gap:6px;padding:8px 14px;border-radius:9px;font-size:12.5px;font-weight:500;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap;flex-shrink:0;margin-top:70px}
.case-detail-back{justify-self:end;margin-right:211px;padding-left:0;border:none;background:none;color:rgba(255,255,255,0.6);font-size:14.5px}
.case-detail-back:hover{color:#fff}
.case-detail-demo{justify-self:start;margin-left:246px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.6)}
.case-detail-demo:hover{color:#fff;border-color:rgba(255,255,255,0.18);background:rgba(255,255,255,0.06)}
.case-detail-demo:disabled{opacity:.45;cursor:default;pointer-events:none}
.case-detail-back svg{width:16px;height:16px;flex-shrink:0}
.case-detail-demo svg{width:13px;height:13px;flex-shrink:0}
.case-detail-heading{grid-column:2;display:flex;flex-direction:column;align-items:center;gap:6px}
.case-detail-art{width:76px;height:76px;display:flex;align-items:center;justify-content:center}
.case-detail-art img{width:100%;height:100%;object-fit:contain;filter:drop-shadow(0 8px 24px rgba(0,0,0,0.5))}
.case-detail-name{font-size:17px;font-weight:700;color:#fff;letter-spacing:-0.01em}

.spin-wrap{position:relative;max-width:820px;margin:34px auto 0}
.spin-pointer{position:absolute;top:-2px;left:50%;transform:translateX(-50%);z-index:5;filter:drop-shadow(0 2px 6px rgba(0,0,0,0.6))}
.spin-pointer img{width:64px;height:64px;display:block;object-fit:contain}
.spin-viewport{position:relative;height:156px;overflow:hidden;border-radius:12px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.02)}
.spin-viewport::before,.spin-viewport::after{content:"";position:absolute;top:0;bottom:0;width:70px;z-index:3;pointer-events:none}
.spin-viewport::before{left:0;background:linear-gradient(90deg,#000 0%,transparent 100%)}
.spin-viewport::after{right:0;background:linear-gradient(270deg,#000 0%,transparent 100%)}
.spin-viewport::marker{content:none}
.spin-track{position:absolute;top:0;left:0;height:100%;display:flex;align-items:center;gap:3px;padding:0 8px;will-change:transform;transform:translateZ(0);backface-visibility:hidden}
.spin-slot{flex-shrink:0;width:132px;height:132px;display:flex;align-items:center;justify-content:center;position:relative;--rarity:120,205,145}
.spin-slot .slot-box{position:absolute;inset:0;border-radius:9px;background:radial-gradient(ellipse 100% 145% at 50% 0%,rgba(var(--rarity),0.35) 0%,rgba(var(--rarity),0.03) 75%,rgba(255,255,255,0.03) 100%);background-clip:padding-box;border:1px solid rgba(255,255,255,0.07);overflow:hidden;pointer-events:none;z-index:0}
.spin-slot img{width:112px;height:112px;object-fit:contain;position:relative;z-index:1}
/* Duds read as a bit dull on the reel — mild desaturation/dim, and the slot's tint is already
   forced to flat grey via --rarity in slotHTML, so no rarity glow either. Kept subtle: fully
   grayscaling it out read as way too dead. */
.spin-slot.dud img{filter:grayscale(.45) brightness(.88);opacity:.92}
.spin-slot .slot-placeholder{width:112px;height:112px;border-radius:6px;background:rgba(255,255,255,0.08)}
.spin-slot .slot-price{position:absolute;left:0;right:0;bottom:10px;z-index:2;display:flex;align-items:center;justify-content:center;gap:6px;font-size:19px;font-weight:800;color:#fff;text-shadow:0 1px 4px rgba(0,0,0,0.9);opacity:0;transform:translateY(14px);transition:opacity .55s cubic-bezier(.22,1,.36,1),transform .55s cubic-bezier(.22,1,.36,1)}
.spin-slot .slot-price img{width:25px;height:25px;object-fit:contain}
.spin-track.settled .spin-slot{transition:opacity .3s ease,filter .3s ease,transform .3s ease}
.spin-track.settled .spin-slot:not(.landed){opacity:.35;filter:grayscale(.4);transform:scale(.97)}
.spin-slot.landed .slot-price{opacity:1;transform:translateY(0)}

/* Multi-spin (qty 2-5): ONE wide viewport (same outer chrome as the single-spin .spin-viewport
   — one arrow pair at the edges, one center line through the middle) containing N narrower
   columns side by side, one per unit. Unlike the single-spin reel (items slide horizontally
   past a fixed pointer), each column here scrolls its items downward past a fixed horizontal
   center line — same slot-machine idea, rotated 90°. Each column's track reuses .spin-slot as
   the individual item card (built via slotHTML, same as single-spin) stacked in a vertical
   flex column instead of the horizontal one the single-spin track uses. */
/* Same overall footprint as .spin-wrap/.spin-viewport (156px tall) and the same .spin-slot
   card size (132px, 112px art) as the single-spin reel — switching qty 1 <-> 2-5 must not
   resize the wheel or shrink the item art, only change what's scrolling inside it. */
.multi-spin-wrap{position:relative;max-width:820px;margin:34px auto 0}
/* Same /assets/img/arrow.png the single-spin pointer uses (points down by default), rotated to point
   inward from each side instead of down. */
.multi-spin-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:4;filter:drop-shadow(0 2px 6px rgba(0,0,0,0.6))}
.multi-spin-arrow img{width:48px;height:48px;display:block;object-fit:contain}
.multi-spin-arrow.left{left:10px}
.multi-spin-arrow.left img{transform:rotate(-90deg)}
.multi-spin-arrow.right{right:6px}
.multi-spin-arrow.right img{transform:rotate(90deg)}
/* No top/bottom fade overlays — just the plain background tint (same rgba(255,255,255,0.02)
   wash the single-spin .spin-viewport uses) visible across the whole box. */
.multi-spin-viewport{position:relative;height:156px;overflow:hidden;border-radius:12px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.02);display:flex;padding:0 30px}
/* Each unit's own slice of the shared viewport — a plain overflow:hidden window its column
   scrolls inside of. */
.multi-spin-unit{position:relative;flex:1;height:100%;overflow:hidden}
.multi-spin-unit .spin-track{position:absolute;top:0;left:0;width:100%;height:auto;flex-direction:column;align-items:center;gap:3px;padding:8px 0;display:flex;z-index:1}
/* One line segment per column (not one line spanning the whole wheel) — same fixed vertical
   offset on every column so, side by side, they read as one continuous horizontal line across
   the wheel. Each segment fades in/out via its own gradient rather than being a solid bar. */
.multi-spin-unit .slot-line{position:absolute;left:0;top:50%;transform:translateY(-50%);width:100%;height:1px;background:linear-gradient(90deg,transparent,rgb(205,65,43),transparent);z-index:0;pointer-events:none}
/* No boxed card here (the single-spin reel's .slot-box is a bordered rounded-rect) — a
   rarity-tinted drop-shadow glow on the item image itself instead. */
.multi-spin-unit .spin-slot .slot-box{display:none}
.multi-spin-unit .spin-slot>img{filter:drop-shadow(0 0 6px rgba(var(--rarity),0.5)) drop-shadow(0 0 12px rgba(var(--rarity),0.25));position:relative;z-index:1}
/* Duds don't glow on the 2-5 multi-spin lanes — a dud with a halo reads like something worth
   landing on. Multi-spin only; the single-spin reel's dud treatment is handled separately. */
.multi-spin-unit .spin-slot.dud>img{filter:none}
/* Columns get tight at qty 4-5 — scale the card/art down slightly so neighboring items don't
   crowd into each other, but not so much it reads as tiny. */
.multi-spin-wrap[data-qty="4"] .spin-slot,.multi-spin-wrap[data-qty="5"] .spin-slot{width:116px;height:116px}
/* ">img"/">.slot-placeholder" (direct child only) so this doesn't also catch the 25px scrap
   icon nested inside .slot-price — that was blowing it up and squeezing it invisible. */
.multi-spin-wrap[data-qty="4"] .spin-slot>img,.multi-spin-wrap[data-qty="5"] .spin-slot>img,
.multi-spin-wrap[data-qty="4"] .spin-slot>.slot-placeholder,.multi-spin-wrap[data-qty="5"] .spin-slot>.slot-placeholder{width:98px;height:98px}

.spin-controls{max-width:820px;margin:14px auto 0;display:flex;align-items:flex-start;gap:6px}
.open-btn{flex-shrink:0;display:flex;align-items:center;justify-content:center;gap:8px;padding:18px 16px;border-radius:11px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.5);font-size:13.5px;font-weight:700;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap}
.open-btn:hover{color:rgba(255,255,255,0.85);border-color:rgba(255,255,255,0.16);background:rgba(255,255,255,0.05)}
.open-btn:disabled{opacity:.45;cursor:default;pointer-events:none}
.open-btn-label{color:rgba(255,255,255,0.85);letter-spacing:.01em}
/* Price matches the label's brightness — without this it inherits the button's dimmer base. */
#openCaseCost{color:rgba(255,255,255,0.85)}
.open-btn img{width:16px;height:16px;object-fit:contain}
.qty-group{display:flex;align-items:center;gap:4px;flex-shrink:0;margin-left:2px}
.qty-btn{width:32px;height:36px;border-radius:9px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.5);font-size:12.5px;font-weight:600;font-family:var(--font);cursor:pointer;transition:all .16s}
.qty-btn:hover{color:rgba(255,255,255,0.85);border-color:rgba(255,255,255,0.16);background:rgba(255,255,255,0.05)}
.qty-btn.active{color:#fff;border-color:rgba(255,255,255,0.24);background:rgba(255,255,255,0.11)}
.qty-btn:disabled{opacity:.35;cursor:default;pointer-events:none}
.qty-group.spinning .qty-btn{opacity:.4;pointer-events:none;transition:opacity .2s ease}
.spin-controls-right{display:flex;align-items:center;gap:8px;flex-shrink:0;margin-left:auto}
.icon-btn{width:42px;height:42px;display:flex;align-items:center;justify-content:center;border-radius:10px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.5);cursor:pointer;transition:all .16s}
.icon-btn:hover{color:rgba(255,255,255,0.85);border-color:rgba(255,255,255,0.16);background:rgba(255,255,255,0.05)}
.icon-btn svg{width:17px;height:17px}
.icon-btn.active{color:#fff;border-color:rgba(255,255,255,0.24);background:rgba(255,255,255,0.11)}
.icon-btn.muted{color:rgb(230,70,50);border-color:rgba(230,70,50,0.35);background:rgba(230,70,50,0.1)}
.icon-btn-wrap{position:relative}
.icon-tooltip{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%) translateY(4px);padding:6px 10px;border-radius:7px;background:rgba(14,14,20,0.98);border:1px solid rgba(255,255,255,0.1);color:rgba(255,255,255,0.85);font-size:12px;font-weight:500;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .16s ease,transform .16s ease;z-index:20}
.icon-btn-wrap:hover .icon-tooltip{opacity:1;transform:translateX(-50%) translateY(0)}

.unboxed-section{max-width:820px;margin:25px auto 0;opacity:0;transform:translateY(-8px);animation:unboxedFadeIn .5s cubic-bezier(.22,1,.36,1) both}
@keyframes unboxedFadeIn{to{opacity:1;transform:translateY(0)}}
.unboxed-header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}
.unboxed-heading{font-size:14px;font-weight:700;color:rgb(230,70,50);letter-spacing:.03em;text-transform:uppercase;margin-bottom:4px}
.unboxed-sub{font-size:13px;color:rgba(255,255,255,0.5)}
.unboxed-last-spin{display:flex;align-items:center;gap:6px;padding:8px 14px;border-radius:9px;background:rgba(120,205,145,0.15);color:rgb(150,220,170);font-size:12px;font-weight:700;letter-spacing:.02em;white-space:nowrap}
.unboxed-last-spin img{width:14px;height:14px;object-fit:contain}
.unboxed-box{margin-top:14px;padding:16px;border-radius:13px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03)}
.unboxed-grid{display:flex;flex-wrap:wrap;gap:10px}
.unboxed-card{--rarity:120,205,145;position:relative;display:flex;flex-direction:column;align-items:center;width:100px;padding:10px 6px 12px;border-radius:11px;border:1px solid rgba(255,255,255,0.08);background:radial-gradient(ellipse 100% 110% at 50% 0%,rgba(var(--rarity),0.35) 0%,rgba(var(--rarity),0.03) 75%,rgba(255,255,255,0.03) 100%);background-clip:padding-box;overflow:hidden;opacity:0;transform:translateY(-10px);animation:unboxedCardIn .45s cubic-bezier(.22,1,.36,1) both}
@keyframes unboxedCardIn{to{opacity:1;transform:translateY(0)}}
.unboxed-card img{width:52px;height:52px;object-fit:contain;margin:8px 0 8px}
.unboxed-card-name{font-size:11.5px;font-weight:700;color:rgb(var(--rarity));text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;margin-bottom:4px}
.unboxed-card-price{display:flex;align-items:center;gap:4px;font-size:11.5px;font-weight:600;color:rgba(255,255,255,0.8)}
.unboxed-card-price img{width:12px;height:12px;margin:0}

.battles-promo{display:flex;align-items:center;gap:16px;max-width:820px;width:100%;margin:25px auto 0;padding:18px 20px;border-radius:13px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);cursor:pointer;transition:all .16s;text-align:left;font-family:var(--font)}
.battles-promo:hover{border-color:rgba(255,255,255,0.16);background:rgba(255,255,255,0.05)}
.battles-promo img{width:50px;height:50px;object-fit:contain;flex-shrink:0}
.battles-promo-text strong{display:block;font-size:16px;font-weight:700;color:#fff;margin-bottom:3px}
.battles-promo-text p{font-size:13.5px;color:rgba(255,255,255,0.55);line-height:1.4}
.battles-promo-text p b{color:rgba(255,255,255,0.85);font-weight:700}

.case-items-section{max-width:820px;margin:32px auto 0}
.case-items-heading{font-size:14px;font-weight:700;color:rgb(230,70,50);letter-spacing:.03em;text-transform:uppercase;margin-bottom:14px}
.case-items-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:12px}
.case-item-card{--rarity:120,205,145;position:relative;display:flex;flex-direction:column;align-items:center;padding:14px 10px 16px;border-radius:12px;border:1px solid rgba(255,255,255,0.08);background:radial-gradient(ellipse 100% 110% at 50% 0%,rgba(var(--rarity),0.35) 0%,rgba(var(--rarity),0.03) 75%,rgba(255,255,255,0.03) 100%);background-clip:padding-box;overflow:hidden}
.case-item-chance-wrap{position:absolute;top:10px;right:12px;height:14px;min-width:30px;overflow:visible}
.case-item-chance,.case-item-range{position:absolute;top:0;right:0;font-size:11px;font-weight:700;color:rgba(255,255,255,0.75);white-space:nowrap;transition:transform .45s cubic-bezier(.22,1,.36,1),opacity .45s cubic-bezier(.22,1,.36,1)}
.case-item-range{transform:translateY(100%);opacity:0}
.case-item-card:hover .case-item-chance{transform:translateY(-100%);opacity:0}
.case-item-card:hover .case-item-range{transform:translateY(0);opacity:1}
.case-item-card img{width:84px;height:84px;object-fit:contain;margin:14px 0 12px}
.case-item-name{font-size:13.5px;font-weight:700;color:rgb(var(--rarity));text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%;margin-bottom:6px}
.case-item-price{display:flex;align-items:center;gap:5px;font-size:13px;font-weight:600;color:rgba(255,255,255,0.8)}
.case-item-price img{width:14px;height:14px;object-fit:contain;margin:0}
@media (max-width:1000px){.case-items-grid{grid-template-columns:repeat(3,1fr)}}
@media (max-width:700px){.case-items-grid{grid-template-columns:repeat(2,1fr)}}

.live-wins-section{max-width:1180px;margin:40px auto 0;transition:none}
.live-wins-heading{font-size:14px;font-weight:700;color:#fff;letter-spacing:.03em;text-transform:uppercase;margin-bottom:14px}
.live-wins-track{display:flex;gap:10px;overflow-x:auto;overflow-y:hidden;padding-bottom:4px;scrollbar-width:none}
.live-wins-track::-webkit-scrollbar{display:none}
.live-win-card{--rarity:120,205,145;flex-shrink:0;width:175px;height:64px;position:relative;padding:0;border-radius:11px;border:1px solid rgba(255,255,255,0.08);background:linear-gradient(90deg,rgba(var(--rarity),0.28) 0%,rgba(var(--rarity),0.04) 60%,rgba(255,255,255,0.03) 100%);background-clip:padding-box;overflow:hidden}
/* Two faces stacked in the card: item + price + player at rest, crate + name + source on hover. */
.live-win-face{position:absolute;inset:0;display:flex;align-items:center;gap:10px;padding:8px 12px;transition:opacity .18s ease}
.live-win-back{opacity:0}
.live-win-card:hover .live-win-front{opacity:0}
.live-win-card:hover .live-win-back{opacity:1}
.live-win-card img{width:42px;height:42px;object-fit:contain;flex-shrink:0}
.live-win-info{display:flex;flex-direction:column;align-items:flex-start;min-width:0}
.live-win-price{display:flex;align-items:center;gap:5px;font-size:13px;font-weight:700;color:#fff}
.live-win-price img{width:14px;height:14px;object-fit:contain;margin:0}
.live-win-player,.live-win-source{font-size:11.5px;font-weight:600;color:rgba(255,255,255,0.62);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;margin-top:3px}
.live-win-source{color:rgba(255,255,255,0.85)}
.live-win-casename{font-size:12.5px;font-weight:800;color:#7ED957;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.live-win-game{font-size:12.5px;font-weight:800;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}

@media (max-width:768px){
  .nav-menu-btn{display:flex}
  /* Same four .nav-link buttons as desktop (router.js wires their click handlers generically by
     class, not by container), just relocated into a panel that drops down below the pill instead
     of sitting inline — there isn't room for all four labels next to the brand and wallet once
     the nav-inner pill itself has to shrink to fit a phone-width screen. */
  .nav-links{position:absolute;top:calc(100% + 8px);left:0;right:0;display:none;flex-direction:column;align-items:stretch;gap:2px;padding:8px;background:rgba(10,10,10,0.96);backdrop-filter:blur(32px);-webkit-backdrop-filter:blur(32px);border:1px solid rgba(255,255,255,0.07);border-radius:16px;box-shadow:0 12px 32px rgba(0,0,0,0.5)}
  .nav-inner.menu-open .nav-links{display:flex}
  .nav-link{text-align:left;padding:11px 14px;border-radius:10px}
  .nav-link.active{background:rgba(255,255,255,0.06)}
  .wrap{padding:88px 18px 50px}
}
.toast-layer{position:fixed;right:20px;bottom:20px;z-index:200;display:flex;flex-direction:column-reverse;gap:10px;pointer-events:none;overflow:visible}
.toast{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:11px;border:1px solid rgba(255,255,255,0.12);background:rgba(24,24,24,0.98);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);box-shadow:0 12px 32px rgba(0,0,0,0.5);color:rgba(255,255,255,0.85);font-size:13.5px;font-weight:500;max-width:320px;animation:toastIn .5s cubic-bezier(.22,1,.36,1) both}
.toast.leaving{animation:toastOut .45s cubic-bezier(.5,0,.75,0) both}
.toast-icon{width:20px;height:20px;flex-shrink:0;color:rgb(108,140,168)}
.toast-error .toast-icon{color:rgb(235,80,70)}
.toast-success .toast-icon{color:rgb(120,205,145)}
.toast-titled{align-items:flex-start}
.toast-titled .toast-icon{margin-top:1px}
.toast-body{display:flex;flex-direction:column;gap:2px}
.toast-title{font-weight:700;color:rgba(255,255,255,0.95)}
.toast-message{color:rgba(255,255,255,0.7);font-weight:500}
@keyframes toastIn{from{opacity:0;transform:translateX(420px)}to{opacity:1;transform:translateX(0)}}
@keyframes toastOut{from{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(420px)}}

/* ══ Scrap Upgrader ══ */
/* Breaks out of .wrap's 1180px cap — the right column needs more room than that leaves,
   otherwise its buttons/search bar overlap at any normal window width. Fixed 480px/750px on
   PC/desktop — do not change these; a prior attempt at making them fluid via minmax()/fr
   ended up shrinking the whole layout (crate included) even at ordinary desktop widths well
   above 1230px, which was never supposed to happen. The narrower-viewport media query below
   (max-width:1300px) is where this grid actually needs to flex — it stays a hard fixed pair
   above that width, matching PC exactly as it always has. */
.upgrader-layout{display:grid;grid-template-columns:480px 750px;gap:16px;align-items:start;margin-top:44px;width:max-content;margin-left:auto;margin-right:auto;position:relative;left:50%;transform:translateX(-50%)}
.upgrader-left{background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.08);border-radius:14px;padding:40px 30px;display:flex;flex-direction:column;align-items:center;text-align:center;min-height:640px;overflow:hidden;position:relative}
.upgrader-play-label{font-size:13px;font-weight:700;letter-spacing:.05em;color:rgba(255,255,255,0.5);text-transform:uppercase}
.upgrader-play-amt{display:flex;align-items:center;gap:10px;font-size:30px;font-weight:800;color:#fff;margin-top:10px}
.upgrader-play-amt img{width:38px;height:38px;object-fit:contain}
.upgrader-preview{margin-top:65px;display:flex;flex-direction:column;align-items:center;gap:7px;height:118px;justify-content:center}
.upgrader-no-items{font-size:22px;font-weight:700;color:#fff}
.upgrader-hint{font-size:15.5px;color:rgba(255,255,255,0.45)}
.upgrader-roll-mult{font-size:18px;font-weight:700;color:#8CC2E7}
.upgrader-roll-amt{display:flex;align-items:center;gap:10px;font-size:30px;font-weight:800;color:#fff}
.upgrader-roll-amt img{width:38px;height:38px;object-fit:contain}
.upgrader-roll-text{font-size:15px;color:rgba(255,255,255,0.7);margin-top:2px}
.upgrader-roll-chance{font-size:13.5px;color:rgba(255,255,255,0.45)}
/* Deliberately fixed at 500px — WIDER than .upgrader-left's 420px content box on purpose: the
   crate art is meant to bleed across the card's side padding and clip at the card's edges
   (.upgrader-left has overflow:hidden), rendering ~480px wide. A min(500px,100%) "safety cap"
   here once shrank it to 420px and visibly shrank the crate on PC — do not re-add one. */
.upgrader-crate-stack{position:relative;width:530px;top:50px;flex-shrink:0}
.upgrader-crate-img{display:block;width:100%;height:auto;object-fit:contain;position:relative;z-index:1;--shake-x:0px;--shake-y:0px}
@keyframes upgCrateShake{
  0%{transform:translate(0,0)}
  30%{transform:translate(var(--shake-x),var(--shake-y))}
  60%{transform:translate(calc(var(--shake-x) * -0.5),calc(var(--shake-y) * -0.5))}
  100%{transform:translate(0,0)}
}
/* Fixed-width, always-centered stage. Every card inside is absolutely positioned at its own
   slot, so the box never resizes as items are added or removed — which is what keeps the
   group visually centered on the crate even while outgoing cards are still fading. */
.upgrader-crate-items{position:absolute;left:50%;bottom:100px;transform:translateX(-50%);width:420px;height:110px;z-index:5;pointer-events:none}
/* will-change:transform promotes this to its own composited layer up front, so the two stacked
   drop-shadow() filters get rendered into that layer's bitmap ONCE — the infinite float
   animation below then just repositions/rescales the whole cached layer each frame instead of
   re-running both filters against the new transform every frame, which is real per-frame paint
   cost a JS rAF timing profile can't see (the float loop is pure CSS, no JS per-frame at all)
   but mobile GPUs feel heavily on an always-running animation like this one. */
.upgrader-crate-item-inner{--rarity:120,205,145;width:110px;height:110px;display:flex;align-items:center;justify-content:center;filter:drop-shadow(0 0 16px rgba(var(--rarity),0.65)) drop-shadow(0 0 32px rgba(var(--rarity),0.3));will-change:transform;animation-name:upgCrateItemFloat;animation-timing-function:ease-in-out;animation-iteration-count:infinite}
/* --slot-x is the card's resting offset from the row's center, set per-item from JS. Cards
   rest at translateX(--slot-x) and both enter and exit through the center (translateX(0))
   while scaled down and dropped into the crate — so they read as rising out of the crate on
   the way in and sinking back into it on the way out. Only transform/opacity ever animate,
   which keeps it smooth and interruptible mid-flight. */
.upgrader-crate-item{--slot-x:0px;position:absolute;left:50%;bottom:0;width:110px;margin-left:-55px;opacity:0;transform:translate(0,45px) scale(.7);transition:opacity .5s ease,transform .5s cubic-bezier(.22,1,.36,1)}
.upgrader-crate-item.in{opacity:1;transform:translate(var(--slot-x),0) scale(1)}
.upgrader-crate-item img{width:100%;height:100%;object-fit:contain}
/* Shrink item size once there are more than 2 on the crate, so 3-4 items stay inside
   the crate opening instead of spilling past its edges. Card width tracks the inner size so
   each card stays centered on its own slot (margin-left is half the width). */
.upgrader-crate-items[data-count="3"] .upgrader-crate-item{width:88px;margin-left:-44px}
.upgrader-crate-items[data-count="3"] .upgrader-crate-item-inner{width:88px;height:88px}
.upgrader-crate-items[data-count="4"] .upgrader-crate-item{width:72px;margin-left:-36px}
.upgrader-crate-items[data-count="4"] .upgrader-crate-item-inner{width:72px;height:72px}
@keyframes upgCrateItemFloat{
  0%,100%{transform:translateY(0) scale(1)}
  50%{transform:translateY(-10px) scale(1.06)}
}
.upgrader-crate-top{width:100%;height:auto;object-fit:contain;position:absolute;left:0;top:1.5%;transform:translateY(-500px);opacity:0;pointer-events:none;z-index:2;transform-origin:50% 50%}

/* Win-chance ring: a Vuetify-style v-progress-circular — two stacked SVG circles sharing
   the same center/radius. The gray track is always fully drawn; the colored fill circle
   uses the classic stroke-dasharray/stroke-dashoffset trick (dasharray = full circumference,
   dashoffset = circumference minus the filled fraction) so it visually reads as a partial
   ring proportional to win chance %. A CSS transition on stroke-dashoffset is what makes the
   fill animate smoothly on change instead of snapping. */
.upgrader-ring-wrap{position:absolute;left:50%;top:45%;transform:translate(-50%,-50%);width:78%;aspect-ratio:1/1;z-index:0;pointer-events:none;opacity:0;transition:opacity .5s ease}
.upgrader-ring-wrap.visible{opacity:1}
.upgrader-ring-svg{width:100%;height:100%;transform:rotate(-90deg)}
.upgrader-ring-track{fill:none;stroke:rgba(255,255,255,0.08);stroke-width:13}
.upgrader-ring-fill{fill:none;stroke:#A43422;stroke-width:13;stroke-linecap:butt;stroke-dasharray:565.487;stroke-dashoffset:565.487;transition:stroke-dashoffset .6s cubic-bezier(.22,1,.36,1)}
.upgrader-ring-arrow{position:absolute;top:4.5%;left:50%;transform:translate(-50%,-50%);width:17%;pointer-events:none}
/* Drop + bounce is driven by a real spring physics simulation in JS (see dropCrateTopSpring
   in upgrader.js), not CSS keyframes — see that function for the full explanation. This class
   only marks "the lid has become visible"; JS writes translateY directly every frame. */
.upgrader-crate-top.dropping{opacity:1}
/* Wobble phase: kicks in a beat after the drop lands — a decaying rotational wobble,
   like a coin settling flat, oscillating roughly ±5° and tapering to 0. */
@keyframes upgCrateTopWobble{
  0%{transform:translateY(0) rotate(0deg);opacity:1}
  10%{transform:translateY(0) rotate(5deg);opacity:1}
  24%{transform:translateY(0) rotate(-4.4deg);opacity:1}
  38%{transform:translateY(0) rotate(3.2deg);opacity:1}
  52%{transform:translateY(0) rotate(-2.2deg);opacity:1}
  66%{transform:translateY(0) rotate(1.3deg);opacity:1}
  80%{transform:translateY(0) rotate(-0.6deg);opacity:1}
  92%{transform:translateY(0) rotate(0.2deg);opacity:1}
  100%{transform:translateY(0) rotate(0deg);opacity:1}
}

/* Everything on the left card fades out once Upgrade is pressed, leaving just the crate. */
.upgrader-left.spinning .upgrader-play-label,
.upgrader-left.spinning .upgrader-play-amt,
.upgrader-left.spinning #upgPreview,
.upgrader-left.spinning .upgrader-actions{animation:upgFadeOut .35s ease forwards}
/* Reset: the play text and preview ease back in first, with the action buttons trailing so the
   card rebuilds itself top-down rather than snapping back all at once. */
.upgrader-left.resetting .upgrader-play-label,
.upgrader-left.resetting .upgrader-play-amt,
.upgrader-left.resetting #upgPreview{animation:upgFadeIn .33s ease both}
.upgrader-left.resetting .upgrader-actions{animation:upgFadeIn .33s ease .29s both}
@keyframes upgFadeIn{from{opacity:0}to{opacity:1}}
/* Ring retreats to where it came from — back down and shrinking away as it fades. */
.upgrader-ring-wrap.retreating{animation:upgRingRetreat .49s cubic-bezier(.4,0,.7,1) forwards}
@keyframes upgRingRetreat{
  0%{opacity:1;transform:translate(-50%,-50%) scale(1)}
  100%{opacity:0;transform:translate(-50%,-50%) translateY(34px) scale(.82)}
}
/* Lid dissolves while the crate is on its way back down. */
.upgrader-crate-top-wobble.dismissing{animation:upgFadeOut .39s ease forwards}
/* Roll readout drops back out of frame, in step with the ring's retreat. Doubled up on the
   class so it outranks the .shown rule further down the file, which would otherwise keep its
   much slower reveal timings and leave the readout hanging while everything else cleared. */
.upgrader-roll-result.hiding.hiding{opacity:0;transform:translateY(46px);
  transition:opacity .33s ease,transform .36s cubic-bezier(.4,0,.7,1)}
/* With the text and buttons faded out, the crate is left sitting low in the card. Sliding it
   up by the gap between its own centre and the card's centre (measured: 89px) puts the crate
   and its ring in the middle of the section. Driven by its own class rather than .spinning so
   it can be timed to the ring appearing, not to the click. The duration is set from JS to
   match the sound, and the curve mirrors the ring's own cubic ease-out so the rise decelerates
   in step with the arc and settles exactly as the sound ends. */
/* The final control point sits well below 1 so the curve keeps a little speed all the way to
   the end instead of braking early — with a hard ease-out the last pixel ate ~150ms and the
   crate looked parked before the sound finished. */
.upgrader-crate-wrap{flex:1;margin-top:12px;width:100%;max-height:220px;display:flex;align-items:center;justify-content:center;position:relative;overflow:visible;z-index:0;transition:transform var(--center-dur,.55s) cubic-bezier(.45,.1,.75,.85)}
.upgrader-crate-wrap.centered{transform:translateY(-89px)}
/* Wobble wrappers. The crate body already owns its transform (impact shake) and the lid's is
   driven frame-by-frame by the drop physics, so the ascent wobble is applied to these extra
   wrapper layers instead — the transforms compose rather than fighting each other.
   The z-indexes mirror what the images themselves carry (ring 0 < body 1 < lid 2); without
   them the wrappers form their own stacking contexts and the whole crate jumps above the
   ring. */
.upgrader-crate-body-wobble,
.upgrader-crate-top-wobble{display:block;width:100%;transform-origin:50% 60%;will-change:transform}
/* Only transition once .dudded is set — during the spin these are driven frame-by-frame from
   JS, and a transition there would lag the rattle behind and smear it. The origin is pinned to
   a fixed point instead of each element's own centre: the lid wrapper is absolutely positioned
   and collapses to a fraction of the body's height, so percentage origins put the two on
   different pivots and the lid swings off the crate when it tilts. */
.upgrader-crate-body-wobble{position:relative;z-index:1}
.upgrader-crate-top-wobble{position:absolute;left:0;top:0;z-index:2}
/* Win: the lid is blown off the crate — mirrors the entry drop in reverse, launching upward
   while fading out. Applied to the wobble wrapper because the lid image's own transform is
   still owned by the drop physics. */
/* Loss: the crate slumps over and goes semi-transparent — a dud, discarded. Applied to the
   two wobble wrappers rather than the whole stack, since the ring and arrow are siblings in
   there and shouldn't tilt or fade with it. */
.upgrader-crate-stack.dudded .upgrader-crate-body-wobble,
.upgrader-crate-stack.dudded .upgrader-crate-top-wobble{transform-origin:50% 190px;transition:transform .9s cubic-bezier(.22,1,.36,1);transform:rotate(-7deg) translateY(10px)}
/* Opacity lives on this shared wrapper rather than on each piece, so the crate and lid fade
   as one flat object. Fading them separately compounds where they overlap — the lid ends up
   showing the lit crate through it and reads as more transparent than the body.
   To revert: delete this rule and put `opacity:.45` back on the two wobble wrappers above. */
/* Needs its own stacking position, otherwise this wrapper flattens the body/lid z-indexes it
   contains and the ring ends up painting over the crate. */
.upgrader-crate-fade{display:block;position:relative;z-index:1;transition:opacity .9s ease}
.upgrader-crate-stack.dudded .upgrader-crate-fade{opacity:.55}
/* Roll readout — sits below the ring and slides up from the bottom of the card once the arc
   has settled. Absolutely positioned so it can't shift the crate/ring layout above it, and it
   starts translated down + transparent so the reveal is a single eased slide-and-fade. */
.upgrader-roll-result{position:absolute;left:0;right:0;bottom:26px;text-align:center;
  pointer-events:none;z-index:3;opacity:0;transform:translateY(52px);
  transition:opacity 1s ease,transform 1.15s cubic-bezier(.22,1,.36,1)}
.upgrader-roll-result.shown{opacity:1;transform:translateY(0)}
.upgrader-roll-value{font-size:19px;font-weight:800;color:#5b9dd9;letter-spacing:.2px;line-height:1.1}
.upgrader-roll-label{margin-top:5px;font-size:11px;font-weight:800;color:#fff;letter-spacing:1px}
.upgrader-crate-top-wobble.launched{animation:upgLidLaunch 1.25s cubic-bezier(.25,0,.5,1) forwards}
@keyframes upgLidLaunch{
  0%{transform:translateY(0) rotate(0deg);opacity:1}
  12%{transform:translateY(14px) rotate(-1.5deg);opacity:1}
  55%{opacity:0}
  100%{transform:translateY(-520px) rotate(9deg);opacity:0}
}
@keyframes upgFadeOut{to{opacity:0}}

/* Items slide/sink down into the crate's center and shrink away as they fade, instead of
   just fading in place — reads as the items dropping into the crate before it closes. */
.upgrader-crate-items.collapsing{animation:upgItemsCollapse .8s cubic-bezier(.4,0,.7,1) forwards}
@keyframes upgItemsCollapse{
  0%{opacity:1;transform:translateX(-50%) translateY(0) scale(1)}
  100%{opacity:0;transform:translateX(-50%) translateY(40px) scale(.25)}
}
/* Win payoff: the items climb back out of the open crate, each turning once on the way up.
   The container handles the rise and fade only — rotating it would swing the whole group
   around one shared centre, so the outer items would arc through the air instead of spinning.
   The turn is applied per card so each one revolves on its own axis, all at the same time. */
.upgrader-crate-items.revealing{animation:upgItemsReveal 1.15s cubic-bezier(.18,.9,.3,1) forwards}
@keyframes upgItemsReveal{
  0%{opacity:0;transform:translateX(-50%) translateY(46px) scale(.3)}
  35%{opacity:1}
  100%{opacity:1;transform:translateX(-50%) translateY(0) scale(1)}
}
/* Applied to the card, not the inner element — the inner owns the perpetual float animation
   and setting animation here would replace it, leaving the items dead still afterwards. */
.upgrader-crate-items.revealing .upgrader-crate-item{
  animation:upgItemSpin 1.15s cubic-bezier(.18,.9,.3,1)}
/* Keeps translate(var(--slot-x),0) scale(1) — the card's resting placement from .in — so the
   spin doesn't yank each item back to the row's centre while it turns. */
@keyframes upgItemSpin{
  0%{transform:translate(var(--slot-x),0) scale(1) rotate(0deg)}
  100%{transform:translate(var(--slot-x),0) scale(1) rotate(360deg)}
}

.upgrader-actions{display:flex;justify-content:center;gap:10px;width:100%;margin-top:auto;position:relative;z-index:1}
.upgrader-go-btn{width:200px;flex:none;display:flex;align-items:center;justify-content:center;gap:9px;padding:16px;border-radius:12px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.05);color:rgba(255,255,255,0.4);font-size:15px;font-weight:800;letter-spacing:.02em;font-family:var(--font);cursor:pointer;transition:all .16s}
.upgrader-go-btn i{font-size:17px}
.upgrader-go-btn:disabled{cursor:default}
.upgrader-go-btn.ready{background:#66852F;border-color:#66852F;color:#DDF2B8}
.upgrader-go-btn.ready:hover{background:#75993a}
.upgrader-reroll-wrap{width:52px;height:52px;flex-shrink:0}
.upgrader-reroll-btn{width:100%;height:100%;display:flex;align-items:center;justify-content:center;border-radius:12px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.6);cursor:pointer;transition:all .16s}
.upgrader-reroll-btn:hover{color:#fff;border-color:rgba(255,255,255,0.18);background:rgba(255,255,255,0.06)}
.upgrader-reroll-btn svg{width:19px;height:19px}

.upgrader-right{display:flex;flex-direction:column;gap:16px}
.upgrader-box{background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.08);border-radius:14px;padding:20px}
.upgrader-header{display:flex;align-items:center;gap:12px}
.upgrader-header-icon{width:34px;height:34px;object-fit:contain;flex-shrink:0}
.upgrader-header-text{flex:1;min-width:0}
.upgrader-header-text strong{display:block;font-size:17px;font-weight:700;color:#fff}
.upgrader-header-text p{font-size:13.5px;color:rgba(255,255,255,0.5);margin-top:2px}
.upgrader-header-right{display:flex;align-items:center;gap:8px;flex-shrink:0}

.upgrader-controls{display:flex;gap:20px;flex-wrap:wrap}
.upgrader-block-label{font-size:11.5px;font-weight:700;letter-spacing:.05em;color:#fff;text-transform:uppercase;margin-bottom:9px}
.upgrader-amount-block{flex:0 0 auto}
.upgrader-amount-row{display:flex;align-items:center;gap:6px}
.upgrader-amount-input-wrap{width:160px;height:42px;box-sizing:border-box;flex:none;display:flex;align-items:center;gap:6px;padding:0 10px;border-radius:10px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03)}
.upgrader-amount-input-wrap img{width:20px;height:20px;object-fit:contain;flex-shrink:0}
.upgrader-amount-input-wrap input{flex:1;width:0;min-width:0;background:none;border:none;outline:none;color:#fff;font-size:14px;font-weight:600;font-family:var(--font)}
.upgrader-quick-btn{width:52px;height:42px;box-sizing:border-box;padding:0;display:flex;align-items:center;justify-content:center;border-radius:10px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.7);font-size:12.5px;font-weight:700;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap;text-align:center}
#upgHalfBtn{font-size:16px}
.upgrader-quick-btn:hover{color:#fff;border-color:rgba(255,255,255,0.18);background:rgba(255,255,255,0.06)}
.upgrader-mult-block{flex-shrink:0}
.upgrader-mult-row{display:flex;gap:6px}
.upgrader-mult-btn{width:52px;height:42px;box-sizing:border-box;padding:0;display:flex;align-items:center;justify-content:center;border-radius:10px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.7);font-size:12.5px;font-weight:700;font-family:var(--font);cursor:pointer;transition:all .16s;text-align:center}
.upgrader-mult-btn:hover{color:#fff;border-color:rgba(255,255,255,0.18);background:rgba(255,255,255,0.06)}
.upgrader-mult-btn.active{background:#66852F;border-color:#66852F;color:#DDF2B8}
.upgrader-mult-btn.disabled{opacity:.4;cursor:not-allowed;pointer-events:none}
/* Bet controls are locked for the duration of a round — same treatment as the multiplier
   buttons so the whole betting row reads as committed. */
.upgrader-quick-btn.disabled{opacity:.4;cursor:not-allowed;pointer-events:none}
.upgrader-amount-input-wrap:has(input.disabled){opacity:.4;pointer-events:none}
.upgrader-amount-input-wrap input.disabled{cursor:not-allowed}

.upgrader-items-box{display:flex;flex-direction:column;gap:16px}
.upgrader-items-header{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap}
.upgrader-items-sub{font-size:12.5px;color:rgba(255,255,255,0.45)}
.upgrader-items-tools{display:flex;align-items:center;gap:8px}
.upgrader-search{width:min(160px,100%);flex:1 1 130px;height:42px;padding:0 13px;border-radius:9px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:#fff;font-size:12.5px;font-family:var(--font);outline:none;transition:border-color .16s}
.upgrader-search:focus{border-color:rgba(255,255,255,0.25)}
.upgrader-search::placeholder{color:rgba(255,255,255,0.35)}
.upgrader-items-spacer{position:relative;width:100%}
.upgrader-items-grid::-webkit-scrollbar{width:6px}
.upgrader-items-grid::-webkit-scrollbar-track{background:transparent}
.upgrader-items-grid::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.15);border-radius:3px}
.upgrader-items-grid::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,0.25)}
.upgrader-items-grid{position:relative;max-height:321px;overflow-y:auto;overflow-x:hidden;padding-right:8px;will-change:scroll-position;transform:translateZ(0);contain:layout style paint;scroll-behavior:smooth;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,0.15) transparent}
.upgrader-item-card{--rarity:120,205,145;position:absolute;top:0;left:0;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;padding:8px 4px 8px;border-radius:9px;border:1px solid rgba(255,255,255,0.08);background:radial-gradient(ellipse 100% 145% at 50% 0%,rgba(var(--rarity),0.32) 0%,rgba(var(--rarity),0.03) 75%,rgba(255,255,255,0.03) 100%);background-clip:padding-box;cursor:pointer;transition:border-color .16s;contain:layout style paint}
.upgrader-item-hover{position:absolute;inset:0;border-radius:8px;display:flex;align-items:center;justify-content:center;padding:6px;background:rgba(0,0,0,0.55);opacity:0;pointer-events:none;transition:opacity .35s ease}
.upgrader-item-hover-name{font-size:13.5px;font-weight:700;text-align:center;line-height:1.25;transform:translateY(10px);transition:transform .45s cubic-bezier(.22,1,.36,1)}
.upgrader-item-card:hover .upgrader-item-hover{opacity:1}
.upgrader-item-card:hover .upgrader-item-hover-name{transform:translateY(0)}
.upgrader-item-card.selected{border-color:#3a6f96;background:#1c3d54}
#upgRefreshBtn.upgrader-clear-btn{background:rgba(180,50,50,0.18);border-color:rgba(220,80,80,0.4);color:rgba(255,150,150,0.9)}
#upgRefreshBtn.upgrader-clear-btn:hover{background:rgba(180,50,50,0.28);border-color:rgba(220,80,80,0.6);color:#ffb3b3}
.upgrader-item-card img{width:67.5px;height:67.5px;object-fit:contain;margin:4px 0 6px}
.upgrader-item-price{display:flex;align-items:center;gap:5px;font-size:13.5px;font-weight:700;color:#fff}
.upgrader-item-price img{width:14px;height:14px;object-fit:contain;margin:0}
.upgrader-item-card.loading{pointer-events:none}
.upgrader-item-card.loading img,.upgrader-item-card.loading .upgrader-item-price{visibility:hidden}
.upgrader-item-spinner{width:16px;height:16px;border-radius:50%;border:2px solid rgba(255,255,255,0.15);border-top-color:rgba(255,255,255,0.6);animation:upgSpinnerSpin .7s linear infinite}
.upgrader-item-loading span{font-size:9.5px;font-weight:600;color:rgba(255,255,255,0.5)}
/* Grid-level refresh state — applies to whatever cards happen to be in the (virtualized,
   constantly recycled) DOM at any moment, instead of tagging specific card elements that
   might get swapped out mid-animation as the user scrolls or the list re-renders. Every
   card always carries its own hidden .upgrader-item-loading overlay; this class just
   reveals it site-wide across the grid while a refresh is in progress. */
.upgrader-item-loading{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;justify-content:center;gap:6px}
.upgrader-items-grid.refreshing .upgrader-item-card img,
.upgrader-items-grid.refreshing .upgrader-item-card .upgrader-item-price{visibility:hidden}
.upgrader-items-grid.refreshing .upgrader-item-card .upgrader-item-loading{display:none}
/* While refreshing, each card runs a skeleton shimmer — a highlight sweeping across an empty
   placeholder — so the reload reads as real work happening per card. --shimmer-delay is set
   per card from JS to stagger the sweep across the grid. */
.upgrader-items-grid.refreshing .upgrader-item-card{pointer-events:none;--shimmer-delay:0ms;overflow:hidden}
.upgrader-items-grid.refreshing .upgrader-item-card::after{
  content:"";position:absolute;inset:0;border-radius:inherit;
  background:linear-gradient(100deg,rgba(255,255,255,0) 30%,rgba(255,255,255,0.13) 50%,rgba(255,255,255,0) 70%);
  background-size:220% 100%;
  animation:upgCardShimmer 1.15s ease-in-out infinite;animation-delay:var(--shimmer-delay)}
@keyframes upgCardShimmer{0%{background-position:130% 0}100%{background-position:-130% 0}}
/* Cards fade back in once their image has actually landed. */
.upgrader-item-card.refreshed{animation:upgCardRefreshed .34s cubic-bezier(.22,1,.36,1)}
@keyframes upgCardRefreshed{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:none}}
@keyframes upgSpinnerSpin{to{transform:rotate(360deg)}}
#upgSortBtn svg{transition:transform .2s ease}
#upgRefreshBtn svg.spinning{animation:upgRefreshSpin 1s linear infinite}
@keyframes upgRefreshSpin{to{transform:rotate(360deg)}}
#upgraderRerollBtn svg{--spin-dir:1}
#upgraderRerollBtn svg.flipping{animation:upgRerollSpin .28s cubic-bezier(.65,0,.35,1)}
@keyframes upgRerollSpin{
  0%{transform:rotate(0)}
  100%{transform:rotate(calc(var(--spin-dir) * 180deg))}
}

/* Preview text spins a full turn on every Change Roll — a plain 2D rotate() that always
   accumulates forward (never resets to 0 or snaps backward), transitioned smoothly so it
   visibly spins through the update and eases to a stop upright again. */
#upgPreview{transition:transform 1.05s cubic-bezier(.16,1,.3,1)}

.upgrader-left.shaking{animation:upgLeftShake 1.05s cubic-bezier(.36,.07,.19,.97) both}
@keyframes upgLeftShake{
  0%,100%{transform:translate(0,0)}
  8%{transform:translate(-1.5px,1px)}
  16%{transform:translate(1.5px,-1px)}
  24%{transform:translate(-1.5px,-1px)}
  32%{transform:translate(1.2px,1px)}
  40%{transform:translate(-1px,1px)}
  48%{transform:translate(1px,-0.8px)}
  56%{transform:translate(-0.8px,-0.8px)}
  64%{transform:translate(0.8px,0.6px)}
  72%{transform:translate(-0.5px,0.5px)}
  80%{transform:translate(0.5px,-0.4px)}
  90%{transform:translate(0,0)}
}

@media (max-width:1320px){
  /* Tablet band: KEEP the two columns side by side, but let them share the viewport
     proportionally (same 480:750 ratio as the desktop fix) instead of holding the fixed
     ~1310px width that forced iPads to pan/pinch-zoom around an oversized page. The desktop
     rule's width:max-content + left:50%/translateX(-50%) centering hack is dropped here for
     plain full-width flow. PC (>1320px) renders the fixed desktop grid exactly as always. */
  .upgrader-layout{grid-template-columns:minmax(0,39fr) minmax(0,61fr);width:100%;left:auto;transform:none}
  /* The crate art deliberately overhangs its column on desktop (530px in a 420px content box,
     ~126%, clipped at the card edges) — the same proportional overhang keeps the look as the
     column shrinks. The floating-items stage scales with the column instead of a fixed 420px. */
  .upgrader-crate-stack{width:126%}
  .upgrader-crate-items{width:100%}
  .upgrader-items-grid{grid-template-columns:repeat(5,1fr)}
}
@media (max-width:700px){
  /* Phones: side-by-side genuinely can't fit — stack to a single column. */
  .upgrader-layout{grid-template-columns:1fr;max-width:600px;margin-left:auto;margin-right:auto}
  .upgrader-crate-stack{width:min(500px,120%)}
  .upgrader-items-grid{grid-template-columns:repeat(4,1fr)}
}


/* ── Spinner Battles ──────────────────────────────────────────────────────── */
/* .spinners-top-row is the whole "title + REMOVE FINISHED + CREATE A GAME" unit, always
   rendered as a single piece so the title and button stay in the same flex row no matter where
   the whole thing currently lives (see renderSpinnersYourGames in spinners.js, which relocates
   this exact node — not a clone — between sitting here by default, reading "Games", and sitting
   inside #spinnersYourGames reading "Your games" once at least one game exists).
   .spinners-games-title-row is a plain placeholder title, hidden by default and only shown
   (by spinners.js) once .spinners-top-row has moved away, so "Games" still has a heading of its
   own left behind. position:relative on .spinners-top-row is just the anchor for the create
   panel, pulled out of flow via absolute positioning so it can sit to the right of the header
   without shrinking the header's own centered width/position. */
.spinners-top-row{position:relative;margin-top:36px}
/* 940px, not 820 — matches .spinners-your-games .spinners-games-list below (widened so a 4th
   220px card fits per row: 4x220 + 3x14 gaps = 922px, which 820px can't hold). Keeping the
   title row and the grid at the same width is what keeps REMOVE FINISHED / CREATE A GAME
   (anchored off this row's right edge) lined up with the wider card grid underneath it. */
.spinners-games-title-row{width:100%;max-width:940px;margin:36px auto 0}
.spinners-header{display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap;width:100%;max-width:940px;margin:0 auto}
/* Same 940px column as .spinners-your-games .spinners-games-list and the header row above —
   without this, the public "Games" grid had no max-width at all, so its cards (sharing the same
   .spinners-games-list grid rule, minmax(220px,1fr)) stretched to fill the full page width
   instead of the same column "Your games" cards sit in, making them visibly bigger/differently
   positioned even though it's the exact same card markup. */
.spinners-layout{margin-top:22px;max-width:940px;margin-left:auto;margin-right:auto}
.spinners-title{font-size:24px;font-weight:800;color:#fff;letter-spacing:.01em}
/* Muted/secondary styling (not the green .create-battle-btn look) — this doesn't do anything
   yet, so it shouldn't read as the page's primary action. */
.spinners-remove-finished-btn{display:flex;align-items:center;gap:8px;flex-shrink:0;padding:11px 18px;border-radius:11px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.05);color:rgba(255,255,255,0.7);font-size:12.5px;font-weight:800;letter-spacing:.02em;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap}
.spinners-remove-finished-btn:hover{color:#fff;border-color:rgba(255,255,255,0.16);background:rgba(255,255,255,0.08)}
.spinners-remove-finished-btn svg{width:15px;height:15px;flex-shrink:0}
/* Positioned relative to the header's own centered right edge (50% + half the header's 940px
   width + the 24px gap) rather than flowing in the header's flexbox, so the header/REMOVE
   FINISHED position is completely untouched by the panel's presence. */
.spinners-create-panel{position:absolute;left:calc(50% + 494px);top:0;width:340px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.08);border-radius:14px;padding:20px}
/* The calc(50% + 494px) offset above needs roughly 940px (the centered games column) + 340px
   (this panel) + a 24px gap either side of that math to actually have somewhere to put the
   panel that doesn't run off the edge of the page — there's no room for that on an iPad-width
   screen, which is what forced horizontal scrolling there. Below that width the panel drops
   out of absolute positioning entirely and just flows as a normal block under the header row. */
@media (max-width:1300px){
  .spinners-create-panel{position:static;width:100%;max-width:940px;margin:16px auto 0}
}
.spinners-create-title{font-size:15px;font-weight:800;letter-spacing:.03em;color:rgb(187,229,113)}
.spinners-create-desc{margin-top:8px;font-size:13.5px;line-height:1.5;color:#fff}
.spinners-create-label{display:flex;align-items:center;gap:8px;margin-top:22px;margin-bottom:10px;font-size:12px;font-weight:800;letter-spacing:.04em;color:rgb(178,214,239)}
.spinners-create-label-plain{margin-bottom:10px}
.spinners-create-label-icon{position:relative;display:flex;align-items:center;justify-content:center;width:16px;height:16px;flex-shrink:0;color:rgb(178,214,239)}
/* PLAYER SLOTS' icon is a raster PNG (a solid black silhouette on transparent) rather than an
   inline SVG, so it can't pick up currentColor the way the brush icon's <svg stroke="currentColor">
   does. A CSS mask (background tinted through the PNG's own alpha shape, via --icon-mask set
   inline in the HTML) recolors it to the exact same light-blue as the label text instead —
   plain brightness/invert filters can only push it to white or black, not an arbitrary color.
   The <img> itself is kept in the DOM (for alt text / graceful degradation) but hidden. */
.spinners-create-label-icon img{width:100%;height:100%;object-fit:contain;opacity:0}
.spinners-create-label-icon[style*="--icon-mask"]::before{content:"";position:absolute;inset:0;background:rgb(178,214,239);-webkit-mask-image:var(--icon-mask);mask-image:var(--icon-mask);-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center}
.spinners-brush-icon svg{width:100%;height:100%}
.spinners-slot-group{display:flex;gap:8px}
.spinners-slot-btn{width:38px;height:38px;flex-shrink:0;box-sizing:border-box;border-radius:9px;border:1px solid transparent;background:rgba(110,107,101,0.75);color:#fff;font-size:13px;font-weight:700;font-family:var(--font);cursor:pointer;transition:all .16s}
.spinners-slot-btn:hover{filter:brightness(1.15)}
/* "2v2" needs more than the square 38px the single digits use. */
.spinners-slot-btn-2v2{width:auto;padding:0 13px}
.spinners-slot-btn.active{background:rgb(25,61,86);color:rgb(178,214,239)}
.spinners-color-group{display:flex;gap:8px}
/* Dark neutral square (like the slot buttons), with just a small swatch block centered inside
   via ::after — not the whole button filled with color. Active state changes the button's own
   background to the same dark blue the active slot button uses, not an outline. */
.spinners-color-btn{position:relative;width:38px;height:38px;flex-shrink:0;box-sizing:border-box;border-radius:9px;border:1px solid transparent;background:rgba(110,107,101,0.75);cursor:pointer;transition:all .16s}
.spinners-color-btn::after{content:"";position:absolute;top:50%;left:50%;width:16px;height:16px;transform:translate(-50%,-50%);border-radius:4px;background:var(--swatch)}
.spinners-color-btn:hover{filter:brightness(1.15)}
.spinners-color-btn.active{background:rgb(25,61,86)}
.spinners-amount-row{display:flex;gap:8px}
.spinners-amount-input-wrap{flex:1;height:42px;box-sizing:border-box;display:flex;align-items:center;gap:6px;padding:0 12px;border-radius:10px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03)}
.spinners-amount-input-wrap img{width:20px;height:20px;object-fit:contain;flex-shrink:0}
.spinners-amount-input-wrap input{flex:1;width:0;min-width:0;background:none;border:none;outline:none;color:#fff;font-size:13.5px;font-weight:600;font-family:var(--font)}
.spinners-quick-btn{width:46px;height:42px;box-sizing:border-box;flex-shrink:0;display:flex;align-items:center;justify-content:center;border-radius:10px;border:1px solid rgb(38,92,129);background:rgb(38,92,129);color:rgb(178,214,239);font-size:12.5px;font-weight:700;font-family:var(--font);cursor:pointer;transition:all .16s}
.spinners-quick-btn:hover{filter:brightness(1.15)}
.spinners-create-btn{width:100%;margin-top:22px;padding:14px;border-radius:11px;border:1px solid transparent;background:rgba(255,255,255,0.12);color:rgba(255,255,255,0.3);font-size:13.5px;font-weight:800;letter-spacing:.02em;font-family:var(--font);cursor:pointer;transition:all .16s}
.spinners-create-btn:disabled{cursor:default}
/* Same ready-state colors as the Scrap Upgrader's UPGRADE button. */
.spinners-create-btn.ready{background:#66852F;border-color:#66852F;color:#DDF2B8}
.spinners-create-btn.ready:hover{background:#75993a}

/* "Your games" — the relocated .spinners-top-row (title + REMOVE FINISHED + CREATE A GAME)
   renders as the first child here once at least one game exists; the list sits right below it.
   940px (not 820) is what actually fits a 4th 220px card per row: 4x220 + 3x14px gaps = 922px,
   which needs more room than 820px has. .spinners-header/.spinners-games-title-row above match
   this same 940px so REMOVE FINISHED / CREATE A GAME / "Games" stay lined up with the grid. */
.spinners-your-games{margin-top:36px}
.spinners-your-games .spinners-games-list{max-width:940px;margin:22px auto 0}

.spinners-games-list{min-height:1px;display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}

/* One created/joined game — mirrors .case-card's vertical-tile look (dark panel, rounded,
   padded) rather than the horizontal .battle-card row used on the Case Battles list. */
/* min-height keeps the card at its original size even though the wheel above got smaller —
   .spinner-game-card-players has flex:1, so the leftover room the smaller wheel leaves behind
   is absorbed there (pushing CANCEL back down to where it was) instead of the whole card
   shrinking to hug its now-shorter content. */
.spinner-game-card{position:relative;display:flex;flex-direction:column;min-height:340px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.08);border-radius:12px;padding:12px}
.spinner-game-card-pool{position:absolute;top:12px;left:12px;z-index:2;display:flex;align-items:center;gap:6px;font-size:14px;font-weight:800;color:#fff}
.spinner-game-card-pool img{width:16px;height:16px;object-fit:contain}
/* Applied only to a card the instant it's actually new (see renderSpinnersYourGames in
   spinners.js, which now updates existing cards in place instead of recreating them) — so
   creating one game plays this once for that card alone, instead of every card in the list
   replaying an entrance animation together on every render. */
.spinner-game-card-enter{animation:spinnerCardIn .38s cubic-bezier(.16,1,.3,1) both}
@keyframes spinnerCardIn{from{opacity:0;transform:translate3d(0,10px,0) scale(.96)}to{opacity:1;transform:translate3d(0,0,0) scale(1)}}

/* Wheel: spinner.png (neutral cracked-earth texture, quartered by its own printed cross lines)
   with a conic-gradient pie overlay tinted per player slot sitting on top of it — semi-
   transparent so the texture still shows through the color instead of being fully hidden. The
   arrow pointer sits above both, anchored to the top like the case-opening reel's pointer. */
.spinner-game-card-wheel-wrap{position:relative;width:100%;aspect-ratio:1;margin:34px auto 14px;max-width:150px}
.spinner-game-card-wheel-arrow{position:absolute;top:-16px;left:50%;transform:translateX(-50%);z-index:3;width:55px;height:55px;filter:drop-shadow(0 2px 4px rgba(0,0,0,0.6))}
.spinner-game-card-wheel-arrow img{width:100%;height:100%;object-fit:contain}
/* The circular clip (border-radius+overflow:hidden) and the background color live here, on an
   element that never itself rotates — .spinner-game-card-wheel-spin (a plain child with nothing
   but a transform on it) is what actually spins during the roll. Putting the clip mask and the
   mix-blend-mode fill on the *same* element being rotated forced a full repaint every animation
   frame (clipping and blend compositing both have to be re-resolved against the new angle, which
   can't just be handed to the GPU as a cheap re-transform the way a bare rotate() can) — that
   per-frame repaint work was the actual cause of the spin feeling laggy, not frame-rate/GPU
   limits. Splitting them apart means the only thing changing every frame is a transform on an
   element with no clip and no blend mode of its own, which the browser can composite instead of
   repaint. will-change hints the browser to promote that layer up front (skip discovering it
   needs one on the first animated frame, which is its own small stutter). */
.spinner-game-card-wheel{position:relative;width:100%;height:100%;border-radius:50%;overflow:hidden;background:#000}
.spinner-game-card-wheel-spin{position:absolute;inset:0;will-change:transform}
.spinner-game-card-wheel-spin img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
/* No flat opacity here — each segment carries its own alpha directly in the conic-gradient's
   rgba stops (spinnerGameConicGradient in spinners.js), so the correct pre-/post-landing value is
   baked in per segment instead of one uniform value applying to the whole layer. */
.spinner-game-card-wheel-fill{position:absolute;inset:0;mix-blend-mode:multiply}
/* mix-blend-mode is dropped ONLY below this width AND only while .spin-active is on the parent
   .spinner-game-card-wheel-spin (set by spinSpinnerWheel in spinners.js for exactly the duration
   the wheel is actually rotating, removed the instant it settles). This element is a CHILD of
   that rotating element, not a sibling sitting outside the rotation — so despite the earlier
   desktop pass separating the *clip* from the rotating layer, this blend mode was still riding
   along on every rotated frame. mix-blend-mode forces the compositor to re-read and re-blend
   against the backdrop on every frame a transform changes, which weaker mobile GPUs feel much
   more than desktop ones.
   Originally this dropped the blend mode unconditionally below 820px, all the time — but at
   opacity:1.0 (the landed winning segment) a flat alpha-composited color is fully opaque and
   hides the wheel's texture completely, reading as a cheap flat color block instead of the
   richly textured, multiply-darkened look PC has always had. Scoping the drop to only the
   actively-spinning window keeps every idle/landed card — the vast majority of the time any
   wheel is ever on screen — looking exactly like PC, and only trades that look away for the few
   seconds a wheel is genuinely mid-spin, which is a much smaller and worthwhile cost. */
@media (max-width:820px){
  .battle-lobby-rounds-pill{width:100%}
  .spinner-game-card-wheel-spin.spin-active .spinner-game-card-wheel-fill{mix-blend-mode:normal}
}

/* flex:1 lets this stretch to fill whatever room is left in the card once CSS Grid has
   stretched every card in the row to match the tallest one — so a 2-slot card's shorter player
   list still pushes CANCEL down to the same line as a 4-slot card's, instead of CANCEL sitting
   right under however many rows this particular game happens to have. justify-content keeps the
   rows themselves anchored to the top rather than spreading out to fill that extra space. */
.spinner-game-card-players{display:flex;flex-direction:column;justify-content:flex-start;gap:6px;margin-bottom:4px;flex:1}
/* Fixed height = the tallest content a row can hold (the 20px pfp) — an empty text-only row
   and a filled row with a pfp measure identical, so a slot filling never shifts or resizes
   anything around it. */
.spinner-game-card-player{display:flex;align-items:center;gap:8px;height:20px;font-size:12.5px;font-weight:600;color:#fff;min-width:0}
/* The callable/joinable hover-pill trick (padding:2px + margin:-2px) shrinks those rows'
   LAYOUT footprint by 4px vs a plain row — so they get 4px more height to compensate, keeping
   every row's flow footprint exactly 20px whether empty or filled. */
.spinner-game-card-player.empty.callable,.spinner-game-card-player.empty.joinable{height:24px}
.spinner-game-card-player-swatch{width:14px;height:14px;flex-shrink:0;border-radius:4px;background:var(--swatch)}
.spinner-game-card-player-pfp{width:20px;height:20px;flex-shrink:0;object-fit:contain}
.spinner-game-card-player-pfp[src^="/assets/img/bots/"]{object-fit:cover;border-radius:4px}
.spinner-game-card-player-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.spinner-game-card-player.empty{color:rgba(255,255,255,0.4)}
/* Only rows on your own cards get the clickable "call a bandit" treatment (see .callable, added
   only when spinnerGamePlayerRowHTML is rendering for the card's owner) — public-list cards
   stay plain text since calling a bandit into someone else's game isn't allowed.
   Box-identical to a plain .spinner-game-card-player on purpose: padding is offset by an equal
   negative margin on every side (not just left/right), so this row occupies the exact same
   width AND height whether it's showing "Call a bot" or, once filled, the plain row markup a
   real username swaps in as. Letting them differ in size was what made the swatch/name visibly
   "jump" into place right when a bot filled the slot, and also meant a card with more open
   slots was measurably taller than the same card once those slots filled in — which is what
   caused *other* cards in the row to visibly reflow (their row's tallest card changed) whenever
   a card was added/removed nearby, e.g. cancelling one card shifting the remaining ones. */
.spinner-game-card-player.empty.callable{cursor:pointer;border-radius:6px;margin:-2px -6px;padding:2px 6px;transition:background-color .15s ease,color .15s ease}
.spinner-game-card-player.empty.callable:hover{background:rgba(255,255,255,0.06);color:rgba(255,255,255,0.75)}
.spinner-game-card-player.empty.callable:active{background:rgba(255,255,255,0.1)}
/* Join — the public "Games" list's real-money equivalent of .callable's free "Call a bot".
   Same hover/box treatment (box-identical to a filled row for the same reason .callable is —
   see its own note above) so it reads as the same kind of clickable row language, just with a
   scrap amount inline instead of "Call a bot" text. */
.spinner-game-card-player.empty.joinable{cursor:pointer;border-radius:6px;margin:-2px -6px;padding:2px 6px;transition:background-color .15s ease,color .15s ease}
.spinner-game-card-player.empty.joinable:hover{background:rgba(255,255,255,0.06);color:rgba(255,255,255,0.75)}
.spinner-game-card-player.empty.joinable:active{background:rgba(255,255,255,0.1)}
.spinner-game-card-player-join-icon{width:12px;height:12px;object-fit:contain;vertical-align:-1px;margin:0 2px}

.spinner-game-card-cancel-btn{margin-top:10px;padding:10px;border-radius:9px;border:1px solid #7A2E2E;background:#7A2E2E;color:#F5C6C6;font-size:12px;font-weight:800;letter-spacing:.02em;font-family:var(--font);cursor:pointer;transition:all .16s}
.spinner-game-card-cancel-btn:hover{background:#8c3636}
/* STARTING / ROLLING / ROLLED — once the board's full and a winner's been decided, cancelling is
   no longer possible (see the server's ALREADY_SPINNING guard), so the button becomes a plain
   status readout instead of the red cancel action for the rest of that game's lifetime. Same
   class/look for all three labels; only the text (spinnerCancelButtonState in spinners.js) changes
   as the game moves from full -> turning -> at rest. cursor:default since it's inert now. */
.spinner-game-card-cancel-btn.starting{background:rgba(255,255,255,0.12);border-color:transparent;color:rgba(255,255,255,0.3);cursor:default}
.spinner-game-card-cancel-btn.starting:hover{background:rgba(255,255,255,0.12)}

/* JOIN GAME — non-owner cards' bottom button, same position/sizing as CANCEL but green, matching
   CREATE GAME's own .ready state exactly (#66852F/#DDF2B8, hover #75993a). Once the game fills,
   spinnerJoinButtonState swaps this to the same STARTING/ROLLING/ROLLED progression CANCEL uses
   — reusing .starting's exact look here too, so both bottom-button roles read as the identical
   "now inert, just a status" state once a game is no longer joinable/cancellable. */
.spinner-game-card-join-btn{margin-top:10px;padding:10px;border-radius:9px;border:1px solid #66852F;background:#66852F;color:#DDF2B8;font-size:12px;font-weight:800;letter-spacing:.02em;font-family:var(--font);cursor:pointer;transition:all .16s}
.spinner-game-card-join-btn:hover{background:#75993a}
.spinner-game-card-join-btn.starting{background:rgba(255,255,255,0.12);border-color:transparent;color:rgba(255,255,255,0.3);cursor:default}
.spinner-game-card-join-btn.starting:hover{background:rgba(255,255,255,0.12)}

/* ── Wheel (PC only — this page is being built section by section, no mobile pass yet) ────── */
/* min-height fills the viewport minus .wrap's own 104px/70px top/bottom padding, so
   align-items:center lands the wheel+panel row in the vertical middle of the screen rather
   than hanging just below the nav. */
.wheel-layout{display:flex;align-items:center;justify-content:center;gap:250px;min-height:calc(100vh - 174px)}
/* position:relative so the pointer arrow (a direct child, positioned absolutely) anchors to
   this box — which tightly wraps .wheel-main-wrap, so the arrow's coordinates are identical to
   when it lived inside the wrap. It was moved out so the wrap can clip its rotating image's
   oversized bounding box on mobile without slicing the arrow. */
.wheel-main{position:relative;display:flex;justify-content:center;flex-shrink:0}
.wheel-main-wrap{position:relative;width:700px;aspect-ratio:1}
/* The shadow lives on a static circle BEHIND the wheel, not as a filter on the wheel image —
   a filter on the element that rotates during the spin forces the browser to re-render the
   filter every animated frame (same per-frame repaint trap the spinner-battles wheel hit),
   whereas a bare transform on a filter-free img composites cheaply. will-change pre-promotes
   the layer so the first spin frame doesn't stutter on layer creation. */
.wheel-main-wrap::before{content:"";position:absolute;inset:2%;border-radius:50%;box-shadow:0 12px 32px rgba(0,0,0,0.55)}
.wheel-main-img{position:relative;width:100%;height:100%;object-fit:contain;will-change:transform}
/* Top-center pointer, sized big relative to the wheel and pulled down so roughly its bottom
   half overlaps into the wheel's rim rather than just touching the edge. */
.wheel-main-arrow{position:absolute;top:-20px;left:50%;transform:translateX(-50%);width:110px;height:auto;z-index:2;filter:drop-shadow(0 4px 10px rgba(0,0,0,0.6))}

/* Right-side control panel — static for now (no click handlers do anything yet), built to match
   an exact reference screenshot's layout: title+help row, an info blurb, a time-left row, the
   five payout slots, then the scrap-stacks amount controls. */
.wheel-panel{position:relative;width:600px;flex-shrink:0;display:flex;flex-direction:column;gap:16px}
/* Round-history strip hanging off the panel's right edge: blue history icon up top (site-
   standard .icon-btn-wrap/.icon-tooltip hover tooltip), then one colored square per finished
   round — newest at the top, sliding down as new results land, clipped at the panel's bottom. */
/* top/height are set by positionWheelHistory in wheel.js (measured against the info section
   and the stacks card), not fixed here. */
.wheel-history{position:absolute;left:calc(100% + 14px);top:50px;display:flex;flex-direction:column;align-items:center;gap:10px}
.wheel-history-icon{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:9px;border:none;background:none;color:rgb(178,214,239);cursor:pointer;transition:all .16s}
.wheel-history-icon:hover{color:#fff}
.wheel-history-icon svg{width:17px;height:17px}
.wheel-history-list{display:flex;flex-direction:column;align-items:center;gap:6px;flex:1;overflow:hidden}
.wheel-history-square{width:15px;height:15px;flex-shrink:0;border-radius:3px;border:1px solid rgba(0,0,0,0.5)}
.wheel-history-square.new{animation:wheelHistIn .3s cubic-bezier(.22,1,.36,1) both}
@keyframes wheelHistIn{from{opacity:0;transform:translateY(-8px) scale(.5)}to{opacity:1;transform:translateY(0) scale(1)}}
.wheel-panel-header{display:flex;align-items:center;gap:10px}
.wheel-panel-title{flex:1;font-size:19px;font-weight:800;color:rgb(239,239,239);letter-spacing:.02em}
.wheel-panel-sound-btn,.wheel-panel-help-btn{display:flex;align-items:center;gap:6px;flex-shrink:0;padding:8px 10px;border-radius:9px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.7);font-size:12px;font-weight:800;letter-spacing:.03em;font-family:var(--font);cursor:pointer;transition:all .16s}
.wheel-panel-sound-btn:hover,.wheel-panel-help-btn:hover{color:#fff;border-color:rgba(255,255,255,0.16);background:rgba(255,255,255,0.06)}
/* Same red muted treatment the site's other sound toggles use. */
.wheel-panel-sound-btn.muted{color:rgb(230,70,50);border-color:rgba(230,70,50,0.35);background:rgba(230,70,50,0.1)}
.wheel-panel-sound-btn svg,.wheel-panel-help-btn svg{width:16px;height:16px;flex-shrink:0}

.wheel-panel-info{display:flex;align-items:center;gap:14px;padding:14px 16px;border-radius:11px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)}
.wheel-panel-info-icon{flex-shrink:0;width:34px;height:34px;color:rgba(255,255,255,0.4)}
.wheel-panel-info-icon svg{width:100%;height:100%}
.wheel-panel-info p{font-size:17px;line-height:1.5;color:rgb(239,239,239)}

.wheel-panel-timer-row{display:flex;align-items:stretch;gap:10px}
.wheel-panel-timer-info{flex:1;padding:14px 16px;border-radius:11px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)}
.wheel-panel-timer-label{font-size:16px;font-weight:800;letter-spacing:.04em;color:rgb(239,239,239)}
.wheel-panel-timer-info p{margin-top:4px;font-size:16px;color:rgb(239,239,239)}
/* Fixed width on the 20s box; the TIME LEFT card next to it is flex:1, so widening this one
   automatically shortens that one — the two always share the row's full width. */
.wheel-panel-timer-value{position:relative;overflow:hidden;flex-shrink:0;width:150px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;border-radius:11px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);color:rgba(255,255,255,0.35)}
.wheel-panel-timer-value span{font-size:34px;font-weight:800;color:rgb(255,255,255)}
/* White countdown bar pinned along the box's bottom edge — the fill drains right-to-left via
   scaleX (transform-origin left), driven by a single CSS transition per round from wheel.js. */
.wheel-panel-timer-bar{position:absolute;left:0;right:0;bottom:0;height:5px;background:rgba(255,255,255,0.08);overflow:hidden}
/* Lock icon shown in place of the countdown once betting closes (entries final). Font
   Awesome's fa-lock — note the free FA set only ships the filled style. */
.wheel-panel-lock{font-size:30px;color:rgba(255,255,255,0.55)}
.wheel-panel-timer-bar-fill{position:absolute;inset:0;background:#fff;transform-origin:left center;transition:transform .25s linear}

.wheel-panel-slots{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;padding:16px;border-radius:11px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)}
/* The slot artwork (colored box, number, PAYS X label, worn texture) is all baked into the
   wheel1/3/5/10/20.png images themselves — the button is just a plain clickable frame around
   the image, no CSS-drawn background/texture of its own. data-mult carries which multiplier
   the button represents, for the game logic to come. */
.wheel-panel-slot{position:relative;display:block;padding:0;border:none;background:none;cursor:pointer;transition:transform .12s;font-family:var(--font);touch-action:none}
/* Bets locked: tiles are completely inert — no hover grow, no green wash, no clicks. */
.wheel-panel-slots.locked .wheel-panel-slot{pointer-events:none}
/* Hover: grow slightly in place (no float-up) with a green wash over the tile artwork. */
.wheel-panel-slot:hover{transform:scale(1.015)}
.wheel-panel-slot-img{position:relative;display:block;width:100%}
.wheel-panel-slot-img img{display:block;width:100%;height:auto}
/* z-index:3 keeps the hover wash above the placed-bet scrap overlay (z-index:2 below), so a
   tile with scrap on it tints green across everything — artwork and scrap pile alike. */
.wheel-panel-slot-img::after{content:"";position:absolute;inset:0.1px;z-index:3;border:2px solid #000;pointer-events:none;transition:background .12s,border-color .12s}
.wheel-panel-slot:hover .wheel-panel-slot-img::after{background:rgba(88,190,140,0.45);border-color:rgba(60,130,96,0.8);box-shadow:inset 0 0 10px rgba(88,190,140,0.6)}
/* Overlaid on the artwork itself, sitting just under the big number baked into the PNG. */
.wheel-panel-slot-pays{position:absolute;left:0;right:0;bottom:9%;z-index:1;text-align:center;font-size:11px;font-weight:800;letter-spacing:.04em;color:rgb(0,0,0);pointer-events:none}
/* A placed bet: scrap pile art centered over the tile with the running total pinned to the
   pile's bottom-right corner in white — repeat clicks just update the number. */
.wheel-panel-slot-bet{position:absolute;inset:0;z-index:2;display:flex;align-items:center;justify-content:center;pointer-events:none}
.wheel-panel-slot-bet img{width:90%;height:auto;filter:drop-shadow(0 2px 6px rgba(0,0,0,0.6))}
.wheel-panel-slot-bet b{position:absolute;right:5%;bottom:7%;font-size:15px;font-weight:800;color:#fff;text-shadow:0 1px 3px rgba(0,0,0,0.9),0 0 6px rgba(0,0,0,0.7)}

.wheel-panel-stacks{display:flex;flex-direction:column;gap:12px;padding:16px;border-radius:11px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)}
.wheel-panel-stacks-row{display:flex;align-items:center;justify-content:space-between}
.wheel-panel-stacks-label{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:800;letter-spacing:.04em;color:rgb(239,239,239)}
/* "?" next to SCRAP STACKS, mouse mode only — hover brings up the Rust-keybinds tooltip. */
.wheel-stacks-help{color:rgba(255,255,255,0.45);cursor:default;font-size:14px;transition:color .16s}
.wheel-stacks-help:hover{color:rgba(255,255,255,0.8)}
.wheel-keybinds-tooltip{position:absolute;bottom:calc(100% + 9px);left:-12px;width:290px;padding:11px 13px;border-radius:8px;background:rgba(9,9,9,0.98);border:1px solid rgba(255,255,255,0.1);box-shadow:0 10px 28px rgba(0,0,0,0.5);opacity:0;transform:translateY(4px);pointer-events:none;transition:opacity .16s ease,transform .16s ease;z-index:20;text-align:left;letter-spacing:normal}
.wheel-stacks-help:hover .wheel-keybinds-tooltip{opacity:1;transform:translateY(0);transition-delay:0.3s}
.wheel-keybinds-tooltip b{display:block;font-size:13px;font-weight:800;color:#fff;margin-bottom:6px}
.wheel-keybinds-tooltip ul{margin:0;padding-left:16px;display:flex;flex-direction:column;gap:3px}
.wheel-keybinds-tooltip li{font-size:12.5px;font-weight:500;line-height:1.45;color:rgba(255,255,255,0.85)}
.wheel-panel-stacks-total{display:flex;align-items:center;gap:7px;font-size:14px;font-weight:800;color:rgb(239,239,239)}
.wheel-panel-stacks-total img{width:16px;height:16px;object-fit:contain}
.wheel-panel-stacks-right{display:flex;align-items:center;gap:14px}
/* Mouse / keyboard input toggle: whichever side is active glows green, the other sits gray.
   Defaults to keyboard (switch on / knob right). */
.wheel-input-toggle{display:flex;align-items:center;gap:7px}
.wheel-input-icon{width:23px;height:23px;display:flex;align-items:center;justify-content:center;font-size:19px;color:rgba(255,255,255,0.35);transition:color .16s}
.wheel-input-toggle.keyboard .wheel-input-kb{color:rgb(170,222,78)}
.wheel-input-toggle.mouse .wheel-input-mouse{color:rgb(170,222,78)}
.wheel-input-switch{position:relative;width:26px;height:15px;flex-shrink:0;border-radius:8px;border:none;background:rgba(255,255,255,0.18);cursor:pointer;transition:background .16s;padding:0}
.wheel-input-switch-knob{position:absolute;top:2px;left:2px;width:11px;height:11px;border-radius:50%;background:#fff;transition:transform .18s cubic-bezier(.22,1,.36,1)}
.wheel-input-toggle.keyboard .wheel-input-switch-knob{transform:translateX(11px)}
.wheel-panel-amount-row{display:flex;align-items:center;gap:8px}
/* Same construction as .spinners-amount-input-wrap / .spinners-quick-btn on the Spinner Battles
   create panel — deliberately identical colors and behavior so the two amount controls read as
   the same component site-wide. */
.wheel-panel-amount-input-wrap{flex:1;height:42px;box-sizing:border-box;display:flex;align-items:center;gap:6px;padding:0 12px;border-radius:10px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03)}
.wheel-panel-amount-input-wrap img{width:20px;height:20px;object-fit:contain;flex-shrink:0}
.wheel-panel-amount-input-wrap input{flex:1;width:0;min-width:0;background:none;border:none;outline:none;color:#fff;font-size:13.5px;font-weight:600;font-family:var(--font)}
.wheel-panel-quick-btn{flex-shrink:0;height:42px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;padding:0 12px;border-radius:10px;border:1px solid rgb(38,92,129);background:rgb(38,92,129);color:rgb(178,214,239);font-size:12.5px;font-weight:700;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap}
.wheel-panel-quick-btn:hover{filter:brightness(1.15)}
.wheel-panel-hint{font-size:12.5px;line-height:1.5;color:rgb(140,194,231)}
/* Mouse-input mode: draggable scrap stacks replacing the amount textbox/quick buttons — a
   5-wide window over the denomination list, paged one step at a time by the edge arrows. */
.wheel-stacks-drag{position:relative}
.wheel-stacks-tiles{display:flex;gap:8px;min-width:0}
/* touch-action:none lets the pointer-drag engine own touch gestures on these — without it a
   finger-drag scrolls the page instead of moving scrap. No effect on mouse/PC. */
.wheel-stack-tile{position:relative;flex:1;aspect-ratio:1;border-radius:8px;background:rgba(255,255,255,0.05);cursor:grab;display:flex;align-items:center;justify-content:center;user-select:none;transition:background .15s;touch-action:none}
.wheel-stack-tile:hover{background:rgba(255,255,255,0.09)}
.wheel-stack-tile:active{cursor:grabbing}
.wheel-stack-tile img{width:86%;height:auto;pointer-events:none;filter:drop-shadow(0 2px 5px rgba(0,0,0,0.5))}
.wheel-stack-tile b{position:absolute;right:7%;bottom:6%;font-size:14px;font-weight:800;color:#fff;text-shadow:0 1px 3px rgba(0,0,0,0.9),0 0 6px rgba(0,0,0,0.7);pointer-events:none}
/* Bets locked: stacks read as simply disabled — faded out at their normal colors (no gloomy
   grayscale), untouchable until the next round's betting opens. */
.wheel-stacks-drag.locked .wheel-stack-tile{pointer-events:none;opacity:0.35}
/* Arrows float ON TOP of the outer tiles at the row's edges (not beside the row), so the tiles
   themselves stretch the full panel width. */
.wheel-stacks-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;display:flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:50%;border:none;background:rgba(20,20,20,0.85);color:rgba(255,255,255,0.8);cursor:pointer;transition:all .16s;box-shadow:0 2px 8px rgba(0,0,0,0.5)}
#wheelStacksLeft{left:-22px}
#wheelStacksRight{right:-22px}
.wheel-stacks-arrow:hover{background:rgba(45,45,45,0.95);color:#fff}
.wheel-stacks-arrow svg{width:17px;height:17px}
/* Floating drag ghost following the pointer during a custom (pointer-event-based) scrap drag —
   the native HTML5 drag API only works for left-click, and the Rust keybinds need right/middle
   drags too, so dragging is done manually with this element. */
/* Anchored at 0,0 and moved purely via transform (never left/top) — a transform on a
   will-change-promoted layer is composited on the GPU each frame, whereas left/top writes
   force style/layout work per pointermove, which is what made the drag feel laggy. Width is
   set at drag start from the real on-screen stack-tile image size so the ghost matches it. */
.wheel-drag-ghost{position:fixed;left:0;top:0;z-index:300;pointer-events:none;width:100px;opacity:0.9;will-change:transform}
.wheel-drag-ghost img{width:100%;height:auto;filter:drop-shadow(0 3px 8px rgba(0,0,0,0.6))}
.wheel-drag-ghost b{position:absolute;right:2%;bottom:2%;font-size:13px;font-weight:800;color:#fff;text-shadow:0 1px 3px rgba(0,0,0,0.9)}
/* While a scrap stack is being dragged: spotlight the number fields by dimming everything else
   DIRECTLY (a brightness filter on each major region) rather than sliding a full-screen shade
   over the page — .wrap keeps a filled CSS animation from page transitions, which makes it one
   sealed stacking context, so no overlay can ever sit between its layers: it either darkened
   the slots too (the bug this replaces) or nothing. The slots card itself is skipped by the
   selectors, gets a solid brighter fill, and its tiles a small brightness boost. */
body.wheel-dragging header,
body.wheel-dragging .wheel-main,
body.wheel-dragging .wheel-history,
body.wheel-dragging .wheel-panel>*:not(.wheel-panel-slots){filter:brightness(0.4)}
body.wheel-dragging .wheel-panel-slots{background:rgb(44,44,48);border-color:rgba(255,255,255,0.14)}
body.wheel-dragging .wheel-panel-slot{filter:brightness(1.1)}
/* Same green treatment as :hover, applied while a scrap stack is dragged over a slot. */
.wheel-panel-slot.dragover{transform:scale(1.015)}
.wheel-panel-slot.dragover .wheel-panel-slot-img::after{background:rgba(88,190,140,0.45);border-color:rgba(60,130,96,0.8);box-shadow:inset 0 0 10px rgba(88,190,140,0.6)}

.wheel-panel-players-row{display:flex;align-items:center;justify-content:space-between}
.wheel-panel-players{font-size:13px;font-weight:800;letter-spacing:.04em;color:rgb(232,120,105)}
.wheel-panel-players-total{display:flex;align-items:center;gap:4px;font-size:13px;font-weight:800;color:rgba(255,255,255,0.55)}
.wheel-panel-players-total img{width:15px;height:15px;object-fit:contain}
/* Bettor pfps under the players row — one circle per player in the round. min-height keeps the
   panel from shifting when the first bettor appears. */
.wheel-panel-bettors{display:flex;align-items:center;gap:5px;min-height:40px;margin-top:-8px}
/* No overflow:hidden here — the hover tooltip is a child and would get clipped; the item art
   (78%, contain-fit) never exceeds the circle anyway. */
.wheel-panel-bettor{position:relative;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;background:rgba(255,255,255,0.07);border:1px solid rgba(255,255,255,0.1);transition:transform .15s ease;cursor:pointer}
.wheel-panel-bettor:hover{transform:translateY(-4px)}
.wheel-panel-bettor>img{width:78%;height:78%;object-fit:contain}
/* Bettor hover tooltip: pfp + name + round total (players-strip red), then per-field colored
   squares with amounts. Same dark surface as the site's other tooltips/modals. */
.wheel-bettor-tooltip{position:absolute;bottom:calc(100% + 9px);left:50%;transform:translateX(-50%) translateY(4px);display:block;padding:9px 12px;border-radius:8px;background:rgba(9,9,9,0.98);border:1px solid rgba(255,255,255,0.1);box-shadow:0 10px 28px rgba(0,0,0,0.5);opacity:0;pointer-events:none;transition:opacity .16s ease,transform .16s ease;z-index:30;white-space:nowrap}
.wheel-panel-bettor:hover .wheel-bettor-tooltip{opacity:1;transform:translateX(-50%) translateY(0)}
.wheel-bettor-tooltip-head{display:flex;align-items:center;gap:7px}
.wheel-bettor-tooltip-pfp{width:20px;height:20px;object-fit:contain}
.wheel-bettor-tooltip-name{font-size:14.5px;font-weight:800;color:rgb(232,120,105)}
.wheel-bettor-tooltip-total{display:flex;align-items:center;gap:4px;margin-left:10px;font-size:14.5px;font-weight:800;color:rgb(232,120,105)}
.wheel-bettor-tooltip-total img{width:14px;height:14px;object-fit:contain}
/* margin-left centers the 10px squares under the 20px pfp above ((20-10)/2 = 5px). */
.wheel-bettor-tooltip-bets{display:flex;align-items:center;gap:11px;margin-top:7px;margin-left:5px}
.wheel-bettor-tooltip-bet{display:flex;align-items:center;gap:5px;font-size:12.5px;font-weight:700;color:#fff}
.wheel-bettor-tooltip-bet i{width:10px;height:10px;border-radius:2px;flex-shrink:0}
/* Entrance: starts collapsed into a negative margin (its own width + gap) and expands to full
   size — the expansion is what smoothly slides every circle after it to the right, instead of
   them all jumping a slot instantly. */
.wheel-panel-bettor.new{animation:wheelBettorIn .35s cubic-bezier(.22,1,.36,1) both}
/* margin-left is deliberately ABSENT from the "to" keyframe: with fill-mode both, an explicit
   end value would pin itself on the element forever — omitting it animates the margin from the
   collapsed start to the element's natural resting value. */
@keyframes wheelBettorIn{
  from{margin-left:-48px;opacity:0;transform:scale(.4)}
  to{opacity:1;transform:scale(1)}
}

/* ── Wheel of Fortune: mobile/tablet (≤1366px) — PC above this is untouched. 1366 covers every
   iPad including a 12.9" Pro in landscape; the side-by-side desktop layout needs ~1614px, so
   anything iPad-sized panned/zoomed around an oversized page before this. Must stay in sync
   with WHEEL_STACKED_MQ in wheel.js. ── */
@media (max-width:1366px){
  /* Tablet band: stays side by side like desktop, but wheel and panel share the viewport
     fluidly (wheel ~44vw, panel takes the rest) with a small gap instead of desktop's fixed
     700px + 250px + 600px that forced iPads to pan/zoom. Everything also runs compact:
     tighter paddings, smaller type. Phones (<=700px) stack instead — see below. */
  .wheel-layout{gap:24px;min-height:0;margin-top:14px}
  /* overflow:clip stops the ROTATED wheel image's bounding box (wider than the wrap — a turned
     square's box grows toward its diagonal) from widening the page. Only transparent corner
     pixels get clipped; the visible circle always fits the wrap. Mobile-gated so PC rendering
     is untouched. */
  .wheel-main-wrap{width:min(500px,44vw);overflow:clip}
  .wheel-main-arrow{width:clamp(56px,14%,90px);top:-14px}
  .wheel-panel{width:auto;flex:1 1 0;min-width:0;max-width:600px;gap:10px}
  .wheel-panel-title{font-size:17px}
  .wheel-panel-info{padding:10px 12px;gap:10px}
  .wheel-panel-info-icon{width:26px;height:26px}
  .wheel-panel-info p{font-size:14px}
  .wheel-panel-timer-info{padding:10px 12px}
  .wheel-panel-timer-label{font-size:14px}
  .wheel-panel-timer-info p{font-size:13.5px}
  .wheel-panel-timer-value{width:110px}
  .wheel-panel-timer-value span{font-size:26px}
  .wheel-panel-lock{font-size:24px}
  .wheel-panel-slots{padding:10px;gap:5px}
  .wheel-panel-stacks{padding:12px;gap:9px}
  /* The history strip can't hang off the panel's right edge when there's no side room — it
     becomes a horizontal row at the top of the panel (icon, then squares newest-first).
     positionWheelHistory in wheel.js skips its top/height measurements in this mode. */
  .wheel-history{position:static;width:100%;flex-direction:row;align-items:center;gap:8px;order:-1;top:auto!important;height:auto!important}
  .wheel-history-list{flex-direction:row;flex:1;height:16px;overflow:hidden;gap:5px}
  /* Amount input takes its own line so the four quick buttons never crush it on a phone. */
  .wheel-panel-amount-row{flex-wrap:wrap}
  .wheel-panel-amount-input-wrap{flex:1 1 100%}
}
@media (max-width:700px){
  /* Phones: side-by-side can't fit — wheel stacks above the panel. */
  .wheel-layout{flex-direction:column;align-items:center;gap:18px}
  .wheel-main-wrap{width:min(540px,90vw)}
  .wheel-panel{width:100%;flex:none}
}
@media (max-width:600px){
  .wheel-help-row{flex-direction:column}
  .wheel-help-row-flip .wheel-help-img{order:2}
  .wheel-help-img{width:100%;max-width:320px;align-self:center}
}

/* ── Wheel of Fortune: HOW TO PLAY modal ─────────────────────────────────── */
.wheel-help-backdrop{position:fixed;inset:0;z-index:210;display:flex;align-items:center;justify-content:center;background:rgba(4,4,6,0);backdrop-filter:blur(0px);-webkit-backdrop-filter:blur(0px);opacity:0;pointer-events:none;transition:opacity .3s ease,background .3s ease,backdrop-filter .3s ease}
.wheel-help-backdrop.open{opacity:1;pointer-events:auto;background:rgba(4,4,6,0.72);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.wheel-help-modal{width:min(640px,92vw);max-height:88vh;overflow-y:auto;padding:30px 32px 26px;background:rgba(9,9,9,0.98);border:1px solid rgba(255,255,255,0.09);border-radius:18px;box-shadow:0 24px 64px rgba(0,0,0,0.55);transform:translateY(14px) scale(.96);opacity:0;transition:transform .32s cubic-bezier(.16,1,.3,1),opacity .28s ease}
.wheel-help-backdrop.open .wheel-help-modal{transform:translateY(0) scale(1);opacity:1}
.wheel-help-label{font-size:13px;font-weight:800;letter-spacing:.06em;color:rgb(63,153,215)}
.wheel-help-title{margin-top:4px;font-size:26px;font-weight:800;color:rgb(255,255,255);letter-spacing:.01em}
.wheel-help-intro{margin-top:12px;font-size:15.5px;line-height:1.55;color:rgba(255,255,255,0.7)}
.wheel-help-row{display:flex;align-items:flex-start;gap:22px;margin-top:26px}
.wheel-help-img{width:220px;height:auto;flex-shrink:0;border-radius:10px}
.wheel-help-text{flex:1;min-width:0}
.wheel-help-text h3{font-size:17px;font-weight:800;color:rgb(101,173,223)}
.wheel-help-text p{margin-top:8px;font-size:14.5px;line-height:1.55;color:rgba(255,255,255,0.7)}
.wheel-help-text b{color:rgba(255,255,255,0.9)}
.wheel-help-link{color:rgb(170,222,78) !important;font-weight:600;cursor:pointer;font-size:12.5px !important}
.wheel-help-ok-btn{width:100%;margin-top:28px;padding:15px;border-radius:8px;border:none;background:rgb(92,122,42);color:rgb(170,222,78);font-size:15px;font-weight:800;letter-spacing:.03em;font-family:var(--font);cursor:pointer;transition:filter .16s}
.wheel-help-ok-btn:hover{filter:brightness(1.12)}

/* ── Case Battles ─────────────────────────────────────────────────────────── */
.battles-header{display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap;margin-top:36px;margin-bottom:34px}
.battles-title{font-size:24px;font-weight:800;color:#fff;letter-spacing:.01em}
.battles-sub{margin-top:5px;font-size:16px;color:rgba(255,255,255,0.62)}
.battles-controls{display:flex;align-items:center;gap:11px;flex-shrink:0}
/* Matches the upgrader's ready state so the primary action reads the same site-wide. */
/* The shared .dd-menu has a 200px min-width for the cases sort labels. Here the menu should
   line up with its own trigger instead, so that floor is dropped and the width is pinned to
   the dropdown wrapper (which is sized by the button). */
#battleShowMenu{min-width:0;width:auto;left:0;right:0}
.create-battle-btn{flex-shrink:0;padding:11px 20px;border-radius:11px;border:1px solid #66852F;background:#66852F;color:#DDF2B8;font-size:13.5px;font-weight:800;letter-spacing:.02em;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap}
.create-battle-btn:hover{background:#75993a;border-color:#75993a}

/* ── Battles browse list ──────────────────────────────────────────────────── */
.battles-list{display:flex;flex-direction:column;gap:10px;margin-bottom:40px}
.battles-empty{display:none;padding:60px 20px;text-align:center;color:rgba(255,255,255,0.45);font-size:15px}
.battle-card.no-anim{animation:none}
/* Feed motion: new cards ease in from above, dropped cards fade and collapse; everything else slides on its own transform transition. */
.battle-card.entering{opacity:0;transform:translateY(-10px);transition:none}
.battle-card.leaving{opacity:0;transform:scale(.97);overflow:hidden;padding-top:0;padding-bottom:0;border-color:transparent;pointer-events:none}
.battle-card{display:flex;align-items:center;gap:22px;padding:14px 18px;border-radius:14px;border:1px solid rgba(255,255,255,0.06);background:rgba(255,255,255,0.02);animation:fadeIn .35s ease both;cursor:pointer;transition:transform .5s cubic-bezier(.23,1,.32,1),opacity .35s ease,height .5s cubic-bezier(.23,1,.32,1),margin .5s cubic-bezier(.23,1,.32,1),background .45s ease}
.battle-card:hover{transform:translateY(-3px);background:rgba(255,255,255,0.035)}
/* Fixed width (not a min-width) so this column is identical on every card — otherwise a long
   title like "Cursed 1v1v1v1 Jackpot" grows the column and pushes that card's case icons
   further right than a plain "1v1 Battle" card's, breaking the row-to-row alignment. */
/* min-height pins the card at its pre-header-merge height (85px column -> 115px card). */
.battle-card-left{display:flex;flex-direction:column;gap:10px;flex-shrink:0;min-width:min(320px,100%);min-height:85px}
/* Desktop: the battles page bleeds past .wrap's side padding so its cards span the same
   1180px as the navbar pill. */
@media (min-width:821px){#page-battles{margin-left:-32px;margin-right:-32px}}
.battle-card-head{display:flex;align-items:center;gap:9px;min-width:0}
.battle-card-total{display:flex;align-items:center;gap:7px;flex-shrink:0;white-space:nowrap}
.battle-card-total .scrap-icon{width:15px;height:15px;flex-shrink:0}
.battle-card-total-amt{font-size:15px;font-weight:800;color:#fff;flex-shrink:0}
/* Partially funded: the full seat price crossed out above what a joiner actually pays. */
.battle-card-price-stack{display:flex;flex-direction:column;align-items:flex-start;line-height:1;gap:2px}
.battle-card-total-orig{font-size:11px;font-weight:700;color:rgba(255,255,255,0.4);text-decoration:line-through}
.battle-card-price-stack .battle-card-total-amt{color:#66852F} /* the price you actually pay, in the join button's green */
/* Title truncates instead of wrapping/overflowing so it can't push the fixed-width column
   (and therefore the case icons after it) out of alignment. */
.battle-card-title{display:inline-flex;align-items:center;gap:5px;font-size:14px;font-weight:800;color:rgba(255,255,255,0.85);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.battle-card-title span{color:inherit;overflow:hidden;text-overflow:ellipsis}
.battle-card-title-icon{width:14px;height:14px;flex-shrink:0}
/* Team modes only ever use p-0/p-1 (team vs team, red vs green). Regular modes (no teams) use
   all four — one distinct color per player slot, red/green/blue/purple in join order. */
/* Player slot tiles: skewed 40px squares with a team-colored bottom bar. Contents are
   counter-skewed so avatars/icons stay upright. */
.battle-slots{display:flex;align-items:center;gap:6px;margin-top:auto;margin-bottom:-6px}
.battle-slot{--slot:rgba(255,255,255,0.3);position:relative;display:flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:none;border-bottom:3px solid var(--slot);border-radius:3px;background:rgba(255,255,255,0.05);transform:skewX(-10deg);overflow:hidden;flex-shrink:0}
.battle-slot>img,.battle-slot>svg{transform:skewX(10deg)}
.battle-slot img{width:38px;height:38px;object-fit:contain}
.battle-slot img[src^="/assets/img/bots/"]{width:140%;max-width:none;height:100%;flex-shrink:0;object-fit:cover}
.battle-slot.empty{cursor:pointer;color:var(--slot);font-family:var(--font);transition:background .15s,filter .15s}
.battle-slot.empty:hover{background:rgba(255,255,255,0.11);filter:brightness(1.15)}
.battle-slot.empty:disabled{opacity:.5;cursor:default}
.battle-slot.empty svg{width:22px;height:22px}
.battle-slot.p-0{--slot:rgb(224,90,80)}
.battle-slot.p-1{--slot:rgb(120,205,145)}
.battle-slot.p-2{--slot:rgb(90,160,224)}
.battle-slot.p-3{--slot:rgb(178,120,224)}
.battle-slot.p-group{--slot:rgb(160,162,170)}
.battle-slot-vs{padding:0 5px;font-size:11px;font-weight:700;color:rgba(255,255,255,0.5);flex-shrink:0}
/* "Join battle" tooltip above an open slot, filled with the slot's team color; the caret
   below it inherits the same color. Positioned from JS. */
.slot-tooltip{position:fixed;z-index:180;padding:6px 10px;border-radius:7px;background:var(--tip-bg,#66852F);color:#fff;font-size:11.5px;font-weight:800;letter-spacing:.02em;white-space:nowrap;pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity .14s ease,transform .14s ease;font-family:var(--font);box-shadow:0 6px 18px rgba(0,0,0,0.45)}
.slot-tooltip::after{content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:var(--tip-bg,#66852F)}
.slot-tooltip.open{opacity:1;transform:translateY(0)}
.slot-tooltip.light{color:#151518}
/* Floating info card over a hovered battle-card case icon (positioned from JS). Same panel
   recipe as .dd-menu (the Show-N dropdown) so the two match. */
.battle-card-case.is-hidden{pointer-events:none;cursor:default}
.case-hover-card{position:fixed;z-index:180;display:flex;flex-direction:column;align-items:center;gap:0;padding:0;overflow:hidden;border-radius:13px;background:rgba(16,16,16,0.98);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border:1px solid rgba(255,255,255,0.1);box-shadow:0 16px 48px rgba(0,0,0,0.6);pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity .14s ease,transform .14s ease;font-family:var(--font);white-space:nowrap}
.case-hover-card.open{opacity:1;transform:translateY(0)}
.case-hover-name{padding:9px 16px 0;font-size:13px;font-weight:800;color:#fff}
.case-hover-price{display:flex;align-items:center;gap:6px;padding:4px 16px 9px;font-size:13px;font-weight:700;color:#fff}
.case-hover-price .scrap-icon{width:14px;height:14px}
/* Own strip along the bottom of the card. */
.case-hover-hint{display:flex;align-items:center;justify-content:center;gap:5px;width:100%;padding:6px 14px;border-top:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.04);font-size:11px;font-weight:600;color:rgba(255,255,255,0.5)}
.case-hover-hint svg{width:13px;height:13px}
/* Same taper as the lobby strip: solid through 55%, then dissolving to nothing at the right
   edge so the last icons ghost out toward the rounds text. */
.battle-card-cases-wrap{position:relative;flex:1;min-width:0}
.battle-card-cases{display:flex;align-items:center;gap:8px;width:100%;overflow:hidden;transform:translateY(4px);-webkit-mask-image:linear-gradient(to right,#000 55%,transparent 100%);mask-image:linear-gradient(to right,#000 55%,transparent 100%)}
.battle-card-case{cursor:pointer;position:relative;display:flex;align-items:center;justify-content:center;width:80px;height:80px;flex-shrink:0}
/* Started battles: one icon per round in a strip that slides left under a fixed red arrow; played
   rounds fade out through the left edge, upcoming ones fade in from the right. */
.battle-card-cases.strip{position:relative;-webkit-mask-image:linear-gradient(to right,transparent 0,#000 10%,#000 72%,transparent 100%);mask-image:linear-gradient(to right,transparent 0,#000 10%,#000 72%,transparent 100%)}
.battle-card-strip{display:flex;align-items:center;gap:8px;will-change:transform;transition:transform .55s cubic-bezier(.23,1,.32,1)}
.battle-card-strip.no-anim,.battle-card-arrow.no-anim{transition:none}
.battle-card-strip .battle-card-case{transition:opacity .4s ease,transform .45s cubic-bezier(.23,1,.32,1)}
.battle-card-strip .battle-card-case.past{transform:scale(.84)} /* played rounds: faded and a touch smaller */
.battle-card-arrow{position:absolute;left:40px;top:-10px;width:55px;height:55px;transform:translateX(-50%);transition:left .55s cubic-bezier(.23,1,.32,1);pointer-events:none;z-index:2;filter:drop-shadow(0 2px 4px rgba(0,0,0,0.6))}
.battle-card-arrow img{width:100%;height:100%;object-fit:contain}
.battle-card-case img{width:100%;height:100%;object-fit:contain;filter:drop-shadow(0 3px 8px rgba(0,0,0,0.5))}
.battle-card-case-qty{position:absolute;right:-2px;bottom:4px;min-width:21px;height:21px;padding:0 5px;border-radius:11px;background:rgba(255,255,255,0.16);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,0.18);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;color:#fff}
.battle-card-right{display:flex;align-items:center;gap:14px;flex-shrink:0}
.battle-card-rounds{font-size:14px;font-weight:700;color:rgba(255,255,255,0.55);white-space:nowrap}
.battle-card-eye-btn{width:38px;height:38px;flex-shrink:0;display:flex;align-items:center;justify-content:center;border-radius:9px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.55);cursor:pointer;transition:all .16s}
.battle-card-eye-btn:hover{color:rgba(255,255,255,0.85);border-color:rgba(255,255,255,0.16);background:rgba(255,255,255,0.05)}
.battle-card-eye-btn svg{width:17px;height:17px}
.battle-card-join-btn{flex-shrink:0;padding:11px 18px;border-radius:9px;border:1px solid var(--join-accent,#66852F);background:var(--join-accent,#66852F);color:color-mix(in srgb,var(--join-accent,#66852F) 28%,white);font-size:12.5px;font-weight:800;letter-spacing:.02em;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap}
.battle-card-join-btn:hover{filter:brightness(1.12)}
/* A battle that has started: WATCH GAME in a quiet grey, whitish text (no accent, no spectate eye). */
/* Finished: rounds + scrap won on the left, WINNERS (green) with the winning seats' pfps on the right. */
.battle-card-rounds-won{display:flex;flex-direction:column;align-items:flex-end;gap:3px}
.battle-card-won{display:flex;align-items:center;gap:5px;font-size:13px;font-weight:800;color:rgba(255,255,255,0.7);white-space:nowrap}
.battle-card-won img{width:14px;height:14px;object-fit:contain}
.battle-card-winners{display:flex;flex-direction:column;align-items:flex-end;gap:6px;margin-left:12px}
.battle-card-winners-label{font-size:12.5px;font-weight:800;letter-spacing:.04em;color:#7ED957}
.battle-card-winner-pfps{display:flex;gap:4px}
.battle-card-winner-pfps .battle-slot{width:36px;height:36px}
.battle-card-join-btn.watch{background:rgba(255,255,255,0.10);border-color:rgba(255,255,255,0.14);color:rgba(255,255,255,0.88)}
.battle-card-join-btn.watch:hover{filter:none;background:rgba(255,255,255,0.15)}
@media (max-width:820px){
  .battle-card{flex-wrap:wrap}
  .battle-card-cases-wrap{order:3;width:100%;margin-top:4px}
  .battle-card-right{order:2;margin-left:auto}
}
@media (max-width:480px){
  .battle-card-left{width:100%}
  .battle-card-right{width:100%;margin-left:0;justify-content:space-between}
  .battle-card-join-btn{flex:1}
}

/* ── Crate Battle setup ────────────────────────────────────────────────────── */
/* Constrained to the same 880px block as the config below, so the back button lines up with
   the left edge of the cards instead of the page. */
.battle-create-bar{position:relative;display:flex;align-items:center;max-width:880px;margin:34px auto 38px}
.battle-create-bar .case-detail-back{position:absolute;left:0;margin-top:0;margin-right:0}
.battle-create-title{flex:1;text-align:center;font-size:24px;font-weight:800;color:#fff;letter-spacing:.01em}
/* Battle lobby bar — same back-button-pinned-left layout as the create bar, but the center
   slot holds a title+modifier-list stack instead of just a title, and the right side gets its
   own icon-button cluster instead of nothing. */
/* Same 1180px band + 4px inset as .battle-lobby-info below it, so BACK TO BATTLES lines up
   with TOTAL and the share/sound buttons line up with the spectator count. */
#page-battle-lobby{--arena-w:min(1180px,100%)}
.battle-lobby-bar{justify-content:center;width:var(--arena-w);max-width:none;margin:34px 0 38px calc(50% - var(--arena-w)/2);padding:0}
.battle-lobby-bar .case-detail-back{margin-left:0}
.battle-lobby-heading .battle-create-title{font-size:20px}
.battle-lobby-heading{flex:1;display:flex;flex-direction:column;align-items:center;gap:10px}
.battle-lobby-modifiers{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:center}
.battle-lobby-modifier{display:flex;align-items:center;gap:4px;font-size:13px;font-weight:700}
.battle-lobby-modifier svg{width:15px;height:15px;flex-shrink:0}
.battle-lobby-actions{position:absolute;right:0;display:flex;align-items:center;gap:6px}

/* Info bar — TOTAL cost on the left, the rounds pill (case art background) centered, spectator
   count on the right. Same 880px column as the rest of the create/lobby content. A plain flex
   row with justify-content:space-between only centers the pill when the TOTAL and spectator
   blocks happen to be the same width — a 3-column grid with the pill in the middle column
   keeps it centered on the page regardless of how wide either side block is. */
.battle-lobby-info{position:relative;z-index:2;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;width:var(--arena-w);margin:0 0 0 calc(50% - var(--arena-w)/2);padding:0}
.battle-lobby-info>.battle-lobby-rounds-pill{justify-self:center}
.battle-lobby-info>.battle-lobby-spectators{justify-self:end}
.battle-lobby-total{display:flex;align-items:center;gap:7px;font-size:14px;font-weight:700;color:rgba(255,255,255,0.85)}
.battle-lobby-info-label{font-size:12px;font-weight:800;letter-spacing:.08em;color:rgba(255,255,255,0.5)}
.battle-lobby-total img{width:16px;height:16px;object-fit:contain}
.battle-lobby-spectators{display:flex;align-items:center;gap:6px;font-size:14px;font-weight:700;color:rgba(255,255,255,0.75)}
.battle-lobby-spectators svg{width:17px;height:17px;flex-shrink:0}

/* Tilted like the NEW UPDATE ribbon on the home cards: a slight rotation pivoting from the
   left edge so the right end lifts. Contents rotate with it. */
.battle-lobby-rounds-pill{position:relative;width:min(366px,calc(100vw - 460px));height:64px;border-radius:12px;transform:translateY(14px) rotate(1.5deg);transform-origin:left center;overflow:hidden;background:rgba(24,24,28,0.94);border:1px solid rgba(255,255,255,0.08);display:flex;align-items:center;justify-content:flex-end;padding:0 14px}
/* One small icon per distinct case, left-aligned and vertically centered in the pill, then
   faded out toward the pill's bottom edge — a much smaller/cropped version of what it looked
   like when a single oversized image bled off the top of the pill. */
/* Art row runs the pill's width; icons only dim a little toward the right and stay visible
   under the "N rounds" label, which sits above them. */
.battle-lobby-rounds-art{position:absolute;left:14px;right:14px;top:0;bottom:0;display:flex;align-items:center;gap:8px;overflow:hidden;-webkit-mask-image:linear-gradient(to right, #000 55%, transparent 100%);mask-image:linear-gradient(to right, #000 55%, transparent 100%)}
.battle-lobby-rounds-art img{cursor:pointer;flex-shrink:0;width:48px;height:48px;object-fit:contain;filter:drop-shadow(0 3px 8px rgba(0,0,0,0.5))}
.battle-lobby-rounds-strip{display:flex;align-items:center;gap:8px;will-change:transform;transition:transform .65s cubic-bezier(.22,1,.36,1)}
.battle-lobby-rounds-strip.no-anim{transition:none}
/* Playing: case name + cost on the left, a 4-icon window in the middle, k/N on the right. */
.battle-lobby-rounds-pill.playing{justify-content:space-between} /* same width as before the start */
.battle-lobby-rounds-current{position:relative;z-index:2;display:none;flex-direction:column;justify-content:center;gap:1px;width:90px;flex-shrink:0}
.battle-lobby-rounds-pill.playing .battle-lobby-rounds-current{display:flex}
.battle-lobby-rounds-current-name{font-size:13px;font-weight:800;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 1px 4px rgba(0,0,0,0.6)}
.battle-lobby-rounds-current-price{display:flex;align-items:center;gap:4px;font-size:13px;font-weight:800;color:#fff;text-shadow:0 1px 4px rgba(0,0,0,0.6)}
.battle-lobby-rounds-current-price img{width:14px;height:14px;object-fit:contain}
/* The icon window runs the whole pill; icons fade out at both edges (under the case name on the left, under the k/N label on the right). */
.battle-lobby-rounds-pill.playing .battle-lobby-rounds-art{left:14px;right:14px;-webkit-mask-image:linear-gradient(to right,transparent 0,#000 22%,#000 62%,transparent 92%);mask-image:linear-gradient(to right,transparent 0,#000 22%,#000 62%,transparent 92%)}
/* While playing only the case being opened is full size and solid, sitting right beside its name; the rest are a touch smaller and see-through. */
.battle-lobby-rounds-pill.playing .battle-lobby-rounds-strip img{transform:scale(.82);opacity:.55;transition:transform .45s cubic-bezier(.22,1,.36,1),opacity .45s ease}
.battle-lobby-rounds-pill.playing .battle-lobby-rounds-strip img.current{transform:scale(1);opacity:1} /* full width: finished icons slide out through the left edge, fading under the case name */
/* Plain text on top of the (already faded) tail of the icon row. */
/* Arena stage under the info row: full band width, fixed height (tweakable), cover art. */
.battle-lobby-arena{position:relative;z-index:1;width:var(--arena-w);height:360px;margin:0 0 30px calc(50% - var(--arena-w)/2);border-radius:16px;background:#0d0d10 url("/assets/img/battles/arena-bg.jpg") center/cover no-repeat;border:1px solid rgba(255,255,255,0.06)}
/* The round reel inside the arena: no box of its own (the lanes float straight over the arena
   art), arrows pinned to the arena's own left/right edges, items a touch larger than the case
   opener's, and the landed item swells a little. */
.battle-spin-wrap{position:absolute;left:0;right:0;top:0;bottom:0;z-index:2}
.battle-spin-wrap .multi-spin-viewport{display:grid;gap:10px;height:100%;padding:0 10px 0 0;background:none;border:none;border-radius:0}
.battle-spin-wrap .multi-spin-arrow img{width:70px;height:70px}
/* As a round starts, each arrow kicks outward and eases back into place. */
.battle-spin-wrap .multi-spin-arrow.left.kick{animation:arrowKickLeft .7s cubic-bezier(.22,1,.36,1)}
.battle-spin-wrap .multi-spin-arrow.right.kick{animation:arrowKickRight .7s cubic-bezier(.22,1,.36,1)}
@keyframes arrowKickLeft{0%{transform:translateY(-50%) translateX(0)}35%{transform:translateY(-50%) translateX(-22px)}100%{transform:translateY(-50%) translateX(0)}}
@keyframes arrowKickRight{0%{transform:translateY(-50%) translateX(0)}35%{transform:translateY(-50%) translateX(22px)}100%{transform:translateY(-50%) translateX(0)}}
.battle-spin-wrap .spin-slot>img{filter:none}
.battle-spin-wrap .multi-spin-arrow.left{left:-26px}
.battle-spin-wrap .multi-spin-arrow.right{right:-26px}
.battle-spin-wrap .spin-slot{width:150px;height:150px}
.battle-spin-wrap .spin-slot>img,.battle-spin-wrap .spin-slot>.slot-placeholder{width:120px;height:120px}
.battle-spin-wrap .spin-track.settled .spin-slot.landed{transform:scale(1.14);transition:transform 1.1s cubic-bezier(.16,1,.3,1)}
/* Bonus Spin: the C4 bait tile, the explosion held over it, and the item won off the respin. */
.spin-slot.bait .slot-price{display:none}
.battle-spin-wrap .spin-slot.bait>img{width:112px;height:112px;object-fit:contain}
.respin-boom{position:absolute;left:50%;top:calc(50% + 8px);transform:translate(-50%,-50%);pointer-events:none;z-index:5} /* on the lane, over the landing spot */
.respin-boom-frame{flex-shrink:0;background-repeat:no-repeat;background-position:0 0;animation:respinPop .3s cubic-bezier(.34,1.56,.64,1) both}
@keyframes respinPop{from{transform:scale(.4);opacity:0}60%{transform:scale(1.14);opacity:1}to{transform:scale(1);opacity:1}}
.spin-slot.respin-won .slot-box{box-shadow:0 0 30px rgba(var(--rarity),0.6)}
/* Round card once its seat has pulled an item. */
/* Same rarity wash as the "Items in this case" cards on the case page. */
.round-card.filled{position:relative;justify-content:flex-start;padding-top:30px;gap:5px;background:radial-gradient(ellipse 100% 110% at 50% 0%,rgba(var(--rarity,120,205,145),0.35) 0%,rgba(var(--rarity,120,205,145),0.03) 75%,rgba(255,255,255,0.03) 100%);background-clip:padding-box}
.round-card-idx{position:absolute;top:10px;left:16px;font-size:19px;font-weight:800;color:rgba(255,255,255,0.7);font-family:var(--font);line-height:1}
.round-card-idx::before{content:"#";position:absolute;top:-7px;left:-11px;font-size:18px;font-weight:300;opacity:.4;color:#fff}
.round-card-pct{position:absolute;top:10px;right:12px;font-size:11px;font-weight:700;color:rgba(255,255,255,0.75);font-family:var(--font);opacity:0;transition:opacity .15s}
.round-card.filled:hover .round-card-pct,.round-card-pct.always{opacity:1}
/* Rare pulls: the always-on badge glows in the item's rarity color. */
.round-card-pct.always{opacity:.8;font-weight:800;color:#f4f4f4;text-shadow:0 2px 8px var(--item-color,#fff)}
.round-card-img{width:88px;height:88px;object-fit:contain}
.round-card-name{max-width:calc(100% - 16px);margin-top:6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:14.5px;font-weight:700;color:var(--item-color,#fff);font-family:var(--font)}
.round-card-price{display:flex;align-items:center;gap:5px;margin-top:1px;font-size:13.5px;font-weight:800;color:#fff;font-family:var(--font)}
.round-card-price img{width:16px;height:16px;object-fit:contain}
/* Dud landings: text instead of a 0.00 price, in the reel and on the round card. */
.dud-note{font-size:12px;font-weight:600;font-style:italic;color:rgba(255,255,255,0.6);white-space:normal;text-align:center;line-height:1.2}
.battle-spin-wrap .spin-slot .slot-price.dud-note{font-size:13px;text-shadow:0 1px 4px rgba(0,0,0,0.9)}
/* Confetti canvas covering just the arena (clips the burst to the arena art). */
.arena-confetti{position:absolute;inset:0;width:100%;height:100%;z-index:3;pointer-events:none;border-radius:inherit}
/* Jackpot finale reel: a flat team-colored bar the full width of the arena. Its two halves
   slide in from the arena's left and right edges and meet in the middle, then fold back out
   the same way after the landing. Red arrow above the center, black line down the bar. */
.jackpot-wrap{position:absolute;left:0;right:0;top:50%;height:74px;transform:translateY(-50%);z-index:2;clip-path:inset(-80px 0 -24px 0)} /* clipped at the arena's sides, open above for the arrow and below for the line's tail */
.jackpot-half{position:absolute;top:0;bottom:0;width:50%;overflow:hidden}
/* Outer ends fade to nothing so the strip reads as sliding through the scene. */
.jackpot-half.left{left:0;-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 22%);mask-image:linear-gradient(90deg,transparent 0,#000 22%)}
.jackpot-half.right{right:0;-webkit-mask-image:linear-gradient(270deg,transparent 0,#000 22%);mask-image:linear-gradient(270deg,transparent 0,#000 22%)}
.jackpot-half.right .jackpot-reel{margin-left:-100%}
.jackpot-reel{position:absolute;top:0;left:0;height:100%;display:flex;will-change:transform}
.jackpot-strip{display:flex;flex-shrink:0;height:100%}
/* Team color with a clean texture: fine diagonal pinstripes, a soft top-to-bottom sheen, and a
   thin dark seam between neighbouring slices. */
.jackpot-slice{position:relative;display:flex;align-items:center;justify-content:center;height:100%;flex-shrink:0;overflow:hidden;transition:width 1.3s cubic-bezier(.22,1,.36,1);background:repeating-linear-gradient(-45deg,rgba(255,255,255,0.10) 0 5px,rgba(255,255,255,0) 5px 14px),linear-gradient(180deg,rgba(255,255,255,0.18) 0%,rgba(255,255,255,0) 45%,rgba(0,0,0,0.22) 100%),rgba(var(--c),0.74);box-shadow:inset 1px 0 0 rgba(0,0,0,0.28),inset 0 1px 0 rgba(255,255,255,0.14)}
.jackpot-slice-avatars{display:flex;gap:6px}
.jackpot-slice img{width:36px;height:36px;border-radius:6px;object-fit:cover;background:rgba(0,0,0,0.3);box-shadow:0 2px 8px rgba(0,0,0,0.5);flex-shrink:0}
/* The scene behind the bar goes dark while it's up. */
.battle-lobby-arena.jackpot-dim::after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit;pointer-events:none;background:rgba(0,0,0,0.5);transition:opacity .55s ease}
.battle-lobby-arena.jackpot-dim.jackpot-out::after{opacity:0}
/* Skinny black line from the arrow's tip straight down to the bottom edge of the bar. Its own
   element (not a pseudo on the arrow) so the arrow's drop-shadow filter can't blur it. The arrow PNG
   has transparent padding: at 64px its drawn tip is 43.6px below the arrow box's top. */
/* Needle: a 1px line at the exact center spanning the bar's full height, red in the middle fading
   to nothing at both ends; above the reel, never moves — the reel slides beneath it. */
.jackpot-line{position:absolute;left:50%;top:0;bottom:0;width:1px;margin-left:-0.5px;background:linear-gradient(transparent,#f00,transparent);z-index:3;pointer-events:none} /* straddles the exact center, where the arrow tip is */
.jackpot-arrow{position:absolute;left:50%;top:-24px;transform:translateX(-50%);z-index:4;filter:drop-shadow(0 2px 6px rgba(0,0,0,0.6))}
.jackpot-arrow img{width:64px;height:64px;display:block;object-fit:contain}
.jackpot-wrap.entering .jackpot-half.left{animation:jackpotInLeft .7s cubic-bezier(.22,1,.36,1) both}
.jackpot-wrap.entering .jackpot-half.right{animation:jackpotInRight .7s cubic-bezier(.22,1,.36,1) both}
.jackpot-wrap.entering .jackpot-arrow,.jackpot-wrap.entering .jackpot-line{animation:fadeIn .3s ease .6s both}
/* One win % per team, centered over that team's columns, above the name plates. */
.arena-pcts{position:absolute;inset:0;z-index:2;pointer-events:none}
.arena-pcts .arena-pct{position:absolute;bottom:auto;transform:translate(-50%,calc(-100% - 40px));text-align:center;transition:top .35s ease}
/* Cursed flip: old value drops out below as the inverted one slides in from above. */
.arena-pct .pct-val{display:block}
.arena-pct .pct-val.out{position:absolute;left:0;right:0;top:0;animation:pctOut .45s ease both}
.arena-pct .pct-val.in{animation:pctIn .45s ease both}
@keyframes pctOut{to{transform:translateY(16px);opacity:0}}
@keyframes pctIn{from{transform:translateY(-16px);opacity:0}}
/* Cursed: a red skull panel hides in every slice; they snap in together (~100ms) while the slice
   widths morph underneath to the cursed shares, then fade back off (~220ms) before the spin. */
.jackpot-slice-cursed{position:absolute;inset:0;z-index:1;display:flex;align-items:center;justify-content:center;background:#eb4d4b;color:#7d1513;opacity:0;pointer-events:none;transition:opacity .22s ease}
.jackpot-slice-cursed svg{width:46px;height:46px;display:block}
.jackpot-wrap.cursed-in .jackpot-slice-cursed{opacity:1;transition-duration:.1s}
.jackpot-wrap.cursed-in.cursed-out .jackpot-slice-cursed{opacity:0;transition-duration:.22s}
/* After the landing the bar, arrow, dim and % labels all fade out together. */
.jackpot-wrap.leaving{opacity:0;transition:opacity .55s ease}
.arena-pcts.leaving{opacity:0;transition:opacity .55s ease}
@keyframes jackpotInLeft{from{transform:translateX(-100%)}to{transform:translateX(0)}}
@keyframes jackpotInRight{from{transform:translateX(100%)}to{transform:translateX(0)}}
/* Win chance above each name plate during / after a jackpot finale, in the team color. */
.arena-pct{position:absolute;left:50%;bottom:calc(100% + 34px);transform:translateX(-50%);font-size:17px;font-weight:800;font-family:var(--font);white-space:nowrap;text-shadow:0 2px 8px rgba(0,0,0,0.6);animation:fadeIn .4s ease both}
/* End-of-battle totals: same column grid as the player row, one big number per team. */
.arena-totals{position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);z-index:2;display:grid;gap:10px;padding:0 10px 0 0;align-items:center}
.arena-total img{width:40px;height:40px;object-fit:contain}
/* Winner: a small float, then a launch straight up and off the arena. Others: slide to the
   middle and fade as they combine; the grand total then pops in centered. */
.arena-total{display:flex;align-items:center;justify-content:center;gap:10px;font-size:38px;font-weight:800;color:#fff;font-family:var(--font);text-shadow:0 2px 12px rgba(0,0,0,0.7);font-variant-numeric:tabular-nums;transition:transform .8s cubic-bezier(.22,1,.36,1),opacity .6s ease}
.arena-total.float{transform:translateY(-10px) scale(1.12)}
/* No keyframe animation on the base totals — a lingering fill-mode value stops the opacity transition from running. */
.arena-total.launch{animation:none;transform:translateY(-150px) scale(1.12);opacity:0;transition:transform 1.7s cubic-bezier(.35,0,.6,.5),opacity 1.2s ease .5s} /* rises to just under the arena top and is fully gone by then */
.arena-total.merge{animation:none;transform:translateX(var(--dx,0px)) scale(.85);opacity:0;transition:transform .7s cubic-bezier(.22,1,.36,1),opacity .55s ease .2s}
.arena-total.center{grid-column:1 / -1;animation:totalPop .5s cubic-bezier(.22,1,.36,1) both}
@keyframes totalPop{from{transform:scale(.7);opacity:0}to{transform:scale(1);opacity:1}}

/* Final Draw's last round: an orange wash in from both sides of the arena while it spins. */
.battle-lobby-arena.final-round::after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit;pointer-events:none;background:radial-gradient(circle, transparent, rgba(255,215,0,0.2))}
/* Final Draw's last-round card: the mode's orange instead of the item's rarity, icon by the badge. */
.round-card-final{width:15px;height:15px;margin-left:3px;position:relative;top:-6px;color:#FFD700}
/* Centered status line ("Waiting for players", later round/turn text) above the overlay. */
.battle-lobby-arena-status{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:1;font-size:16px;font-weight:400;color:rgba(255,255,255,0.5);letter-spacing:.01em;white-space:nowrap;font-family:var(--font)}
.battle-lobby-arena-status.starting{text-align:center;font-size:20px;font-weight:800;letter-spacing:.06em;color:rgba(255,255,255,0.7)}
.arena-countdown{display:block;margin-top:6px;font-size:36px;font-weight:800;letter-spacing:.04em;color:#fff;font-variant-numeric:tabular-nums}
/* Arena player row: evenly spread columns along the bottom of the arena. */
.arena-players{position:absolute;left:0;right:0;bottom:-24px;z-index:2;display:flex;align-items:center;justify-content:space-around;gap:14px;padding:0 24px}
.arena-player{position:relative;display:flex;align-items:center;gap:10px;transform:translateY(var(--dy,0px)) rotate(var(--rot,0deg))}
/* Winning seat: green "+ amount" floating above the slot, and the whole column bobs slowly. */
.arena-win{position:absolute;left:50%;bottom:calc(100% + 10px);transform:translateX(-50%);display:flex;align-items:center;gap:6px;font-size:19px;font-weight:800;color:#6CBF4B;font-family:var(--font);white-space:nowrap;text-shadow:0 2px 8px rgba(0,0,0,0.6);animation:fadeIn .4s ease both} /* the WINNERS green, toned down a step */
.arena-win img{width:19px;height:19px;object-fit:contain}
.arena-player.winner{animation:winBob 2.4s ease-in-out infinite}
@keyframes winBob{0%,100%{transform:translateY(var(--dy,0px)) rotate(var(--rot,0deg))}50%{transform:translateY(calc(var(--dy,0px) - 9px)) rotate(var(--rot,0deg))}}
.arena-tile{--slot:rgba(255,255,255,0.3);position:relative;display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:48px;height:48px;padding:0;border:none;border-left:4px solid var(--slot);border-bottom:4px solid var(--slot);border-radius:3px;background:rgba(18,18,22,0.92);transform:skewX(-10deg);overflow:hidden;flex-shrink:0;font-family:var(--font)}
.arena-tile>img,.arena-tile>svg{transform:skewX(10deg)}
.arena-tile img{width:36px;height:36px;object-fit:contain}
/* Bot pfps are photos, not item icons — fill the tile edge to edge. The tile is skewed and the
   image counter-skewed, so the image is oversized sideways to cover the tile's slanted corners. */
.arena-tile img[src^="/assets/img/bots/"]{width:140%;max-width:none;height:100%;flex-shrink:0;object-fit:cover}
.arena-tile.empty{cursor:pointer;color:var(--slot);transition:background .15s,filter .15s,transform .18s ease}
.arena-tile.empty:hover{background:rgba(48,48,54,0.95)}
.arena-tile.empty:disabled{opacity:.5;cursor:default}
.arena-tile.empty svg{width:22px;height:22px}
.arena-tile.p-0{--slot:rgb(224,90,80)}
.arena-tile.p-1{--slot:rgb(120,205,145)}
.arena-tile.p-2{--slot:rgb(90,160,224)}
.arena-tile.p-3{--slot:rgb(178,120,224)}
.arena-tile.p-group{--slot:rgb(160,162,170)}
.arena-plate{display:flex;align-items:center;gap:9px;box-sizing:border-box;width:160px;height:48px;padding:0 18px;border:none;border-radius:3px;background:rgba(32,32,36,0.9);transform:skewX(-10deg);color:#fff;font-size:15px;font-weight:700;font-family:var(--font);white-space:nowrap}
.arena-plate>*{transform:skewX(10deg)}
.arena-plate-icon{display:flex;color:#8cc2e7}
.arena-plate-icon svg{width:1.25em;height:1em}
.arena-plate-bot,.arena-plate-join{cursor:pointer;transition:background .15s,transform .18s ease}
.arena-plate-join.locked{cursor:not-allowed;opacity:.6}
.battle-card-join-btn.locked{--join-accent:#3a3a40;color:rgba(255,255,255,0.55);cursor:not-allowed}
.battle-card-join-btn.locked:hover{filter:none;transform:none}
/* Hovering either the arrow tile or the plate lifts both together. */
.arena-player:hover .arena-plate-bot,.arena-player:hover .arena-plate-join{transform:skewX(-10deg) translateY(-3px)}
.arena-player:hover .arena-tile.empty{transform:skewX(-10deg) translateY(-3px)}
.arena-plate-bot:hover,.arena-plate-join:hover{background:rgba(48,48,54,0.95)}
/* 6-slot rows (3v3, 2v2v2): tighter gaps/padding and slightly smaller plates so all six
   columns plus the "vs" chips fit inside the arena. */
.arena-players.many{justify-content:center;gap:24px}
/* Group unbox rows mirror .battle-lobby-rounds-grid's columns (same gap + scrollbar inset). */
.arena-players.group-align{display:grid;grid-template-columns:repeat(var(--slots,3),minmax(0,1fr));justify-items:center;gap:10px;padding:0 10px 0 0}
.arena-players.group-align .arena-vs{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%) rotate(1.5deg)} /* left is set per chip by positionArenaVs() */
.arena-players.crowded .arena-player{gap:8px}
.arena-players.crowded .arena-plate{width:140px;padding:0 12px;font-size:13.5px}
.arena-players.crowded .arena-vs{padding:6px 9px;font-size:15px}
.arena-plate-cost{display:flex;align-items:center;gap:5px;margin-left:auto;font-weight:800}
.arena-plate-cost img{width:16px;height:16px;object-fit:contain}
.arena-vs{display:inline-block;padding:7px 11px;border-radius:6px;background:rgba(32,32,36,0.9);transform:rotate(1.5deg);font-size:16.5px;font-weight:800;color:rgba(255,255,255,0.85);letter-spacing:.03em;flex-shrink:0}
/* While a different battle is being fetched, the parts that differ per battle stay hidden. */
#page-battle-lobby.loading>*{visibility:hidden}
/* Round cards under the arena: same width/centering as the arena, one column per slot. */
.battle-lobby-rounds-grid{--slots:2;--col-min:0px;position:relative;z-index:1;display:grid;grid-template-columns:repeat(var(--slots),minmax(0,1fr));gap:10px;box-sizing:border-box;width:var(--arena-w);max-height:430px;overflow-y:auto;overflow-x:hidden;padding-right:10px;margin:58px 0 40px calc(50% - var(--arena-w)/2)}
/* Chrome ignores the ::-webkit-scrollbar rules (and shows its stock arrow buttons) as soon as
   scrollbar-width/scrollbar-color are set, so those only apply where the webkit ones don't. */
@supports not selector(::-webkit-scrollbar){.battle-lobby-rounds-grid{scrollbar-width:thin;scrollbar-color:rgba(255,255,255,0.22) rgba(255,255,255,0.05)}}
.battle-lobby-rounds-grid::-webkit-scrollbar{width:8px}
.battle-lobby-rounds-grid::-webkit-scrollbar-button{display:none;width:0;height:0}
.battle-lobby-rounds-grid::-webkit-scrollbar-track{background:rgba(255,255,255,0.05);border-radius:4px}
.battle-lobby-rounds-grid::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.22);border-radius:4px}
.battle-lobby-rounds-grid::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,0.32)}
/* Each player's column: its rounds in order, --per-row cards across (2 on wide columns). */
.round-col{display:grid;grid-template-columns:repeat(var(--per-row,1),minmax(0,1fr));gap:10px;align-content:start}
.team-spacer{min-width:0}
.round-card{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;height:190px;border-radius:4px;background:rgba(58,58,60,0.55);border:1px solid rgba(255,255,255,0.05)}
.round-card-label{font-size:12px;font-weight:800;letter-spacing:.1em;color:rgba(255,255,255,0.35);font-family:var(--font)}
.round-card-num{font-size:30px;font-weight:800;color:rgba(255,255,255,0.4);font-family:var(--font);line-height:1}
/* Dark wash over the art so slots/text placed on it read clearly. */
.battle-lobby-arena::before{content:"";position:absolute;inset:0;border-radius:inherit;background:rgba(0,0,0,0.70);pointer-events:none}
.battle-lobby-rounds-count{position:relative;z-index:2;font-size:14.5px;font-weight:800;color:#fff;text-shadow:0 1px 4px rgba(0,0,0,0.6)}
.battle-section-title{max-width:880px;margin-left:auto;margin-right:auto;margin-top:76px;font-size:14px;font-weight:800;letter-spacing:.09em;color:rgba(255,255,255,0.92)}
.battle-section-sub{max-width:880px;margin-left:auto;margin-right:auto;margin-top:6px;font-size:15px;color:rgba(255,255,255,0.6)}
/* Three equal columns, but the row is capped below the full page width so the cards aren't
   stretched far wider than the icon + toggles they hold. */
.battle-modes{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:20px;max-width:880px;margin-left:auto;margin-right:auto}
.battle-mode-group{display:flex;align-items:center;gap:14px;padding:16px;border:1px solid rgba(255,255,255,0.07);border-radius:13px;background:rgba(255,255,255,0.02)}
.battle-mode-body{flex:1;min-width:0}
.battle-mode-name{font-size:15px;font-weight:700;color:#fff}
/* The source icons are light, so a red drop-shadow under a fully-offset image recolours them
   without needing a second asset per state. */
.battle-mode-icon{width:40px;height:40px;object-fit:contain;flex-shrink:0;filter:brightness(0) invert(1);transition:filter .16s}
.battle-mode-group.has-selection .battle-mode-icon{filter:brightness(0) saturate(100%) invert(28%) sepia(46%) saturate(1512%) hue-rotate(331deg) brightness(93%) contrast(92%)}
.battle-mode-opts{display:flex;gap:7px;margin-top:9px}
.battle-mode-opt{padding:7px 12px;border-radius:10px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.65);font-size:13px;font-weight:700;font-family:var(--font);cursor:pointer;transition:all .16s;white-space:nowrap}
.battle-mode-opt:hover{color:#fff;border-color:rgba(255,255,255,0.18);background:rgba(255,255,255,0.06)}
.battle-mode-opt.selected{background:#8C3A32;border-color:#8C3A32;color:#F3D3D0}

/* ── Add battle rounds ─────────────────────────────────────────────────────── */
.battle-rounds-bar{display:flex;align-items:center;justify-content:space-between;gap:20px;max-width:880px;margin:44px auto 0}
/* The shared .battle-section-title centres itself inside the 880px block; here it sits at the
   start of a flex row instead, so those auto margins have to be cleared. */
.battle-rounds-title{margin:0;max-width:none}
.battle-rounds-title-cost{font-weight:600;letter-spacing:normal;color:rgba(255,255,255,0.55);display:inline-flex;align-items:center;gap:4px}
.battle-rounds-title-cost img{width:13px;height:13px;object-fit:contain}
.battle-toggle{display:flex;align-items:center;gap:11px;padding:0;border:none;background:none;cursor:pointer;font-family:var(--font)}
.battle-toggle-label{font-size:12.5px;font-weight:800;letter-spacing:.09em;color:rgba(255,255,255,0.6)}
.battle-toggle-track{position:relative;width:46px;height:25px;flex-shrink:0;border-radius:999px;background:rgba(255,255,255,0.13);transition:background .22s ease}
.battle-toggle-dot{position:absolute;top:3px;left:3px;width:19px;height:19px;border-radius:50%;background:rgba(255,255,255,0.75);transition:transform .22s cubic-bezier(.22,1,.36,1),background .22s ease}
.battle-toggle.on .battle-toggle-track{background:#3F6B2B}
.battle-toggle.on .battle-toggle-dot{transform:translateX(21px);background:#A6E05F}
.modifier-card .modifier-toggle.on .battle-toggle-track{background:color-mix(in srgb, var(--mc) 35%, transparent)}
.modifier-card .modifier-toggle.on .battle-toggle-dot{background:var(--mc)}
#customSortingToggle .battle-toggle-track{width:41.7px;height:22.7px}
#customSortingToggle .battle-toggle-dot{width:17.2px;height:17.2px}
#customSortingToggle.on .battle-toggle-dot{transform:translateX(19px)}
.battle-rounds-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;max-width:880px;margin:16px auto 0}
/* Same lift-on-hover as the case cards on /cases, so the two grids feel like one system. */
.battle-add-crate{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;min-height:240.75px;padding:16px;border-radius:12px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);cursor:pointer;font-family:var(--font);transition:transform .6s cubic-bezier(.16,1,.3,1),border-color .3s ease,background .3s ease}
.battle-add-crate:hover{transform:translateY(-3px);border-color:rgba(255,255,255,0.18);background:rgba(255,255,255,0.05)}
.battle-add-crate-box{display:flex;align-items:center;justify-content:center;width:68px;height:68px;border:2px dashed rgba(255,255,255,0.28);border-radius:8px;transition:border-color .3s ease}
.battle-add-crate:hover .battle-add-crate-box{border-color:rgba(255,255,255,0.45)}
/* The source PNG is a blue plus on transparency. A light-blue disc is painted behind it via the
   parent, and the glyph itself is knocked down to near-black — filtering the img alone would
   invert its own background too. */
.battle-add-crate-icon{display:flex;align-items:center;justify-content:center;width:39px;height:39px;border-radius:50%;background:#A9D4F5}
.battle-add-crate-icon img{width:23px;height:23px;object-fit:contain;filter:brightness(0)}
.battle-add-crate-label{margin-top:3px;font-size:12.5px;font-weight:800;letter-spacing:.05em;color:#4A9FE0}

.battle-round-card{--glow:120,205,145;position:relative;display:flex;flex-direction:column;align-items:center;padding:10px 8px 12px;border-radius:12px;border:1px solid rgba(255,255,255,0.045);background:rgba(255,255,255,0.008);cursor:pointer;box-sizing:border-box;transition:transform .3s cubic-bezier(.16,1,.3,1),border-color .3s ease,background .3s ease}
.battle-round-card:hover{transform:translateY(-3px);border-color:rgba(255,255,255,0.14);background:rgba(255,255,255,0.02);z-index:2}
.battle-round-card-preview{position:absolute;top:2px;left:2px;width:26px;height:26px;display:flex;align-items:center;justify-content:center;color:rgba(255,255,255,0.75);opacity:0;transition:opacity .15s;z-index:5;pointer-events:none}
.battle-round-card:hover .battle-round-card-preview{opacity:1}
.battle-round-card-preview svg{width:16px;height:16px}
.battle-round-card-name{font-size:14.5px;font-weight:600;color:rgba(255,255,255,0.85);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center;width:100%}
.battle-round-card-price{display:flex;align-items:center;justify-content:center;gap:5px;font-size:13px;font-weight:600;color:rgba(255,255,255,0.6);margin-top:6px}
.battle-round-card-price img{width:14px;height:14px;object-fit:contain}
.battle-round-card-art{width:100%;aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;position:relative;margin-top:8px}
.battle-round-card-art img{width:78%;height:78%;object-fit:contain;filter:drop-shadow(0 0 0 rgba(var(--glow),0));transition:filter .5s ease}
.battle-round-card:hover .battle-round-card-art img{filter:drop-shadow(0 0 14px rgba(var(--glow),0.55))}
.battle-round-card-slider{position:relative;width:75%;height:4px;display:flex;gap:3px;margin-top:8px}
.battle-round-card-slider .seg{flex:1;height:100%;border-radius:3px;background:rgba(255,255,255,0.12)}
.battle-round-card-slider .seg.lit:nth-child(1){background:rgb(120,205,145)}
.battle-round-card-slider .seg.lit:nth-child(2){background:rgb(240,160,55)}
.battle-round-card-slider .seg.lit:nth-child(3){background:rgb(235,80,70)}
.battle-round-card-slider .pin{position:absolute;top:-2.5px;width:3px;height:9px;border-radius:2px;background:#fff;transform:translateX(-50%)}
.battle-round-card-qty{display:flex;align-items:center;justify-content:center;gap:10px;width:75%;margin-top:10px}
.battle-round-card-remove{display:flex;align-items:center;justify-content:center;gap:8px;width:75%;margin-top:10px;padding:9px 8px;border-radius:9px;border:1px solid rgba(255,255,255,0.06);background:rgba(255,255,255,0.04);color:rgb(235,140,130);font-size:12.5px;font-weight:800;font-family:var(--font);letter-spacing:.02em;cursor:pointer;transition:background .15s ease}
.battle-round-card-remove:hover{background:rgba(255,255,255,0.07)}
.battle-round-card-remove svg{width:15px;height:15px;flex-shrink:0}
.battle-round-card-menu{position:absolute;top:2px;right:2px;width:26px;height:26px;display:flex;align-items:center;justify-content:center;color:rgba(255,255,255,0.55);z-index:5}
.battle-round-card-menu svg{width:16px;height:16px}
.battle-round-card[data-unit]{cursor:grab}
/* Custom sorting cards skip the hover lift/border/background highlight the grouped cards
   use — with drag-to-reorder in play, that highlight fighting for the same visual space as
   the drag interaction read as noisy rather than useful. */
.battle-round-card[data-unit]:hover{transform:none;border-color:rgba(255,255,255,0.045);background:rgba(255,255,255,0.008)}
/* SortableJS's own class names — it toggles these itself, styling is on us. .ghost is the
   placeholder left in the list at the drop position; .sortable-chosen is the original card
   being dragged. */
.battle-round-card.ghost{opacity:0.35;background:rgba(255,255,255,0.03)}
.battle-round-card.sortable-chosen{cursor:grabbing}

/* ── Battle modifiers ──────────────────────────────────────────────────────── */
.modifiers-title{max-width:880px;margin:44px auto 0}
.modifiers-grid{display:grid;grid-template-columns:repeat(2,1fr);grid-auto-rows:min-content;align-items:start;gap:14px;max-width:880px;margin:16px auto 0}
.modifier-card{display:flex;align-items:center;gap:14px;padding:16px 18px;border-radius:13px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.03);cursor:pointer;transition:transform .6s cubic-bezier(.16,1,.3,1),border-color .3s ease,background .3s ease,opacity .22s ease,scale .22s ease}
.modifier-card-hiding{opacity:0;scale:.94;pointer-events:none}
.modifier-card-hidden{display:none}
.battle-create-submit-bar{max-width:880px;margin:24px auto 0;display:flex;justify-content:flex-end;gap:12px}
.battle-share-setup-btn{display:none;margin-right:auto;padding:16px 32px;border-radius:12px;border:1px solid rgba(74,143,217,0.3);background:#265c81;color:#b2d6ef;font-size:15px;font-weight:800;letter-spacing:.02em;font-family:var(--font);cursor:pointer;transition:background .16s}
.battle-share-setup-btn.visible{display:inline-flex}
.battle-share-setup-btn:hover{background:#2d6c98}
/* "+ [icon] amount": the creator's funding share on the create page. */
.battle-create-funding{display:flex;align-items:center;gap:4px;margin-left:2px;color:#6FBF6F;font-weight:800}
.battle-create-funding svg{width:16px;height:16px}
.battle-create-total{display:none;align-items:center;justify-content:center;gap:8px;padding:16px 20px;border-radius:12px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.05);font-size:15px;font-weight:700;color:rgba(255,255,255,0.75)}
.battle-create-total.visible{display:flex}
.battle-create-total img{width:18px;height:18px;object-fit:contain}
.battle-create-submit-btn{padding:16px 32px;border-radius:12px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.05);color:rgba(255,255,255,0.4);font-size:15px;font-weight:800;letter-spacing:.02em;font-family:var(--font);cursor:default;transition:all .16s}
.battle-create-submit-btn.ready{cursor:pointer;background:#66852F;border-color:#66852F;color:#DDF2B8}
.battle-create-submit-btn.ready:hover{background:#75993a}
.modifiers-grid.group-unbox-order [data-modifier-order="private"]{order:1}
.modifiers-grid.group-unbox-order [data-modifier-order="fast"]{order:2}
.modifiers-grid.group-unbox-order [data-modifier-order="partialfunding"]{order:3}
.modifiers-grid.group-unbox-order [data-modifier-order="banditspins"]{order:4}
.modifier-card-expandable{display:block;cursor:default}
.modifier-card-row{display:flex;align-items:center;gap:14px;cursor:pointer}
.modifier-pct{font-size:19px;font-weight:800;color:var(--mc);width:44px;text-align:right;opacity:0;white-space:nowrap;transition:opacity .3s ease}
.modifier-card-expandable.expanded .modifier-pct{opacity:1}
.modifier-card-expand{max-height:0;overflow:hidden;will-change:max-height;contain:layout;transition:max-height .38s cubic-bezier(.16,1,.3,1)}
.modifier-card-expand-inner{padding-top:20px}
.modifier-slider{--fill:50%;width:100%;appearance:none;height:6px;border-radius:999px;background:linear-gradient(to right, rgba(255,255,255,0.85) 0%, rgba(255,255,255,0.85) var(--fill), rgba(255,255,255,0.13) var(--fill), rgba(255,255,255,0.13) 100%);cursor:pointer;outline:none}
.modifier-slider::-webkit-slider-thumb{appearance:none;width:7px;height:20px;border-radius:3.5px;background:var(--mc);cursor:pointer}
.modifier-slider::-moz-range-thumb{width:7px;height:20px;border:none;border-radius:3.5px;background:var(--mc);cursor:pointer}
.modifier-slider::-moz-range-progress{height:6px;border-radius:999px;background:rgba(255,255,255,0.85)}
.modifier-slider::-moz-range-track{height:6px;border-radius:999px;background:rgba(255,255,255,0.13)}
.modifier-sub-row{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-top:18px}
.modifier-sub-title{font-size:14.5px;font-weight:700;color:rgba(255,255,255,0.92)}
.modifier-sub-desc{margin-top:3px;font-size:13px;line-height:1.4;color:rgba(255,255,255,0.5)}
.level-stepper{display:flex;align-items:center;gap:8px;flex-shrink:0}
.level-stepper-btn{width:26px;height:26px;border-radius:50%;border:none;background:rgba(255,255,255,0.1);color:rgba(255,255,255,0.8);font-size:16px;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s ease}
.level-stepper-btn:hover{background:rgba(255,255,255,0.18)}
.level-stepper-input{width:64px;height:32px;border-radius:8px;border:none;background:#1b2420;color:#fff;font-size:13px;font-weight:700;text-align:center;font-family:var(--font)}
.level-stepper-input:focus{outline:2px solid var(--mc)}
.modifier-card:hover{transform:translateY(-3px);border-color:rgba(255,255,255,0.18);background:rgba(255,255,255,0.05)}
.modifier-icon{display:flex;align-items:center;justify-content:center;width:50px;height:50px;flex-shrink:0;color:var(--mc)}
.modifier-icon svg{width:32px;height:32px}
.modifier-body{flex:1;min-width:0}
.modifier-title{font-size:14.5px;font-weight:700}
.modifier-desc{margin-top:3px;font-size:13px;line-height:1.4;color:rgba(255,255,255,0.5)}
.modifier-toggle{flex-shrink:0}
.modifier-min-rounds{display:none;flex-shrink:0;font-size:12.5px;font-weight:600;color:rgba(255,255,255,0.4);white-space:nowrap}
.modifier-card.locked .modifier-toggle{display:none}
.modifier-card.locked .modifier-min-rounds{display:block}

/* ── Add-crate modal ───────────────────────────────────────────────────────── */
.crate-modal-backdrop{position:fixed;inset:0;z-index:200;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0);backdrop-filter:blur(0px);-webkit-backdrop-filter:blur(0px);opacity:0;pointer-events:none;transition:opacity .28s ease,background .28s ease,backdrop-filter .28s ease}
.crate-modal-backdrop.open{opacity:1;pointer-events:auto;background:rgba(0,0,0,0.6);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.crate-modal{width:min(1100px,92vw);max-height:92vh;display:flex;flex-direction:column;background:rgba(9,9,9,0.98);border:1px solid rgba(255,255,255,0.08);border-radius:18px;box-shadow:0 24px 64px rgba(0,0,0,0.6);padding:22px 22px 18px;transform:translateY(18px) scale(.97);opacity:0;transition:transform .28s cubic-bezier(.16,1,.3,1),opacity .28s ease}
.crate-modal-backdrop.open .crate-modal{transform:translateY(0) scale(1);opacity:1}
.crate-modal-topbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.crate-modal-topbar .filter-chips{display:flex;align-items:center;gap:8px;flex-wrap:wrap;flex:1}
.crate-modal-search{max-width:220px;margin:0}
.crate-modal-search input{padding:9px 15px 9px 40px;border-radius:11px;font-size:13px}
.crate-modal-search .search-ico{width:15px;height:15px;left:15px}
.crate-modal-grid{height:calc(3 * var(--crate-row-h, 246px));max-height:100%;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:none;-ms-overflow-style:none;margin-top:12px;padding:6px 0 0;will-change:scroll-position;transform:translateZ(0);contain:layout style paint}
.crate-modal-grid::-webkit-scrollbar{display:none}
.crate-modal-spacer{display:grid;grid-template-columns:repeat(6,1fr);gap:10px}
.crate-modal-card{--glow:120,205,145;display:flex;flex-direction:column;align-items:center;background:rgba(255,255,255,0.008);border:1px solid rgba(255,255,255,0.045);border-radius:12px;padding:10px 8px 12px;position:relative;transition:transform .3s cubic-bezier(.16,1,.3,1),border-color .3s ease,background .3s ease;box-sizing:border-box;animation:fadeIn .4s ease both;contain:content}
.crate-modal-card:hover{transform:translateY(-3px);border-color:rgba(255,255,255,0.1);background:rgba(255,255,255,0.02);z-index:2}
.crate-modal-card.selected{border-color:rgba(255,255,255,0.35)}
.crate-modal-card-fav{position:absolute;top:6px;right:6px;width:24px;height:24px;background:none;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:0;transition:opacity .15s;z-index:5}
.crate-modal-card:hover .crate-modal-card-fav{opacity:1}
.crate-modal-card-fav.active{opacity:1}
.crate-modal-card-fav svg{width:18px;height:18px;color:rgba(255,255,255,0.55);transition:color .15s;filter:drop-shadow(0 1px 2px rgba(0,0,0,0.8))}
.crate-modal-card-fav:hover svg{color:rgba(255,255,255,0.9)}
.crate-modal-card-fav.active svg{color:rgb(255,165,80);fill:rgb(255,165,80)}
.crate-modal-card-name{order:1;font-size:14.5px;font-weight:600;color:rgba(255,255,255,0.85);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center;width:100%}
.crate-modal-card-price{order:2;display:flex;align-items:center;justify-content:center;gap:5px;font-size:13px;font-weight:600;color:rgba(255,255,255,0.6);margin-top:6px}
.crate-modal-card-price img{width:14px;height:14px;object-fit:contain}
.crate-modal-card .case-art{order:3;width:100%;aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;position:relative;border-radius:8px;margin-top:8px}
.crate-modal-card .case-glow{display:none}
.crate-modal-card .case-art img{position:relative;z-index:1;width:78%;height:78%;object-fit:contain;filter:drop-shadow(0 0 0 rgba(var(--glow),0));transition:filter .5s ease}
.crate-modal-card:hover .case-art img{filter:drop-shadow(0 0 14px rgba(var(--glow),0.55))}
.crate-modal-card-slider{order:4;position:relative;width:75%;height:4px;display:flex;gap:3px;margin-top:8px}
.crate-modal-card-slider .seg{flex:1;height:100%;border-radius:3px;background:rgba(255,255,255,0.12)}
.crate-modal-card-slider .seg.lit:nth-child(1){background:rgb(120,205,145)}
.crate-modal-card-slider .seg.lit:nth-child(2){background:rgb(240,160,55)}
.crate-modal-card-slider .seg.lit:nth-child(3){background:rgb(235,80,70)}
.crate-modal-card-slider .pin{position:absolute;top:-2.5px;width:3px;height:9px;border-radius:2px;background:#fff;transform:translateX(-50%)}
.crate-modal-card-actions{order:5;display:flex;align-items:center;justify-content:center;gap:6px;width:75%;margin-top:10px}
.crate-modal-card-add{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;height:32px;border-radius:8px;border:none;background:#3F6B2B;color:#DDF2B8;font-size:12.5px;font-weight:800;font-family:var(--font);cursor:pointer;transition:background .15s ease}
.crate-modal-card-add:hover{background:#4c8034}
.crate-modal-card-add svg{width:16px;height:16px}
.crate-modal-card-preview{width:32px;height:32px;flex-shrink:0;display:flex;align-items:center;justify-content:center;border-radius:8px;border:1px solid rgba(255,255,255,0.1);background:rgba(255,255,255,0.05);color:rgba(255,255,255,0.7);cursor:pointer;transition:background .15s ease}
.crate-modal-card-preview:hover{background:rgba(255,255,255,0.1)}
.crate-modal-card-preview svg{width:16px;height:16px}
.crate-modal-card-qty{display:none;align-items:center;justify-content:center;gap:10px;width:100%}
.crate-modal-card.selected .crate-modal-card-qty{display:flex}
.crate-modal-card.selected .crate-modal-card-add,.crate-modal-card.selected .crate-modal-card-preview{display:none}
.crate-modal-qty-btn{display:flex;align-items:center;justify-content:center;width:32px;height:32px;flex-shrink:0;border-radius:8px;border:none;background:none;cursor:pointer;transition:opacity .15s ease}
.crate-modal-qty-minus{color:rgb(220,90,80)}
.crate-modal-qty-minus:hover{opacity:.75}
.crate-modal-qty-plus{color:rgb(80,150,220)}
.crate-modal-qty-plus:hover{opacity:.75}
.crate-modal-qty-btn svg{width:16px;height:16px}
.crate-modal-qty-value{font-size:14px;font-weight:800;color:#fff;min-width:26px;text-align:center}
.crate-modal-footer{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-top:6px;padding-top:14px}
.crate-modal-count{display:flex;align-items:center;gap:6px;font-size:14px;font-weight:600;color:rgba(255,255,255,0.75)}
.crate-modal-count img{width:16px;height:16px;object-fit:contain}
.crate-modal-footer-btns{display:flex;align-items:center;gap:10px}
.crate-modal-cancel-btn{padding:11px 24px;border-radius:11px;border:1px solid rgba(220,90,80,0.4);background:rgba(220,90,80,0.14);color:rgb(235,140,130);font-size:13px;font-weight:800;font-family:var(--font);cursor:pointer;transition:background .15s ease}
.crate-modal-cancel-btn:hover{background:rgba(220,90,80,0.22)}
.crate-modal-add-btn{padding:13px 28px;border-radius:11px;border:1px solid rgba(255,255,255,0.08);background:rgba(255,255,255,0.05);color:rgba(255,255,255,0.4);font-size:14px;font-weight:800;font-family:var(--font);cursor:default;transition:all .15s ease;white-space:nowrap}
.crate-modal-add-btn.ready{cursor:pointer;background:#66852F;border-color:#66852F;color:#DDF2B8}
.crate-modal-add-btn.ready:hover{background:#75993a}
@media (max-width:1300px){.crate-modal-spacer{grid-template-columns:repeat(4,1fr)}}
@media (max-width:700px){.crate-modal-spacer{grid-template-columns:repeat(2,1fr)}}

/* ── Case preview modal (opened from the magnifier icon on a round card) ─────────────────── */
.case-preview-modal{position:relative;width:min(720px,92vw);max-height:85vh;overflow-y:auto;padding:32px;gap:0}
.case-preview-modal .case-detail-heading{flex-direction:row;align-items:center;justify-content:flex-start;gap:14px;margin-bottom:8px}
.case-preview-modal .case-detail-art{width:76px;height:76px;flex-shrink:0}
.case-preview-modal .case-detail-name-wrap{display:flex;flex-direction:column;align-items:flex-start;gap:6px}
.case-preview-modal .case-detail-name{text-align:left}
.case-preview-modal .case-price{margin:0;width:auto;justify-content:flex-start;background:none;border:none;padding:0}
.case-preview-modal .case-items-section{max-width:none;margin:28px 0 0}
/* Item cards ~10% smaller than the case-detail page's version (padding, image, and text all
   scaled down together), gap tightened from 12px to 10px to match. */
.case-preview-modal .case-items-grid{grid-template-columns:repeat(4,1fr);gap:10px}
.case-preview-modal .case-item-card{padding:13px 9px 14px}
.case-preview-modal .case-item-card>img{width:76px;height:76px;margin:13px 0 11px}
.case-preview-modal .case-item-name{font-size:12px}
.case-preview-modal .case-item-price{font-size:12px}
.case-preview-modal .case-item-price img{width:13px;height:13px}
.case-preview-modal .case-item-chance,.case-preview-modal .case-item-range{font-size:10px}
@media (max-width:600px){.case-preview-modal .case-items-grid{grid-template-columns:repeat(2,1fr)}}


/* ══ Case Battles on phones (≤768px, the site's mobile breakpoint) ══════════════════════════ */
@media (max-width:768px){
  /* ── Browse list ── */
  .battles-header{margin-top:22px;margin-bottom:22px}
  .battles-title{font-size:22px}
  .battles-sub{font-size:14px}
  .battle-card{gap:12px;padding:12px 14px;border-radius:12px}
  .battle-card-left{min-width:0;min-height:0;width:100%}
  .battle-card-head{flex-wrap:wrap;row-gap:4px}
  .battle-card-title{font-size:13.5px}
  .battle-slots{gap:5px;margin-bottom:0}
  .battle-slot{width:36px;height:36px;border-bottom-width:3px}
  .battle-slot.empty svg{width:18px;height:18px}
  .battle-slot-vs{padding:0 3px;font-size:10px}
  .battle-card-cases-wrap{margin-top:0}
  .battle-card-cases{gap:6px;transform:none}
  .battle-card-case{width:64px;height:64px}
  .battle-card-strip{gap:8px}
  .battle-card-case,.lobby-case-icon{-webkit-touch-callout:none}
  .battle-card-case-qty{min-width:18px;height:18px;font-size:10.5px;right:-2px;bottom:2px}
  .battle-card-arrow{width:44px;height:44px;top:-8px}
  .battle-card-right{width:100%;margin-left:0;justify-content:space-between;gap:10px}
  .battle-card-rounds{font-size:13px}
  .battle-card-join-btn{flex:1;padding:12px 14px}
  .battle-card-winners{margin-left:0}
  .battle-card-winner-pfps .battle-slot{width:32px;height:32px}

  /* ── Create page ── */
  .battle-create-bar{flex-direction:column;align-items:flex-start;gap:12px;margin:18px auto 24px}
  .battle-create-bar .case-detail-back{position:static}
  .battle-create-title{width:100%;text-align:left;font-size:21px}
  .battle-section-title{margin-top:40px}
  .battle-modes{grid-template-columns:minmax(0,1fr);gap:10px}
  .battle-mode-group{min-width:0;padding:14px}
  .battle-rounds-bar{flex-wrap:wrap;gap:12px;margin-top:30px}
  .battle-rounds-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
  .modifiers-grid{grid-template-columns:minmax(0,1fr);gap:10px}
  .modifier-card{padding:14px}
  .battle-create-submit-bar{flex-wrap:wrap;gap:10px}
  .battle-create-submit-bar>*{flex:1 1 auto}

  /* ── Lobby: header row, info row, pill ── */
  /* header: back link + share/mute on one row, the title under them */
  .battle-lobby-bar{display:grid;grid-template-columns:1fr auto;row-gap:12px;margin-top:14px;margin-bottom:20px;padding-top:0}
  .battle-lobby-bar .case-detail-back{position:static;grid-column:1;grid-row:1;align-self:center;justify-self:start}
  .battle-lobby-actions{position:static;grid-column:2;grid-row:1}
  .battle-lobby-heading{grid-column:1/-1;grid-row:2;text-align:left}
  .battle-lobby-heading .battle-lobby-modifiers{justify-content:flex-start}
  .battle-lobby-heading .battle-create-title{font-size:18px}
  .battle-lobby-info{grid-template-columns:1fr auto;grid-template-areas:"total spect" "pill pill";row-gap:10px}
  .battle-lobby-total{grid-area:total;font-size:13px}
  .battle-lobby-spectators{grid-area:spect;font-size:13px}
  .battle-lobby-info>.battle-lobby-rounds-pill{grid-area:pill;justify-self:stretch;width:auto;transform:none;height:58px;padding:0 12px}
  .battle-lobby-rounds-art img{width:42px;height:42px}
  .battle-lobby-rounds-current{width:82px}
  .battle-lobby-rounds-current-name,.battle-lobby-rounds-current-price{font-size:12px}
  .battle-lobby-rounds-pill.playing .battle-lobby-rounds-art{left:12px;right:12px}

  /* ── Lobby: arena + seats (tile above a compact name plate, so six seats fit in 335px) ── */
  .battle-lobby-arena{height:300px;margin-bottom:44px}
  .arena-players{bottom:-34px;gap:4px;padding:0 4px}
  .arena-players.group-align{gap:4px;padding:0 4px 0 0}
  .arena-player{flex-direction:column;gap:4px;transform:translateY(var(--dy,0px))} /* no tilt: there's no room for it to read */
  .arena-tile{width:40px;height:40px;border-left-width:3px;border-bottom-width:3px}
  .arena-tile img{width:30px;height:30px}
  .arena-tile.empty svg{width:18px;height:18px}
  .arena-plate{width:auto;max-width:76px;height:20px;padding:0 6px;gap:4px;font-size:10px;transform:none;border-radius:3px}
  .arena-plate>*{transform:none}
  .arena-plate>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .arena-player:hover .arena-plate-bot,.arena-player:hover .arena-plate-join{transform:none}
  .arena-plate-icon svg{width:1em;height:.9em}
  .arena-plate-cost{margin-left:0;gap:3px}
  .arena-plate-join>span:first-child{display:none} /* the arrow tile already says join; the plate keeps just the cost */
  .arena-plate-cost img{width:11px;height:11px}
  .arena-players.crowded .arena-plate{width:auto;padding:0 5px;font-size:9.5px}
  .arena-vs{padding:3px 5px;font-size:10px;border-radius:4px}
  .arena-win{font-size:12px;gap:3px;bottom:calc(100% + 4px)}
  .arena-win img{width:12px;height:12px}
  #battleLobbyArenaStatus{font-size:15px}

  /* ── Lobby: reel lanes sized by seat count ── */
  .battle-spin-wrap .multi-spin-arrow{display:none}
  .battle-spin-wrap .multi-spin-viewport{gap:4px;padding:0 4px 0 0}
  .battle-spin-wrap .spin-slot{width:112px;height:112px}
  .battle-spin-wrap .spin-slot>img,.battle-spin-wrap .spin-slot>.slot-placeholder{width:84px;height:84px}
  .battle-spin-wrap[data-qty="3"] .spin-slot{width:96px;height:96px}
  .battle-spin-wrap[data-qty="3"] .spin-slot>img,.battle-spin-wrap[data-qty="3"] .spin-slot>.slot-placeholder{width:72px;height:72px}
  .battle-spin-wrap[data-qty="4"] .spin-slot{width:76px;height:76px}
  .battle-spin-wrap[data-qty="4"] .spin-slot>img,.battle-spin-wrap[data-qty="4"] .spin-slot>.slot-placeholder{width:58px;height:58px}
  .battle-spin-wrap[data-qty="4"] .slot-price{font-size:9px}
  .battle-spin-wrap[data-qty="6"] .spin-slot{width:40px;height:40px}
  .battle-spin-wrap[data-qty="6"] .spin-slot>img,.battle-spin-wrap[data-qty="6"] .spin-slot>.slot-placeholder{width:32px;height:32px}
  .battle-spin-wrap[data-qty="5"] .spin-slot{width:52px;height:52px}
  .battle-spin-wrap[data-qty="5"] .spin-slot>img,.battle-spin-wrap[data-qty="5"] .spin-slot>.slot-placeholder{width:40px;height:40px}
  .battle-spin-wrap[data-qty="5"] .slot-price{display:none}
  .battle-spin-wrap[data-qty="6"] .slot-price{display:none}
  .battle-spin-wrap .spin-slot.bait>img{width:70%;height:70%}
  .respin-boom-frame{transform:scale(.7)}

  /* ── Lobby: end screen, jackpot bar ── */
  .arena-total{font-size:26px;gap:7px}
  .arena-total img{width:26px;height:26px}
  .jackpot-wrap{height:56px}
  .jackpot-slice img{width:26px;height:26px}
  .jackpot-slice-avatars{gap:4px}
  .jackpot-slice-cursed svg{width:28px;height:28px}
  .jackpot-arrow{top:-18px}
  .jackpot-arrow img{width:46px;height:46px}
  .arena-pcts .arena-pct{font-size:12px;transform:translate(-50%,calc(-100% - 26px))}

  /* ── Lobby: round cards (columns keep a real width; the grid scrolls sideways when needed) ── */
  .battle-lobby-rounds-grid{--col-min:118px;gap:6px;max-height:none;overflow:visible;overflow-x:auto;padding-bottom:6px;margin-top:40px} /* real column minimum: the grid scrolls sideways past that */
  .round-col{gap:6px}
  .round-card{height:128px;gap:2px;border-radius:4px}
  .round-card.filled{padding-top:18px;gap:2px}
  .round-card-img{width:54px;height:54px}
  .round-card-label{font-size:10px}
  .round-card-num{font-size:22px}
  .round-card-idx{top:6px;left:12px;font-size:14px}
  .round-card-idx::before{font-size:13px;top:-5px;left:-8px}
  .round-card-pct{top:6px;right:8px;font-size:9px}
  .round-card-name{font-size:11px;margin-top:2px}
  .round-card-price{font-size:11px}
  .round-card-price img{width:11px;height:11px}
}
@media (max-width:420px){
  .battle-lobby-arena{height:280px}
  .battle-card-case{width:56px;height:56px}
}


/* ══ Home page on phones/tablets ══════════════════════════════════════════════════════════════ */
@media (max-width:768px){
  .home-hero-guest,.home-hero-auth{padding:28px 2px 6px;gap:14px;min-height:0}
  .home-title{font-size:28px}
  .home-welcome-back{font-size:22px}
  .home-subtitle{font-size:14px}
  .live-wins-section.home-live-wins{margin-top:12px}
  .home-levelup-copy{padding-left:12%}
  .home-levelup-label{font-size:13px}
  .home-levelup-title{font-size:20px}
  .home-levelup-chip{margin-top:6px;padding:6px 12px;font-size:12px}
  .home-levelup-chip svg{width:13px;height:13px}
  .home-levelup-gauge{transform:translate(-50%,-50%) scale(.42)}
  .home-levelup-reward{right:3%;transform:translateY(-50%) scale(.42);transform-origin:right center}
  .home-rewards-arrow{width:32px;height:32px}
  .home-rewards-arrow svg{width:20px;height:20px}
  .home-rewards-arrow.left{left:8px}
  .home-rewards-arrow.right{right:8px}
  .home-games-heading{margin-top:26px;font-size:17px}
  /* Game cards: two per row instead of five squeezed into 55px each; an odd last card spans the row. */
  .home-games-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .home-game-card{height:200px}
  .home-game-card:last-child:nth-child(odd){grid-column:1/-1;height:170px}
  .home-game-icon{width:58px;height:58px;top:40%}
  .home-game-title{top:66%;font-size:19px}
  .home-game-ribbon{top:10px;padding:4px 8px;font-size:11px}
}
@media (max-width:420px){
  .home-game-title{font-size:17px}
}
