  :root{
    --ink:#16120D;
    --counter:#3B2A1E;
    --counter-light:#4E3928;
    --cardboard:#D9C3A0;
    --cardboard-dark:#C2A87E;
    --paper:#F3ECDD;
    --red:#C1443C;
    --gold:#D4AF37;
    --green:#4C8A5E;
    --blue:#3E6FA6;
    --gray:#8A8377;
    --accent:#08d9d6;
    --accent2:#ff2e63;
    --room-wall:#c7bba7;
    --shadow: 0 6px 18px rgba(0,0,0,0.45);
  }
  *{box-sizing:border-box;}
  html,body{margin:0;padding:0;height:100%;}
  body{
    background:#000;
    color:var(--paper);
    font-family:'Inter',sans-serif;
    height:100vh; overflow:hidden;
    -webkit-font-smoothing:antialiased;
  }
  ::selection{ background:var(--gold); color:var(--ink); }

  /* ================= PHOTO STAGE (real day/night desk photos) ================= */
  .photo-stage{ position:fixed; inset:0; z-index:0; overflow:hidden; background:#000; }
  .photo-blur{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
    filter:blur(36px) brightness(0.65) saturate(1.1); transform:scale(1.15);
    opacity:0; transition:opacity .8s ease;
  }
  .photo-main{
    position:absolute; inset:0; width:100%; height:100%; object-fit:contain;
    opacity:0; transition:opacity .8s ease;
  }
  :root:not([data-time="night"]) #photoBlurDay,
  :root:not([data-time="night"]) #photoDay{ opacity:1; }
  :root[data-time="night"] #photoBlurNight,
  :root[data-time="night"] #photoNight{ opacity:1; }

  .hotspot{
    position:fixed; z-index:5; cursor:pointer;
    border-radius:2%;
    box-shadow:0 0 0 2px rgba(255,255,255,0.16);
    animation: hotspotPulse 2.6s ease-in-out infinite;
    transition: opacity .35s ease;
  }
  .hotspot:hover{ box-shadow:0 0 0 2px rgba(255,255,255,0.4), 0 0 30px rgba(255,255,255,0.25) inset; }
  .hotspot .hotspot-label{
    position:absolute; left:50%; bottom:-30px; transform:translateX(-50%);
    font-family:'Space Mono',monospace; font-size:11px; letter-spacing:1px; color:#fff;
    background:rgba(0,0,0,0.55); padding:4px 10px; border-radius:12px; white-space:nowrap;
    opacity:0; transition:opacity .2s ease; pointer-events:none;
  }
  .hotspot:hover .hotspot-label{ opacity:1; }
  @keyframes hotspotPulse{
    0%,100%{ box-shadow:0 0 0 2px rgba(255,255,255,0.12); }
    50%{ box-shadow:0 0 0 2px rgba(255,255,255,0.32), 0 0 22px rgba(255,255,255,0.18); }
  }
  .photo-stage.zoomed .hotspot{ opacity:0; pointer-events:none; }

  .room-dim{
    position:fixed; inset:0; z-index:40; background:rgba(4,3,2,0.6);
    opacity:0; pointer-events:none; transition:opacity .45s ease;
  }
  .room-dim.on{ opacity:1; }

  /* ================= ZOOM SCREEN (the computer, or the binder, once you click in) ================= */
  .zoom-window{
    position:fixed; z-index:50; left:50%; top:50%;
    width:min(90vw, 1480px); height:min(88vh, 920px);
    transform:translate(-50%,-50%);
    border-radius:14px; overflow:hidden;
    box-shadow: 0 50px 120px rgba(0,0,0,0.65), 0 0 0 6px #0c0c0d, 0 0 0 9px #000;
    opacity:0; pointer-events:none;
  }
  .zoom-window.visible{ opacity:1; pointer-events:auto; }
  .zoom-window.animating{ transition: transform .55s cubic-bezier(.22,.8,.25,1); }
  /* the computer takes over the whole viewport — the walk-up-to-it zoom animation (see
     openZoomOn/closeZoomOn in script.js) is purely bounding-box math against whatever size is
     defined here, so it keeps working unchanged at any size. The binder stays a windowed
     overlay — it was never the target of the "fill the screen" request. */
  #zoomScreen{
    background: radial-gradient(ellipse at 50% -10%, #2a2018 0%, var(--ink) 55%);
    width:100vw; height:100vh; border-radius:0;
  }
  #binderScreen{ background: radial-gradient(ellipse at 50% -10%, #3c2a18 0%, #211408 55%); }
  .screen-scroll{ position:absolute; top:38px; left:0; right:0; bottom:0; overflow-y:auto; overflow-x:hidden; }
  /* room for the event feed sidebar (computer only) — see .event-feed below */
  #zoomScreen .screen-scroll{ right:300px; transition: right .3s ease; }
  /* collapsed via the .feed-toggle handle — slides the feed off past the right edge (clipped by
     .zoom-window's overflow:hidden) and gives the reclaimed 300px back to the main content */
  #zoomScreen.feed-collapsed .screen-scroll{ right:0; }
  #zoomScreen.feed-collapsed .event-feed{ transform:translateX(100%); pointer-events:none; }
  #zoomScreen.feed-collapsed .feed-toggle{ right:0; }
  #zoomScreen.feed-collapsed .feed-toggle svg{ transform:rotate(180deg); }
  .feed-toggle{
    position:absolute; top:50%; right:300px; z-index:256;
    transform:translate(50%,-50%);
    width:26px; height:48px; padding:0; cursor:pointer;
    display:flex; align-items:center; justify-content:center;
    background:linear-gradient(180deg,#3c3c3f,#2a2a2c);
    border:1px solid rgba(212,175,55,0.35); border-radius:7px;
    color:var(--gold);
    box-shadow:0 3px 10px rgba(0,0,0,0.45);
    transition: right .3s ease, background .15s ease, color .15s ease, transform .15s ease;
  }
  .feed-toggle:hover{ background:linear-gradient(180deg,#4a4a4d,#333335); color:#ffe9a8; }
  .feed-toggle:active{ transform:translate(50%,-50%) scale(0.92); }
  .feed-toggle svg{ width:10px; height:16px; transition: transform .3s ease; }
  @media (max-width: 900px){
    /* not enough width for a sidebar without crushing the app content — feed moves out of the
       way rather than staying half-usable */
    #zoomScreen .screen-scroll{ right:0; }
    .event-feed, .feed-toggle{ display:none; }
  }
  .screen-glare{
    position:absolute; inset:0; z-index:250; pointer-events:none;
    background: linear-gradient(115deg, transparent 40%, rgba(255,255,255,0.05) 50%, transparent 60%);
    mix-blend-mode:screen;
  }

  /* ---------- event feed: a live, scrollable ledger of everything that used to interrupt as a
     toast (sales, grading, box hits, ...). Toasts are now reserved for bills; everything else
     lands here instead, chat-log order (oldest on top, newest at the bottom, auto-scrolled to
     the newest entry on every update), for the player to check on their own time. */
  .event-feed{
    position:absolute; top:38px; right:0; bottom:0; width:300px; z-index:255;
    display:flex; flex-direction:column;
    background:rgba(10,8,6,0.55); backdrop-filter:blur(6px);
    border-left:1px solid rgba(212,175,55,0.22);
    transition: transform .3s ease;
  }
  .event-feed-header{
    flex-shrink:0; padding:12px 14px; font-family:'Bebas Neue',sans-serif; letter-spacing:0.5px;
    font-size:15px; color:var(--gold); text-transform:uppercase;
    border-bottom:1px solid rgba(212,175,55,0.2);
  }
  .event-feed-list{ flex:1; overflow-y:auto; overflow-x:hidden; padding:8px 10px; display:flex; flex-direction:column; gap:6px; }
  .event-feed-empty{ font-family:'Space Mono',monospace; font-size:11px; color:#8a7960; padding:14px 4px; text-align:center; line-height:1.5; }
  .event-row{
    padding:8px 9px; border-radius:6px;
    background:rgba(255,255,255,0.04); border:1px solid rgba(255,255,255,0.06);
  }
  /* events tied to a specific card (sales, grading results, hits, ...) are clickable — see the
     event-feed delegated listeners in script.js for the click-to-inspect / hover-to-preview */
  .event-row.has-card{ cursor:pointer; transition: background .12s ease, border-color .12s ease; }
  .event-row.has-card:hover{ background:rgba(212,175,55,0.1); border-color:rgba(212,175,55,0.35); }
  .event-time{
    display:block; font-family:'Space Mono',monospace; font-size:9px; letter-spacing:0.4px;
    text-transform:uppercase; color:#8a7960; margin-bottom:2px;
  }
  .event-msg{ font-family:'Inter',sans-serif; font-size:12px; line-height:1.35; color:var(--paper); }

  /* "hype word" — a punchy comic-caption font for the handful of exciting callouts inside an
     event message (SOLD, CHASE HIT!, AUTO HIT!, 1-OF-1 HIT!, PERFECT SCORE!) so they read as a
     highlight instead of blending into the sentence around them. Only ever used on plain-text
     messages that go straight to the feed's innerHTML — never on anything that can also reach
     the #toast popup, since that renders via textContent and would show the raw tag as text.
     Color variants: win/money/even/loss. money/even/loss mirror the same green/gold/red the
     Auctions "Sell" tab already uses for a settled listing's bid (see auctionOutcomeClass), so a
     SOLD callout reads the same profit/comp/loss signal at a glance in both places — win (pull
     hits: 1-of-1/auto/chase/perfect-grade) is deliberately its own blue rather than sharing gold
     with SOLD-at-comp, since those are two unrelated kinds of "good news" a player shouldn't
     have to tell apart by color alone. */
  .hype-word{
    font-family:'Bangers','Bebas Neue',cursive; letter-spacing:0.5px; font-size:1.15em;
    -webkit-text-stroke:0.3px rgba(0,0,0,0.4);
  }
  .hype-word.win{ color:#5ec2ff; text-shadow:0 1px 0 rgba(0,0,0,0.5), 0 0 8px rgba(62,111,166,0.65); }
  .hype-word.money{ color:#7be69a; text-shadow:0 1px 0 rgba(0,0,0,0.5), 0 0 8px rgba(76,138,94,0.55); }
  .hype-word.even{ color:#ffd75e; text-shadow:0 1px 0 rgba(0,0,0,0.5), 0 0 8px rgba(212,175,55,0.6); }
  .hype-word.loss{ color:#ff8f87; text-shadow:0 1px 0 rgba(0,0,0,0.5), 0 0 8px rgba(193,68,60,0.55); }
  /* CertCore grade tiers in the event feed (see certcoreGradeHTML) — metal color by grade so a
     7/8/9/10 reads at a glance without having to parse the number: bronze/silver/gold/platinum */
  .hype-word.bronze{ color:#e0975a; text-shadow:0 1px 0 rgba(0,0,0,0.5), 0 0 8px rgba(180,110,55,0.6); }
  .hype-word.silver{ color:#d7dee5; text-shadow:0 1px 0 rgba(0,0,0,0.5), 0 0 8px rgba(170,185,200,0.55); }
  .hype-word.gold{ color:#ffd75e; text-shadow:0 1px 0 rgba(0,0,0,0.5), 0 0 8px rgba(212,175,55,0.6); }
  .hype-word.platinum{ color:#f2fbff; text-shadow:0 1px 0 rgba(0,0,0,0.5), 0 0 10px rgba(170,225,255,0.75); }

  /* small floating card preview shown on hover over a card-linked event row — click the row
     itself for the full flippable inspect modal instead */
  .card-hover-preview{
    position:fixed; z-index:700; pointer-events:none;
    display:flex; gap:10px; align-items:flex-start;
    width:220px; padding:10px; border-radius:8px;
    background:linear-gradient(160deg,#241c12,var(--ink)); border:1.5px solid var(--gold);
    box-shadow:0 14px 34px rgba(0,0,0,0.5), 0 0 0 1px rgba(212,175,55,0.15);
    opacity:0; transform:translateY(-4px);
    transition: opacity .12s ease, transform .12s ease;
  }
  .card-hover-preview.show{ opacity:1; transform:translateY(0); }
  .card-hover-preview .swatch{ width:46px; height:64px; }
  .chp-info{ min-width:0; flex:1; }
  .chp-name{ font-family:'Bebas Neue',sans-serif; font-size:15px; line-height:1.15; color:var(--paper); }
  .chp-brand{ font-family:'Space Mono',monospace; font-size:9px; color:#8a7960; margin:2px 0 6px; }
  .chp-rarity{
    display:inline-block; font-family:'Space Mono',monospace; font-size:9px; font-weight:700;
    color:#fff; padding:2px 7px; border-radius:10px;
  }

  /* ---------- generic tooltip system: any [data-tip] element shows this on hover/focus (see the
     tooltip IIFE in script.js). Styled to match .card-hover-preview's frame language rather than
     reusing that element, since this one is plain text (no swatch/rarity chip) and needs to flip
     above/below the target depending on available space (.below). */
  .app-tooltip{
    position:fixed; z-index:1000; pointer-events:none;
    max-width:240px; padding:8px 11px; border-radius:8px;
    background:linear-gradient(160deg,#241c12,var(--ink)); border:1.5px solid var(--gold);
    box-shadow:0 14px 34px rgba(0,0,0,0.5), 0 0 0 1px rgba(212,175,55,0.15);
    color:var(--paper,#f2e9d8); font-family:'Inter',sans-serif; font-size:11.5px; line-height:1.45;
    opacity:0; transform:translateY(-4px);
    transition:opacity .12s ease, transform .12s ease;
  }
  .app-tooltip.show{ opacity:1; transform:translateY(0); }
  .app-tooltip.below{ transform:translateY(4px); }
  .app-tooltip.show.below{ transform:translateY(0); }

  .browser-chrome{
    position:absolute; top:0; left:0; right:0; height:38px; z-index:260;
    background:linear-gradient(180deg,#3c3c3f,#2a2a2c);
    display:flex; align-items:center; gap:10px; padding:0 10px;
    border-bottom:1px solid rgba(0,0,0,0.5);
  }
  .browser-dots{ display:flex; gap:6px; flex-shrink:0; }
  .browser-dots span{ width:11px; height:11px; border-radius:50%; display:block; }
  .browser-dots span:nth-child(1){ background:#ff5f57; }
  .browser-dots span:nth-child(2){ background:#febc2e; }
  .browser-dots span:nth-child(3){ background:#28c840; }
  .browser-back{
    width:22px; height:22px; border-radius:50%; border:none; cursor:pointer;
    background:rgba(255,255,255,0.08); color:rgba(255,255,255,0.6); font-size:13px; line-height:1;
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
    transition: background .15s ease, color .15s ease;
  }
  .browser-back:hover{ background:rgba(255,255,255,0.18); color:#fff; }
  .browser-address{
    flex:1; height:23px; min-width:0; background:rgba(255,255,255,0.1); border-radius:12px;
    display:flex; align-items:center; gap:6px; padding:0 12px;
    font-family:'Space Mono',monospace; font-size:10.5px; color:rgba(255,255,255,0.6);
    overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
  }
  .browser-address .lock{ font-size:9px; flex-shrink:0; }

  .binder-chrome{
    position:absolute; top:0; left:0; right:0; height:38px; z-index:260;
    background:linear-gradient(180deg,#6b4a2c,#4a3320);
    display:flex; align-items:center; gap:10px; padding:0 10px 0 6px;
    border-bottom:1px solid rgba(0,0,0,0.5);
  }
  .binder-title{
    flex:1; font-family:'Bebas Neue',sans-serif; font-size:17px; letter-spacing:1px; color:var(--paper);
  }
  .binder-count{
    font-family:'Space Mono',monospace; font-size:10.5px; color:rgba(243,236,221,0.7);
    background:rgba(0,0,0,0.2); padding:3px 10px; border-radius:10px; white-space:nowrap;
  }

  .time-toggle{
    position:fixed; top:18px; right:18px; z-index:20;
    width:38px; height:38px; border-radius:50%; border:none; cursor:pointer;
    background:rgba(20,16,10,0.55); color:var(--paper); font-size:16px;
    display:flex; align-items:center; justify-content:center;
    box-shadow:0 4px 12px rgba(0,0,0,0.35); backdrop-filter:blur(3px);
    transition: transform .15s ease, background .15s ease;
  }
  .time-toggle:hover{ transform:scale(1.08); background:rgba(20,16,10,0.75); }

  .settings-toggle{
    position:fixed; top:64px; right:18px; z-index:20;
    width:38px; height:38px; border-radius:50%; border:none; cursor:pointer;
    background:rgba(20,16,10,0.55); color:var(--paper); font-size:16px;
    display:flex; align-items:center; justify-content:center;
    box-shadow:0 4px 12px rgba(0,0,0,0.35); backdrop-filter:blur(3px);
    transition: transform .15s ease, background .15s ease;
  }
  .settings-toggle:hover{ transform:scale(1.08) rotate(20deg); background:rgba(20,16,10,0.75); }
  .settings-toggle.active{ background:rgba(212,175,55,0.85); color:#1a1408; }

  /* lives INSIDE the register box itself (cash/rep/day, top-right of every tab's header) as its
     own segment, right after the Day block — same border-left-divider treatment .day-block already
     uses, so it reads as a natural 4th segment of that box rather than a floating icon. Shown on
     every tab (the register is shared header markup, not per-tab), which is what "accessible
     anywhere" actually meant in context — every page of the app, not the outer desk/binder scenes,
     which don't have this box at all.
     No hover-transform — background/glow feedback only, per this session's hover-edge-flicker fix. */
  .unlocks-toggle{
    /* a ::before divider line instead of border-left/padding-left directly on this element — those
       would stretch a border-radius:50% circle into an oval, since they widen the box without
       widening its height to match */
    position:relative; flex-shrink:0; margin-left:14px;
    width:34px; height:34px; border-radius:50%; border:none; cursor:pointer;
    background:rgba(212,175,55,0.12); color:var(--gold,#d4af37);
    display:flex; align-items:center; justify-content:center;
    transition: background .15s ease, box-shadow .15s ease;
  }
  .unlocks-toggle::before{
    content:""; position:absolute; left:-14px; top:50%; transform:translateY(-50%);
    width:1px; height:26px; background:var(--counter-light);
  }
  .unlocks-toggle svg{ display:block; width:19px; height:19px; }
  .unlocks-toggle:hover{ background:rgba(212,175,55,0.22); box-shadow:0 0 0 2px rgba(212,175,55,0.4); }
  .unlocks-toggle.active{ background:rgba(212,175,55,0.85); color:#1a1408; }

  /* position:fixed but with no static top/left of its own — the button above is a normal in-flow
     element now (inside the register box, wherever that lands on screen), not a fixed corner icon,
     so openUnlocks() in script.js positions this panel from the button's live getBoundingClientRect()
     each time it opens, the same way the app-tooltip system already positions itself off its target */
  .unlocks-panel{
    position:fixed; z-index:150;
    width:min(88vw, 320px); max-height:min(70vh, 560px);
    background:linear-gradient(160deg,#1c1810,var(--ink,#161210));
    border:1.5px solid rgba(212,175,55,0.45); border-radius:12px;
    box-shadow:0 18px 44px rgba(0,0,0,0.55), 0 0 0 1px rgba(0,0,0,0.4);
    opacity:0; transform:translateY(-10px) scale(0.97); pointer-events:none;
    transition:opacity .18s ease, transform .22s cubic-bezier(.22,.85,.3,1.3);
    display:flex; flex-direction:column; backdrop-filter:blur(4px);
  }
  .unlocks-panel.open{ opacity:1; transform:translateY(0) scale(1); pointer-events:auto; }

  .unlock-card{
    display:flex; gap:10px; align-items:flex-start;
    background:rgba(255,255,255,0.03); border:1px solid rgba(255,255,255,0.06); border-radius:9px;
    padding:10px;
  }
  .unlock-card.owned{ opacity:0.75; }
  .unlock-card-swatch{
    flex-shrink:0; width:40px; height:40px; border-radius:8px; border:1.5px solid rgba(212,175,55,0.4);
    background:rgba(212,175,55,0.12);
    display:flex; align-items:center; justify-content:center;
    font-family:'Bebas Neue',sans-serif; font-size:14px; letter-spacing:0.5px;
  }
  .unlock-card-body{ flex:1; min-width:0; display:flex; flex-direction:column; gap:5px; }
  .unlock-card-name{ font-family:'Bebas Neue',sans-serif; font-size:15px; letter-spacing:0.4px; color:var(--paper,#f2e9d8); }
  .unlock-card-desc{ font-family:'Inter',sans-serif; font-size:11px; line-height:1.4; color:rgba(243,236,221,0.6); }
  .unlock-card-btn{
    align-self:flex-start;
    background:rgba(212,175,55,0.14); border:1px solid rgba(212,175,55,0.4); color:var(--gold,#d4af37);
    font-family:'Inter',sans-serif; font-weight:700; font-size:11.5px; padding:6px 11px; border-radius:7px;
    cursor:pointer; transition:background .15s ease, border-color .15s ease;
  }
  .unlock-card-btn:hover{ background:rgba(212,175,55,0.28); border-color:rgba(212,175,55,0.65); }
  .unlock-card-owned{
    font-family:'Space Mono',monospace; font-weight:700; font-size:11px; letter-spacing:0.5px;
    color:var(--green,#4C8A5E);
  }

  .settings-panel{
    position:fixed; top:110px; right:18px; z-index:150;
    width:min(88vw, 320px); max-height:min(70vh, 560px);
    background:linear-gradient(160deg,#1c1810,var(--ink,#161210));
    border:1.5px solid rgba(212,175,55,0.45); border-radius:12px;
    box-shadow:0 18px 44px rgba(0,0,0,0.55), 0 0 0 1px rgba(0,0,0,0.4);
    opacity:0; transform:translateY(-10px) scale(0.97); pointer-events:none;
    transition:opacity .18s ease, transform .22s cubic-bezier(.22,.85,.3,1.3);
    display:flex; flex-direction:column; backdrop-filter:blur(4px);
  }
  .settings-panel.open{ opacity:1; transform:translateY(0) scale(1); pointer-events:auto; }
  .settings-panel-header{
    display:flex; align-items:center; justify-content:space-between;
    padding:12px 14px; border-bottom:1px solid rgba(212,175,55,0.25);
    flex-shrink:0;
  }
  .settings-panel-title{
    font-family:'Bebas Neue',sans-serif; letter-spacing:0.5px; font-size:18px; color:var(--gold,#d4af37);
  }
  .settings-panel-close{
    background:none; border:none; color:var(--paper,#f2e9d8); font-size:20px; line-height:1;
    cursor:pointer; opacity:0.7; padding:2px 4px;
  }
  .settings-panel-close:hover{ opacity:1; }
  .settings-panel-back{
    background:none; border:none; color:var(--paper,#f2e9d8); font-size:18px; line-height:1;
    cursor:pointer; opacity:0.7; padding:2px 6px 2px 2px; margin-right:2px;
  }
  .settings-panel-back:hover{ opacity:1; }
  .settings-panel-header{ gap:4px; }
  .settings-panel-title{ flex:1; }
  .settings-panel-body{ overflow-y:auto; padding:12px 14px 14px; display:flex; flex-direction:column; gap:12px; }

  .settings-pad-status{
    font-family:'Space Mono',monospace; font-size:11px; padding:7px 10px; border-radius:7px;
    background:rgba(0,0,0,0.25); color:rgba(243,236,221,0.75); display:flex; align-items:center; gap:7px;
  }
  .settings-pad-status .dot{ width:8px; height:8px; border-radius:50%; background:#8A8377; flex-shrink:0; }
  .settings-pad-status.connected .dot{ background:#4C8A5E; box-shadow:0 0 6px #4C8A5E; }

  .settings-sub{
    font-family:'Inter',sans-serif; font-size:11.5px; color:rgba(243,236,221,0.6); line-height:1.4;
  }

  .bind-row{
    display:flex; align-items:center; justify-content:space-between; gap:8px;
    background:rgba(255,255,255,0.03); border:1px solid rgba(255,255,255,0.06); border-radius:8px;
    padding:8px 10px;
  }
  .bind-row-label{ font-family:'Inter',sans-serif; font-weight:600; font-size:12.5px; color:var(--paper,#f2e9d8); }
  .bind-row-hint{ font-family:'Inter',sans-serif; font-size:10.5px; color:rgba(243,236,221,0.5); margin-top:1px; }
  .bind-key{
    font-family:'Space Mono',monospace; font-size:11px; padding:5px 9px; border-radius:6px;
    background:rgba(212,175,55,0.15); color:var(--gold,#d4af37); border:1px solid rgba(212,175,55,0.35);
    cursor:pointer; white-space:nowrap; transition:background .15s ease, transform .15s ease;
  }
  .bind-key:hover{ background:rgba(212,175,55,0.28); }
  .bind-key.listening{
    background:var(--red,#C1443C); color:#fff; border-color:var(--red,#C1443C);
    animation:bindPulse 0.9s ease-in-out infinite;
  }
  @keyframes bindPulse{ 0%,100%{ opacity:1; } 50%{ opacity:0.55; } }

  .settings-reset-btn{
    align-self:flex-start; background:none; border:1px solid rgba(243,236,221,0.25); color:rgba(243,236,221,0.75);
    font-family:'Inter',sans-serif; font-weight:600; font-size:11.5px; padding:6px 12px; border-radius:7px;
    cursor:pointer; transition:border-color .15s ease, color .15s ease;
  }
  .settings-reset-btn:hover{ border-color:var(--red,#C1443C); color:#fff; background:var(--red,#C1443C); }
  .settings-reset-btn.danger{ border-color:rgba(193,68,60,0.5); color:var(--red,#C1443C); }

  .settings-nav-btn{
    display:flex; align-items:center; gap:10px; width:100%; text-align:left;
    background:rgba(255,255,255,0.03); border:1px solid rgba(255,255,255,0.06); border-radius:8px;
    padding:10px 12px; cursor:pointer; transition:background .15s ease, border-color .15s ease;
  }
  .settings-nav-btn:hover{ background:rgba(212,175,55,0.1); border-color:rgba(212,175,55,0.3); }
  .settings-nav-icon{ font-size:17px; line-height:1; flex-shrink:0; }
  .settings-nav-text{ display:flex; flex-direction:column; flex:1; min-width:0; }
  .settings-nav-label{ font-family:'Inter',sans-serif; font-weight:600; font-size:13px; color:var(--paper,#f2e9d8); }
  .settings-nav-hint{ font-family:'Inter',sans-serif; font-size:10.5px; color:rgba(243,236,221,0.5); margin-top:1px; }
  .settings-nav-arrow{ font-size:18px; color:rgba(243,236,221,0.4); flex-shrink:0; }

  .settings-action-btn{
    display:flex; align-items:center; gap:9px; width:100%; text-align:left;
    background:rgba(212,175,55,0.1); border:1px solid rgba(212,175,55,0.3); color:var(--paper,#f2e9d8);
    font-family:'Inter',sans-serif; font-weight:600; font-size:12.5px; padding:9px 12px; border-radius:8px;
    cursor:pointer; transition:background .15s ease, border-color .15s ease;
  }
  .settings-action-btn:hover{ background:rgba(212,175,55,0.22); border-color:rgba(212,175,55,0.5); }

  .settings-danger-zone{
    display:flex; flex-direction:column; gap:8px; margin-top:4px; padding-top:12px;
    border-top:1px solid rgba(193,68,60,0.25);
  }

  /* reuses .bind-row's row shell (label + hint on the left, control on the right) so General
     settles into the same visual rhythm as Controls instead of inventing a new layout */
  .settings-toggle-row{
    display:flex; align-items:center; justify-content:space-between; gap:8px;
    background:rgba(255,255,255,0.03); border:1px solid rgba(255,255,255,0.06); border-radius:8px;
    padding:8px 10px;
  }
  .toggle-switch{
    position:relative; width:38px; height:22px; flex-shrink:0; border:none; border-radius:11px;
    background:rgba(255,255,255,0.15); cursor:pointer; transition:background .15s ease;
  }
  .toggle-switch::after{
    content:""; position:absolute; top:2px; left:2px; width:18px; height:18px; border-radius:50%;
    background:var(--paper,#f2e9d8); transition:transform .15s ease;
  }
  .toggle-switch.on{ background:var(--gold,#d4af37); }
  .toggle-switch.on::after{ transform:translateX(16px); background:#1a1408; }

  /* ================= DESK PROPS: boxes to rip + reveal spread ================= */
  #deskArea{
    position:fixed; z-index:4; top:0; left:0;
    display:flex; flex-direction:column; gap:8px; align-items:flex-start;
    transform-origin:top left;
  }
  .desk-hint{
    font-family:'Space Mono',monospace; font-size:10px; color:rgba(255,255,255,0.8);
    background:rgba(0,0,0,0.4); padding:3px 9px; border-radius:10px; backdrop-filter:blur(2px);
  }
  #deskBoxes{ display:flex; gap:10px; align-items:flex-end; }

  #deskSpread{
    position:fixed; inset:0; z-index:300;
    display:flex; flex-direction:column; align-items:center; justify-content:flex-start;
    gap:22px; overflow-y:auto;
    background: rgba(8,6,4,0.78); backdrop-filter:blur(2px);
    opacity:0; pointer-events:none; transition:opacity .25s ease;
    /* bottom padding reserves a clear strip beneath the last card row so it can never scroll in
       underneath the fixed #deskSpreadClose button below — see that rule for why they were made
       siblings instead of nesting the button inside this scrolling element */
    padding:60px 20px 110px;
  }
  #deskSpread.open{ opacity:1; pointer-events:auto; }
  #deskSpread .spread-hint{
    font-family:'Space Mono',monospace; font-size:12px; color:rgba(255,255,255,0.75); letter-spacing:1px; text-align:center;
  }
  #deskSpread .fan{ max-width:1100px; }
  /* a sibling of #deskSpread, not a child — a fixed-position child would be trapped inside the
     containing block #deskSpread's own backdrop-filter creates (tested: it tracks that element's
     scroll instead of the viewport), and a sticky child visually overlaps the card grid it's
     stickying over, which fought with the cards' own hover states for the cursor (flickering,
     unreliable clicks right at the button's edge — the thing this fix addresses). As a true
     sibling, fixed positioning is relative to the real viewport, and #deskSpread's bottom padding
     above keeps the card grid entirely out of this strip, so nothing ever sits underneath it. */
  #deskSpreadClose{
    position:fixed; left:50%; bottom:22px; transform:translateX(-50%); z-index:310;
    opacity:0; pointer-events:none; transition:opacity .25s ease;
    box-shadow:0 8px 24px rgba(0,0,0,0.5);
  }
  #deskSpreadClose.open{ opacity:1; pointer-events:auto; }

  .spread-totals{ display:flex; gap:14px; justify-content:center; flex-wrap:wrap; }
  .spread-stat{
    font-family:'Space Mono',monospace; text-align:center; min-width:120px;
    background:rgba(0,0,0,0.35); border:1.5px solid rgba(255,255,255,0.18); border-radius:9px;
    padding:9px 18px; backdrop-filter:blur(2px);
  }
  .spread-stat .label{
    display:block; font-size:10px; letter-spacing:1.5px; text-transform:uppercase;
    color:rgba(255,255,255,0.55); margin-bottom:3px;
  }
  .spread-stat .num{ display:block; font-size:19px; font-weight:700; color:#fff; }
  .spread-stat.profit{ border-color:var(--green); box-shadow:0 0 18px rgba(76,138,94,0.4); }
  .spread-stat.profit .num{ color:#8fe6ab; }
  .spread-stat.loss{ border-color:var(--red); box-shadow:0 0 18px rgba(193,68,60,0.4); }
  .spread-stat.loss .num{ color:#ff9a92; }

  /* ---------- big-hit gem burst: a quick, un-skippable flash the instant a reveal contains a
     1-of-1 / auto / chase pull — deliberately short (~1s) so it reads as a punch, not a pause.
     0.95s here must match triggerGemBurst()'s setTimeout in script.js ---------- */
  .gem-burst{
    position:fixed; inset:0; z-index:400;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px;
    opacity:0; pointer-events:none;
  }
  .gem-burst.show{ animation: gemBurstGlow 0.95s ease forwards; }
  .gem-burst .gem-svg{
    width:150px; height:150px; opacity:0; transform:scale(0.2) rotate(-15deg);
    filter:drop-shadow(0 0 26px rgba(255,210,63,0.85));
  }
  .gem-burst.show .gem-svg{ animation: gemPop 0.95s cubic-bezier(.2,.85,.25,1.3) forwards; }
  .gem-burst .gem-label{
    font-family:'Bangers','Bebas Neue',cursive; font-size:38px; letter-spacing:1.5px; color:#fff;
    -webkit-text-stroke:0.6px rgba(0,0,0,0.45);
    text-shadow:0 2px 4px rgba(0,0,0,0.5), 0 0 20px rgba(255,210,63,0.7);
    opacity:0; transform:translateY(8px) scale(0.85);
  }
  .gem-burst.show .gem-label{ animation: gemLabelPop 0.95s ease forwards; }
  @keyframes gemBurstGlow{
    0%{ opacity:0; background:radial-gradient(circle, rgba(255,210,63,0) 0%, rgba(0,0,0,0) 70%); }
    12%{ opacity:1; background:radial-gradient(circle, rgba(255,210,63,0.32) 0%, rgba(0,0,0,0) 65%); }
    65%{ opacity:1; }
    100%{ opacity:0; }
  }
  @keyframes gemPop{
    0%{ transform:scale(0.2) rotate(-15deg); opacity:0; }
    22%{ transform:scale(1.25) rotate(3deg); opacity:1; }
    40%{ transform:scale(1) rotate(0deg); opacity:1; }
    78%{ transform:scale(1.02); opacity:1; }
    100%{ transform:scale(1.6); opacity:0; }
  }
  @keyframes gemLabelPop{
    0%{ transform:translateY(8px) scale(0.85); opacity:0; }
    28%{ transform:translateY(0) scale(1.06); opacity:1; }
    72%{ opacity:1; }
    100%{ transform:translateY(-6px) scale(1); opacity:0; }
  }

  /* ---------- layout shell ---------- */
  .app{ max-width:1080px; margin:0 auto; padding:22px 18px 60px; }
  /* the computer is fullscreen now (see #zoomScreen above) — let its content actually spread out
     into that space instead of sitting capped at the binder's old windowed width; the card grids
     (repeat(auto-fill, minmax(...))) just lay out more columns automatically at the wider size */
  #zoomScreen .app{ max-width:1600px; }

  .marquee{
    display:flex; align-items:center; justify-content:space-between;
    gap:16px; margin-bottom:18px; flex-wrap:wrap;
  }
  .marquee h1{
    font-family:'Bebas Neue',sans-serif;
    font-size:44px; letter-spacing:2px; margin:0; line-height:0.9;
    background: linear-gradient(180deg, #fff 0%, var(--paper) 55%, #cbb98f 100%);
    -webkit-background-clip:text; background-clip:text; color:transparent;
    text-shadow: 2px 2px 0 var(--red), 4px 4px 0 rgba(0,0,0,0.35), 0 0 22px rgba(212,175,55,0.35);
    filter: drop-shadow(0 0 10px rgba(255,46,99,0.25));
  }
  .marquee .tagline{
    font-family:'Space Mono',monospace; font-size:11px; letter-spacing:1.5px;
    color:var(--gray); text-transform:uppercase; margin-top:2px;
  }

  .register{
    background:linear-gradient(160deg,#151109,#0d0b08 60%); border-radius:8px; padding:10px 18px;
    border:2px solid var(--gold);
    box-shadow: inset 0 0 12px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.08), 0 0 16px rgba(212,175,55,0.25);
    display:flex; align-items:center; gap:14px;
    position:relative; overflow:hidden;
  }
  .register .label{ font-family:'Space Mono',monospace; font-size:10px; color:var(--gray); letter-spacing:1px; text-transform:uppercase;}
  .register .cash{
    font-family:'Space Mono',monospace; font-weight:700; font-size:26px;
    color:#7CFF9E; text-shadow:0 0 10px rgba(124,255,158,0.65);
    transition: text-shadow .3s ease;
  }
  /* spawned by spawnCashFloat() — position:fixed set inline per-instance (JS), so it isn't
     clipped by .register's overflow:hidden the way a normal descendant would be */
  .cash-float{
    position:fixed; pointer-events:none; z-index:500;
    font-family:'Bebas Neue',sans-serif; font-size:18px; letter-spacing:0.5px;
    color:#7CFF9E; text-shadow:0 0 10px rgba(124,255,158,0.8), 0 1px 2px rgba(0,0,0,0.6);
    animation: cashFloatUp 0.9s ease-out forwards;
  }
  .cash-float.neg{
    color:#ff6b6b; text-shadow:0 0 10px rgba(255,107,107,0.8), 0 1px 2px rgba(0,0,0,0.6);
  }
  @keyframes cashFloatUp{
    0%{ opacity:0; transform:translate(-50%, 0) scale(0.9); }
    15%{ opacity:1; transform:translate(-50%, -8px) scale(1); }
    100%{ opacity:0; transform:translate(-50%, -36px) scale(1); }
  }
  .register .rep{
    position:relative; font-family:'Space Mono',monospace; font-size:15px; letter-spacing:2px;
    border-left:1px solid var(--counter-light); padding-left:14px; cursor:default;
  }
  /* classic "two stacked star rows, foreground clipped to a %" trick — gives smooth partial-star
     fill (e.g. 1 of 3 unlocks = 33% filled) without needing separate half-star glyphs */
  .register .rep .stars-bg{ color:rgba(255,255,255,0.22); }
  .register .rep .stars-fg{
    position:absolute; top:0; left:14px; width:0%; overflow:hidden; white-space:nowrap;
    color:var(--gold); text-shadow:0 0 8px rgba(212,175,55,0.6);
    transition: width .4s ease;
  }
  .day-block{ border-left:1px solid var(--counter-light); padding-left:14px; }
  .day-block .label{ color:var(--paper); }
  .day-block .label span{ color:var(--gold); }
  .billnote{ font-family:'Space Mono',monospace; font-size:10.5px; color:var(--gray); margin-top:2px; }
  .billnote.due-soon{ color:var(--red); }
  .day-actions{ display:flex; gap:5px; margin-top:5px; }
  .pay-bills-btn{
    font-family:'Space Mono',monospace; font-size:9.5px; font-weight:700; letter-spacing:0.5px;
    padding:3px 9px; border-radius:4px; cursor:pointer;
    background:linear-gradient(180deg,#e6c458,var(--gold)); color:#2a2205; border:1px solid rgba(0,0,0,0.35);
    transition: filter .15s ease;
  }
  .pay-bills-btn:hover:not(:disabled){ filter:brightness(1.1); }
  .pay-bills-btn:disabled{ background:var(--counter-light); color:var(--gray); cursor:not-allowed; border-color:var(--counter-light); }
  .skip-time-btn{
    font-family:'Space Mono',monospace; font-size:9.5px; font-weight:700; letter-spacing:0.5px;
    padding:3px 9px; border-radius:4px; cursor:pointer;
    background:var(--counter-light); color:var(--paper); border:1px solid rgba(255,255,255,0.15);
    transition: filter .15s ease;
  }
  .skip-time-btn:hover:not(:disabled){ filter:brightness(1.25); }
  .skip-time-btn:disabled{ opacity:0.5; cursor:not-allowed; }

  /* ---------- tabs ---------- */
  .tabs{ display:flex; gap:6px; margin-bottom:0; flex-wrap:wrap; }
  .tab{
    font-family:'Bebas Neue',sans-serif; letter-spacing:1px; font-size:18px;
    background:linear-gradient(180deg, var(--counter-light), var(--counter)); color:var(--cardboard);
    border:none; padding:9px 20px 7px; border-radius:6px 6px 0 0;
    cursor:pointer; position:relative; top:2px;
    transition: transform .12s ease, background .12s ease, color .12s ease, box-shadow .12s ease;
  }
  .tab .count{
    font-family:'Space Mono',monospace; font-size:11px; margin-left:6px;
    background:rgba(0,0,0,0.3); padding:1px 6px; border-radius:10px;
  }
  /* no transform here on purpose — see the big comment on .mini-btn:hover below for why a
     hover-triggered translateY/scale on the SAME element that owns :hover can self-cancel into a
     rapid flicker right at its edge; box-shadow alone still gives a clear "lifted" feel */
  .tab:hover{ box-shadow:0 4px 12px rgba(0,0,0,0.35); }
  .tab.active{
    background:linear-gradient(180deg,#fdf8ec,var(--cardboard)); color:var(--ink); top:0; box-shadow:var(--shadow);
  }
  .tab.active::after{
    content:""; position:absolute; left:10%; right:10%; bottom:-2px; height:3px; border-radius:3px;
    background:linear-gradient(90deg, var(--accent2), var(--gold), var(--accent));
    box-shadow:0 0 8px rgba(212,175,55,0.6);
  }
  .tab.active .count{ background:rgba(0,0,0,0.12); }

  .panel{
    /* fixed-length stops (not percentages) so the gradient always reaches the same tones at the
       same distance from the top, regardless of how tall a given tab's content makes the panel —
       percentage stops would stretch across taller tabs (e.g. a full Auctions/Buy grid) and read
       as a visibly brighter page than a shorter one showing the same viewport height */
    background:linear-gradient(165deg, #eaddc0, var(--cardboard) 170px, var(--cardboard-dark) 560px);
    color:var(--ink);
    border-radius:4px 10px 10px 10px;
    padding:24px;
    box-shadow:var(--shadow), 0 0 0 1px rgba(255,255,255,0.15) inset;
    min-height:420px;
    background-image:
      repeating-linear-gradient(135deg, rgba(0,0,0,0.025) 0 2px, transparent 2px 6px),
      linear-gradient(165deg, #eaddc0, var(--cardboard) 170px, var(--cardboard-dark) 560px);
    position:relative;
  }
  .panel h2{
    font-family:'Bebas Neue',sans-serif; font-size:26px; letter-spacing:1px;
    margin:0 0 4px; color:var(--counter);
  }
  .panel .sub{
    font-family:'Inter',sans-serif; font-size:13.5px; color:#5a4c3a; margin-bottom:20px; max-width:640px;
    line-height:1.5;
  }
  /* #binderPanel (the Binder/"My Collection" screen) reuses the exact same h2/.sub markup as every
     other tab, but was never actually inside a `.panel`-classed element — it sits in its own
     #binderScreen, not #zoomScreen's #panel — so the two rules above silently never applied there.
     Browser-default h2 margins (~20px top AND bottom) plus a totally unstyled .sub (0 margin) left
     zero gap between the subtitle and the toggle buttons right below it while everything else in the
     header was correctly spaced — that's the "crowded at the top" bug. Same layout metrics as
     `.panel h2`/`.panel .sub` above, but light colors (var(--paper), the same muted tone
     .binder-count already uses) instead of those two's dark ink — `.panel`'s colors are tuned for
     its own light tan cardboard background, which the Binder's dark "shelf" backdrop deliberately
     doesn't share. */
  #binderPanel h2{
    font-family:'Bebas Neue',sans-serif; font-size:26px; letter-spacing:1px;
    margin:0 0 4px; color:var(--paper);
  }
  #binderPanel .sub{
    font-family:'Inter',sans-serif; font-size:13.5px; color:rgba(243,236,221,0.7); margin-bottom:20px; max-width:640px;
    line-height:1.5;
  }
  .grades-badge{
    position:absolute; top:20px; right:24px;
    font-family:'Space Mono',monospace; font-size:12px; font-weight:700;
    padding:6px 12px; border-radius:20px; letter-spacing:0.3px;
    background:linear-gradient(180deg,#e6c458,var(--gold)); color:#2a2205;
    box-shadow:0 2px 6px rgba(0,0,0,0.25);
  }
  .grades-badge.zero{ background:linear-gradient(180deg,#d9635a,var(--red)); color:#ffecea; }

  /* ---------- SOURCE tab: lots ---------- */
  .lots{ display:grid; grid-template-columns:repeat(auto-fill, minmax(230px,1fr)); gap:16px; }
  /* shared base look for every card-shaped tile in the app — lot, inventory, market, listing,
     and email cards all share this same paper/border/shadow treatment; each keeps its own
     padding, layout, cursor, transition and hover styling below since those genuinely differ */
  .lot-card, .inv-card, .market-card, .listing, .email-card{
    background:linear-gradient(160deg,#fbf6e8,var(--paper) 55%);
    border-radius:8px; border:2px solid var(--cardboard-dark);
    box-shadow:0 3px 10px rgba(0,0,0,0.12);
  }
  .lot-card{
    padding:16px;
    display:flex; flex-direction:column; gap:8px;
    position:relative; overflow:hidden;
    transition: transform .18s ease, box-shadow .18s ease;
  }
  .lot-card:hover{ transform:translateY(-4px); box-shadow:0 10px 22px rgba(0,0,0,0.28); }
  .lot-card .risk-tag{
    position:absolute; top:10px; right:-30px; transform:rotate(35deg);
    font-family:'Space Mono',monospace; font-size:9.5px; font-weight:700;
    padding:2px 34px; letter-spacing:1px; box-shadow:0 2px 4px rgba(0,0,0,0.25);
  }
  .risk-low .risk-tag{ background:linear-gradient(180deg,#5fb377,var(--green)); color:#eafff0;}
  .risk-mid .risk-tag{ background:linear-gradient(180deg,#e6c458,var(--gold)); color:#2a2205;}
  .risk-high .risk-tag{ background:linear-gradient(180deg,#d9635a,var(--red)); color:#ffecea;}
  .lot-card .name{ font-family:'Bebas Neue',sans-serif; font-size:22px; letter-spacing:0.5px;}
  /* fits the longest lot description at 4 lines (Mega Box) so every card's meta/dropdowns/price/
     button start at the same row regardless of how long that particular lot's blurb runs */
  .lot-card .desc{ font-size:12.5px; color:#6b5c46; line-height:1.4; min-height:70px;}
  .lot-card .meta{ font-family:'Space Mono',monospace; font-size:11px; color:#8a7960; display:flex; justify-content:space-between;}
  .lot-card .product-summary{
    font-family:'Space Mono',monospace; font-size:10.5px; color:var(--counter); font-weight:700;
    letter-spacing:0.2px;
  }
  .lot-card .price{ font-family:'Space Mono',monospace; font-size:20px; font-weight:700; color:var(--counter);}
  .lot-card.locked{ filter:grayscale(0.6); }
  .lock-overlay{
    position:absolute; inset:0; z-index:5; cursor:pointer;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px;
    background:rgba(30,26,20,0.82); border-radius:6px;
    color:#f4ecd8; text-align:center; padding:10px;
  }
  .lock-icon{ font-size:28px; }
  .lock-name{ font-family:'Bebas Neue',sans-serif; font-size:18px; letter-spacing:0.5px; }
  .lock-cost{ font-family:'Space Mono',monospace; font-size:12px; color:var(--gold); font-weight:700; }
  .brand-select, .product-select, .sport-select, .set-select{
    font-family:'Space Mono',monospace; font-size:11.5px; color:var(--counter);
    background:var(--paper); border:1.5px solid var(--cardboard-dark); border-radius:5px;
    padding:6px 8px; cursor:pointer;
  }
  .sort-controls{ display:flex; align-items:center; gap:8px; margin-bottom:12px; flex-wrap:wrap; }
  .sort-label{ font-family:'Space Mono',monospace; font-size:11.5px; color:#6b5c46; letter-spacing:0.5px; text-transform:uppercase; }
  .inv-filter-count{ margin-left:auto; text-transform:none; letter-spacing:0; }

  .bulk-actions{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:18px; }
  .bulk-btn{
    font-family:'Space Mono',monospace; font-size:11px; font-weight:700; letter-spacing:0.3px;
    padding:8px 12px; border-radius:6px; cursor:pointer; border:1.5px solid transparent;
    transition: transform .1s ease, filter .15s ease, box-shadow .15s ease;
  }
  .bulk-btn:hover:not(:disabled){ filter:brightness(1.06); }
  .bulk-btn:disabled{ opacity:0.4; cursor:not-allowed; }
  .bulk-btn.sell{
    background:linear-gradient(180deg,#d9635a,var(--red)); color:#fff; border-color:var(--red);
    box-shadow:0 3px 8px rgba(193,68,60,0.35);
  }
  .bulk-btn.list{
    background:linear-gradient(180deg,#6a94c7,var(--blue)); color:#eaf2fb; border-color:var(--blue);
    box-shadow:0 3px 8px rgba(62,111,166,0.35);
  }
  .bulk-btn.grade{
    background:linear-gradient(180deg,#e6c458,var(--gold)); color:#2a2205; border-color:var(--gold);
    box-shadow:0 3px 8px rgba(212,175,55,0.35);
  }
  .bulk-btn.keep{
    background:linear-gradient(180deg,#8a6a44,#6b4a2c); color:var(--paper); border-color:#6b4a2c;
    box-shadow:0 3px 8px rgba(107,74,44,0.35);
  }
  .bulk-btn.commons{
    background:linear-gradient(180deg,#d9635a,var(--red)); color:#fff; border-color:var(--red);
    box-shadow:0 3px 8px rgba(193,68,60,0.35);
  }
  .bulk-btn.relist-all{
    background:linear-gradient(180deg,#3fe0dc,var(--accent)); color:#04302f; border-color:var(--accent);
    box-shadow:0 3px 8px rgba(8,217,214,0.35);
  }
  .mini-btn.keep{ border-color:#6b4a2c; color:#6b4a2c; }
  .mini-btn.keep:hover:not(:disabled){ background:#6b4a2c; color:var(--paper); }
  .buy-btn{
    font-family:'Bebas Neue',sans-serif; font-size:16px; letter-spacing:1px;
    background:linear-gradient(180deg, var(--counter-light), var(--counter)); color:var(--cardboard); border:none; border-radius:5px;
    padding:9px; cursor:pointer; transition:transform .12s, background .15s, box-shadow .15s;
    box-shadow:0 3px 8px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.12);
  }
  .buy-btn:hover:not(:disabled){
    background:linear-gradient(180deg,#d9635a,var(--red));
    box-shadow:0 6px 14px rgba(193,68,60,0.45), inset 0 1px 0 rgba(255,255,255,0.2);
  }
  .buy-btn:disabled{ opacity:0.4; cursor:not-allowed; }

  /* ---------- box art ---------- */
  .box{
    position:relative; cursor:pointer; border-radius:6px; overflow:hidden;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
    text-align:center; box-shadow:0 5px 12px rgba(0,0,0,0.35);
    transition: transform .18s ease, box-shadow .18s ease;
    animation: boxAppear .5s cubic-bezier(.2,.9,.3,1.2) backwards;
  }
  .box:hover{ transform:translateY(-6px) scale(1.09); box-shadow:0 12px 22px rgba(0,0,0,0.45); }
  .box.opening{ cursor:default; pointer-events:none; }
  .box .box-label{
    font-family:'Bebas Neue',sans-serif; letter-spacing:0.5px; position:relative; z-index:2;
  }
  .box .box-sub{
    font-family:'Space Mono',monospace; font-size:8px; letter-spacing:0.5px; position:relative; z-index:2; opacity:0.85;
  }
  .box-mono{
    position:absolute; top:5px; left:5px; z-index:3;
    font-family:'Space Mono',monospace; font-weight:700; font-size:8px; width:16px; height:16px;
    border-radius:50%; border:1.5px solid; display:flex; align-items:center; justify-content:center;
    background:rgba(0,0,0,0.4); color:#fff;
  }
  @keyframes boxAppear{
    0%{ opacity:0; transform:scale(0.4) translateY(30px) rotate(-8deg); }
    65%{ opacity:1; transform:scale(1.08) translateY(-5px) rotate(2deg); }
    100%{ opacity:1; transform:scale(1) translateY(0) rotate(0deg); }
  }
  /* total shake+burst time (.32s + .32s = 640ms) must match triggerRip()'s setTimeout in script.js */
  .box.opening{ animation: boxAppear .5s cubic-bezier(.2,.9,.3,1.2) backwards, boxShake .32s ease-in-out, boxBurst .32s ease-in .32s forwards; }
  @keyframes boxShake{
    0%,100%{ transform:translateX(0) rotate(0); }
    20%{ transform:translateX(-5px) rotate(-4deg); }
    40%{ transform:translateX(5px) rotate(4deg); }
    60%{ transform:translateX(-4px) rotate(-3deg); }
    80%{ transform:translateX(4px) rotate(3deg); }
  }
  @keyframes boxBurst{
    0%{ transform:scale(1); opacity:1; filter:brightness(1); }
    55%{ transform:scale(1.18); opacity:1; filter:brightness(1.7); }
    100%{ transform:scale(0.82); opacity:0; filter:brightness(2.2); }
  }
  .box.opening::after{
    content:""; position:absolute; inset:-30px; z-index:5; pointer-events:none;
    background: radial-gradient(circle, rgba(255,255,255,0.95) 0%, rgba(255,255,255,0) 68%);
    opacity:0; animation: boxFlash .32s ease-in .32s forwards;
  }
  @keyframes boxFlash{ 0%{opacity:0;} 55%{opacity:1;} 100%{opacity:0;} }

  /* Blaster: small retail rack box, bold two-tone with a hype sticker */
  .box-blaster{
    width:72px; height:96px; border:2px solid #16120D;
    background: linear-gradient(135deg, #e6483e 0%, #e6483e 46%, #2b6fc4 46%, #2b6fc4 100%);
  }
  .box-blaster .box-label{ font-size:13px; color:#fff; text-shadow:1px 1px 0 rgba(0,0,0,0.4); }
  .box-blaster .box-sub{ color:rgba(255,255,255,0.85); }
  .box-blaster::before{
    content:""; position:absolute; inset:0;
    background: repeating-linear-gradient(-45deg, rgba(255,255,255,0.16) 0 4px, transparent 4px 10px);
  }
  .box-blaster .box-badge{
    position:absolute; top:5px; right:-15px; transform:rotate(35deg); z-index:2;
    background:#ffe14d; color:#3a2a05; font-family:'Space Mono',monospace; font-size:6.5px; font-weight:700;
    padding:1px 15px; letter-spacing:0.5px;
  }

  /* Hobby: dark foil box with a moving shine sweep */
  .box-hobby{
    width:82px; height:108px; border:2px solid var(--gold);
    background: linear-gradient(160deg, #16120D 0%, #2b2118 100%);
  }
  .box-hobby .box-label{ font-size:14px; color:var(--gold); text-shadow:0 0 6px rgba(212,175,55,0.5); }
  .box-hobby .box-sub{ color:rgba(217,195,160,0.65); }
  .box-hobby::before{
    content:""; position:absolute; inset:0;
    background: repeating-linear-gradient(45deg, rgba(212,175,55,0.14) 0 2px, transparent 2px 14px);
  }
  .box-hobby::after{
    content:""; position:absolute; top:0; left:-60%; width:35%; height:100%; z-index:1;
    background:linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
    transform:skewX(-20deg); animation: hobbyShine 3.4s ease-in-out infinite;
  }
  @keyframes hobbyShine{ 0%{ left:-60%; } 45%{ left:130%; } 100%{ left:130%; } }

  /* Mega: oversized sunburst box */
  .box-mega{
    width:94px; height:114px; border:2px solid #7a2a1c;
    background: radial-gradient(circle at 50% 38%, #ffd23f 0%, #ff8a3d 48%, #e6483e 100%);
  }
  .box-mega::before{
    content:""; position:absolute; inset:-15%; z-index:0;
    background: repeating-conic-gradient(from 0deg, rgba(255,255,255,0.28) 0deg 8deg, transparent 8deg 16deg);
    mix-blend-mode:overlay;
  }
  .box-mega .box-label{ font-size:17px; color:#fff; text-shadow:1px 2px 0 rgba(0,0,0,0.45); }
  .box-mega .box-sub{ color:#fff; background:rgba(0,0,0,0.28); padding:1px 7px; border-radius:8px; }

  /* Case: sealed cardboard shipping case with tape band + stamp */
  .box-case{
    width:122px; height:96px; border:2px solid #7a5a34;
    background: repeating-linear-gradient(0deg, #c2a87e 0 3px, #b89a6e 3px 6px);
  }
  .box-case::before{
    content:""; position:absolute; left:0; right:0; top:50%; height:15px; transform:translateY(-50%); z-index:1;
    background:rgba(230,224,204,0.6); box-shadow:0 0 0 1px rgba(0,0,0,0.08) inset;
  }
  .box-case .box-stamp{
    position:absolute; bottom:7px; left:50%; transform:translateX(-50%) rotate(-4deg); z-index:2;
    font-family:'Space Mono',monospace; font-weight:700; font-size:10px; letter-spacing:2px;
    color:#7a2a1c; border:2px solid #7a2a1c; padding:0px 5px; opacity:0.8;
  }
  .box-case .box-label{ font-size:13px; color:#3a2a15; margin-top:-14px; }
  .box-case .box-sub{ color:#5a4c3a; }

  .fan{ display:flex; gap:16px; flex-wrap:wrap; justify-content:center; align-items:flex-start; }
  .pull-wrap{ display:flex; flex-direction:column; align-items:center; gap:7px; }
  /* reusable "under glass" gloss — a fixed diagonal glass highlight (top-left) plus a soft cool
     falloff (bottom-right), independent of the animated shine sweep below, so every card reads as
     reflective foil even between sweeps. Referenced from every rarity/insert box-shadow rule since
     each of those replaces .pull-card's own box-shadow wholesale rather than layering onto it. */
  .pull-card{
    --gloss: inset 0 1px 0 rgba(255,255,255,0.5),
             inset 40px -70px 70px -45px rgba(255,255,255,0.35),
             inset -30px 40px 60px -40px rgba(255,255,255,0.15);
    width:120px; height:150px; border-radius:9px;
    background:linear-gradient(160deg,#fff,#eee);
    border:3px solid #222; position:relative; overflow:hidden; cursor:pointer;
    display:flex; flex-direction:column; padding:0;
    box-shadow:0 8px 18px rgba(0,0,0,0.35), var(--gloss);
    animation: dealIn .45s cubic-bezier(.2,.9,.3,1.2) backwards;
    transform-origin:bottom center;
    transition: transform .15s ease;
  }
  .pull-card:hover{ transform:scale(1.04) rotate(var(--tilt,0deg)); }
  /* animated glass-reflection sweep — wider and brighter than a plain white glint, with a faint
     cyan/magenta fringe on each side (like chromatic aberration on real foil) so it reads as a
     light source moving across a reflective surface rather than just a static highlight */
  .pull-card::after{
    content:""; position:absolute; top:-30%; left:-60%; width:38%; height:170%; z-index:4;
    background:linear-gradient(120deg, transparent, rgba(120,220,255,0.22) 32%, rgba(255,255,255,0.68) 48%, rgba(255,160,230,0.22) 64%, transparent);
    transform:rotate(20deg); pointer-events:none;
    animation: cardShine 7s ease-in-out infinite;
    animation-delay: var(--shine-delay, 0s);
  }
  @keyframes cardShine{
    0%{ left:-60%; } 8%{ left:130%; } 100%{ left:130%; }
  }
  @keyframes dealIn{
    0%{ opacity:0; transform:translateY(-40px) rotate(-8deg) scale(0.7);}
    100%{ opacity:1; transform:translateY(0) rotate(var(--tilt,0deg)) scale(1);}
  }
  .pull-card .card-top{
    position:relative; z-index:3; display:flex; flex-direction:column; align-items:flex-start; gap:4px;
    padding:8px 8px 0; flex-shrink:0; max-height:52px; overflow:hidden;
  }
  .card-top-row{ display:flex; align-items:center; justify-content:space-between; width:100%; gap:6px; }
  .set-monogram{
    font-family:'Space Mono',monospace; font-weight:700; font-size:8px; width:16px; height:16px;
    border-radius:50%; border:1.5px solid; flex-shrink:0;
    display:flex; align-items:center; justify-content:center; background:rgba(0,0,0,0.4);
  }
  .pull-card .rarity-tag{
    font-family:'Space Mono',monospace; font-size:8.5px; font-weight:700; letter-spacing:0.5px;
    padding:2px 5px; border-radius:3px; color:#fff;
  }
  .pull-card .portrait{
    flex:1; position:relative; z-index:1; display:flex; align-items:center; justify-content:center;
  }
  .pull-card .portrait svg{ width:56%; height:auto; filter:drop-shadow(0 3px 6px rgba(0,0,0,0.35)); }
  .pull-card .card-bottom{
    position:relative; z-index:3; padding:8px 8px; flex-shrink:0;
    background:linear-gradient(0deg, rgba(0,0,0,0.85), rgba(0,0,0,0.4) 75%, transparent);
  }
  .pull-card .p-name{
    font-family:'Bebas Neue',sans-serif; font-size:14px; line-height:1.05; color:#fff;
    text-shadow:0 1px 3px rgba(0,0,0,0.7);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .pull-card .p-brand{
    font-family:'Space Mono',monospace; font-size:7.5px; color:rgba(255,255,255,0.8);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .pull-wrap .p-val-chip{
    font-family:'Space Mono',monospace; font-size:13px; font-weight:700;
    background:var(--ink); color:#7CFF9E; padding:3px 12px; border-radius:20px;
    box-shadow:0 3px 8px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.1);
    border:1px solid rgba(255,255,255,0.15);
    animation: chipIn .3s ease backwards;
  }
  @keyframes chipIn{
    0%{ opacity:0; transform:translateY(-6px) scale(0.85); }
    100%{ opacity:1; transform:translateY(0) scale(1); }
  }
  .rarity-common{ box-shadow:0 8px 18px rgba(0,0,0,0.35), var(--gloss); }
  .rarity-uncommon{
    box-shadow:0 0 0 2px var(--green), 0 8px 18px rgba(76,138,94,0.4), var(--gloss);
    background:linear-gradient(160deg,#eafff0,#c9f2d4);
  }
  .rarity-rare{
    box-shadow:0 0 0 2px var(--blue), 0 8px 22px rgba(62,111,166,0.5), var(--gloss);
    background:linear-gradient(160deg,#eaf2ff,#c7dbf5);
  }
  .rarity-chase{
    box-shadow:0 0 0 3px var(--gold), 0 0 28px rgba(212,175,55,0.75), var(--gloss);
    background:linear-gradient(160deg,#fff8e5,#f6e6ad);
    animation: dealIn .45s cubic-bezier(.2,.9,.3,1.2) backwards, shimmer 2.2s ease-in-out infinite;
  }
  @keyframes shimmer{
    0%,100%{ filter:brightness(1);} 50%{ filter:brightness(1.18);}
  }

  /* ---------- card special attributes: insert / numbered / mem / diecut / auto ---------- */
  .card-badges{ display:flex; gap:3px; flex-wrap:wrap; position:relative; z-index:3; }
  .cbadge{
    font-family:'Space Mono',monospace; font-size:6.5px; font-weight:700; letter-spacing:0.3px;
    padding:1.5px 4px; border-radius:3px; color:#fff; text-transform:uppercase; white-space:nowrap;
  }
  .cbadge.auto{ background:#111; border:1px solid #fff; }
  .cbadge.mem{ background:#6b4f27; }
  .cbadge.diecut{ background:#3a3a3a; }
  .cbadge.numbered{ background:#111; color:#ffd23f; border:1px solid #ffd23f; }
  .cbadge.oneofone{ background:#3a2a05; box-shadow:0 0 6px rgba(255,210,63,0.9); animation:pulse 1.4s infinite; }
  .cbadge.rookie{ background:#1f5c3a; }
  .cbadge.hot{ background:linear-gradient(90deg,#c1443c,#e0793a); box-shadow:0 0 6px rgba(193,68,60,0.6); }
  /* opposite of .hot above — a card that's sat unsold through multiple relist cycles (see
     card.noSaleCount / cardBadgesHTML), or a Trending name whose price is actually falling, not
     just a slow one. Same treatment, icy blue instead of fire, so the two read as a clear pair. */
  .cbadge.cold{ background:linear-gradient(90deg,#2c5f7a,#3ec6e0); box-shadow:0 0 6px rgba(62,198,224,0.6); }

  .pull-wrap.insert .p-val-chip{ border-color:rgba(255,255,255,0.4); }
  .pull-card.insert-card{ box-shadow:0 8px 18px rgba(0,0,0,0.35), 0 0 16px 2px rgba(255,255,255,0.35), var(--gloss); }
  .inspect-face.insert-card{ box-shadow:0 0 22px 3px rgba(255,255,255,0.3), var(--gloss); }

  /* ---------- minigame bonus pulls in the reveal spread: flagged separately from the cards
     the deal itself paid for, so it's obvious which card the minigame actually won ---------- */
  .bonus-ribbon{
    font-family:'Space Mono',monospace; font-size:9px; font-weight:700; letter-spacing:0.5px;
    text-transform:uppercase; padding:3px 10px; border-radius:20px; color:#3a2a05;
    background:linear-gradient(180deg,#ffe17a,#ffbf3f);
    box-shadow:0 2px 6px rgba(0,0,0,0.35); animation: chipIn .3s ease backwards;
  }
  .bonus-ribbon.hit{
    background:linear-gradient(180deg,#9dffb8,#3ecf6a); color:#0a2e14;
    box-shadow:0 0 8px rgba(124,255,158,0.7), 0 2px 6px rgba(0,0,0,0.35);
  }
  .pull-card.bonus-card{
    box-shadow:0 8px 18px rgba(0,0,0,0.35), 0 0 0 3px #ffbf3f, 0 0 18px 3px rgba(255,191,63,0.65), var(--gloss);
  }

  .mem-swatch{
    position:absolute; top:36px; right:8px; width:22px; height:30px; border-radius:3px; z-index:3;
    background: repeating-linear-gradient(45deg, #8a6a3c 0 3px, #6b4f27 3px 6px);
    border:1px dashed rgba(255,255,255,0.75); box-shadow:0 2px 5px rgba(0,0,0,0.35);
  }

  /* ---------- baked-art cards: the new full-card non-sport art already prints a TYPE/CLASS/LEVEL
     plate top-right and a name/stats/rarity bar across the bottom (see NONSPORT_SUBJ_PORTRAITS) —
     .set-monogram's default flex layout would land it square on that top-right plate, and
     .card-bottom's opaque bar would sit right over the bottom one (cardFaceHTML already drops the
     mem-swatch/auto-sig overlays and the whole .card-bottom bar for these, since their info is
     already in .card-badges or baked into the art), so this keeps what's left confined to
     .card-top's own corner, which the template always leaves clear of baked text. */
  .baked-art .card-top-row{ justify-content:flex-start; }
  .baked-brand{
    font-family:'Space Mono',monospace; font-size:7.5px; color:rgba(255,255,255,0.85);
    text-shadow:0 1px 3px rgba(0,0,0,0.85), 0 0 4px rgba(0,0,0,0.6);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%;
  }

  /* ---------- set identity: holographic refractor foil — a diagonal rainbow diffraction band plus
     scattered sparkle flecks, blended INTO the photo/color beneath (mix-blend-mode) rather than
     sitting on top of it as a flat tint, the way real Chrome/Prizm-style trading cards catch light.
     The 6 variants keep some brand identity via the rainbow band's angle/hue-bias and the sparkle
     grain's size, but all share the same foil recipe so every card front reads as reflective. */
  .pull-card.pat-stripes::before, .pull-card.pat-dots::before, .pull-card.pat-grid::before,
  .pull-card.pat-chevron::before, .pull-card.pat-hex::before, .pull-card.pat-circuit::before{
    content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
    mix-blend-mode:overlay; opacity:0.42;
  }
  .inspect-back.pat-stripes::after, .inspect-back.pat-dots::after, .inspect-back.pat-grid::after,
  .inspect-back.pat-chevron::after, .inspect-back.pat-hex::after, .inspect-back.pat-circuit::after{
    content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
    mix-blend-mode:overlay; opacity:0.42;
  }
  .pull-card.pat-stripes::before, .inspect-back.pat-stripes::after{
    background-image:
      repeating-linear-gradient(100deg, rgba(255,60,60,0.65) 0%, rgba(255,170,40,0.65) 8%, rgba(230,230,50,0.65) 16%, rgba(70,220,90,0.65) 24%, rgba(50,210,220,0.65) 32%, rgba(60,120,240,0.65) 40%, rgba(160,60,240,0.65) 48%, rgba(240,60,200,0.65) 56%, rgba(255,60,60,0.65) 64%),
      radial-gradient(circle at 18% 22%, rgba(255,255,255,0.9) 0 1.4px, transparent 1.8px),
      radial-gradient(circle at 62% 12%, rgba(255,255,255,0.8) 0 1.1px, transparent 1.5px),
      radial-gradient(circle at 40% 45%, rgba(255,255,255,0.85) 0 1.3px, transparent 1.7px),
      radial-gradient(circle at 85% 38%, rgba(255,255,255,0.75) 0 1.1px, transparent 1.5px),
      radial-gradient(circle at 12% 68%, rgba(255,255,255,0.8) 0 1.2px, transparent 1.6px),
      radial-gradient(circle at 70% 75%, rgba(255,255,255,0.85) 0 1.4px, transparent 1.8px),
      radial-gradient(circle at 92% 88%, rgba(255,255,255,0.7) 0 1.1px, transparent 1.5px),
      radial-gradient(circle at 30% 90%, rgba(255,255,255,0.75) 0 1.2px, transparent 1.6px);
    background-size: 220% 220%, 26px 26px, 30px 30px, 24px 24px, 28px 28px, 27px 27px, 25px 25px, 32px 32px, 29px 29px;
  }
  .pull-card.pat-dots::before, .inspect-back.pat-dots::after{
    background-image:
      repeating-linear-gradient(96deg, rgba(255,60,60,0.6) 0%, rgba(255,170,40,0.6) 8%, rgba(230,230,50,0.6) 16%, rgba(70,220,90,0.6) 24%, rgba(50,210,220,0.6) 32%, rgba(60,120,240,0.6) 40%, rgba(160,60,240,0.6) 48%, rgba(240,60,200,0.6) 56%, rgba(255,60,60,0.6) 64%),
      radial-gradient(circle, rgba(255,255,255,0.85) 0 1.2px, transparent 1.5px);
    background-size: 220% 220%, 15px 15px;
  }
  .pull-card.pat-grid::before, .inspect-back.pat-grid::after{
    background-image:
      repeating-linear-gradient(104deg, rgba(255,60,60,0.6) 0%, rgba(255,170,40,0.6) 8%, rgba(230,230,50,0.6) 16%, rgba(70,220,90,0.6) 24%, rgba(50,210,220,0.6) 32%, rgba(60,120,240,0.6) 40%, rgba(160,60,240,0.6) 48%, rgba(240,60,200,0.6) 56%, rgba(255,60,60,0.6) 64%),
      radial-gradient(circle, rgba(255,255,255,0.8) 0 1.3px, transparent 1.7px);
    background-size: 220% 220%, 22px 22px;
  }
  .pull-card.pat-chevron::before, .inspect-back.pat-chevron::after{
    background-image:
      repeating-linear-gradient(80deg, rgba(255,60,60,0.6) 0%, rgba(255,170,40,0.6) 8%, rgba(230,230,50,0.6) 16%, rgba(70,220,90,0.6) 24%, rgba(50,210,220,0.6) 32%, rgba(60,120,240,0.6) 40%, rgba(160,60,240,0.6) 48%, rgba(240,60,200,0.6) 56%, rgba(255,60,60,0.6) 64%),
      radial-gradient(circle at 22% 30%, rgba(255,255,255,0.85) 0 1.3px, transparent 1.7px),
      radial-gradient(circle at 68% 55%, rgba(255,255,255,0.75) 0 1.1px, transparent 1.5px),
      radial-gradient(circle at 40% 80%, rgba(255,255,255,0.8) 0 1.3px, transparent 1.7px);
    background-size: 220% 220%, 26px 26px, 24px 24px, 28px 28px;
  }
  .pull-card.pat-hex::before, .inspect-back.pat-hex::after{
    background-image:
      repeating-linear-gradient(120deg, rgba(255,60,60,0.6) 0%, rgba(255,170,40,0.6) 8%, rgba(230,230,50,0.6) 16%, rgba(70,220,90,0.6) 24%, rgba(50,210,220,0.6) 32%, rgba(60,120,240,0.6) 40%, rgba(160,60,240,0.6) 48%, rgba(240,60,200,0.6) 56%, rgba(255,60,60,0.6) 64%),
      radial-gradient(circle at 30% 25%, rgba(255,255,255,0.85) 0 1.4px, transparent 1.8px),
      radial-gradient(circle at 75% 60%, rgba(255,255,255,0.75) 0 1.1px, transparent 1.5px),
      radial-gradient(circle at 15% 78%, rgba(255,255,255,0.8) 0 1.3px, transparent 1.7px);
    background-size: 220% 220%, 30px 30px, 27px 27px, 32px 32px;
  }
  /* Future set only — biased toward the cyan/blue end of the spectrum so it still reads as
     distinctly "tech" next to the 5 warmer-leaning brand patterns above */
  .pull-card.pat-circuit::before, .inspect-back.pat-circuit::after{
    background-image:
      repeating-linear-gradient(100deg, rgba(50,210,220,0.65) 0%, rgba(60,120,240,0.65) 14%, rgba(160,60,240,0.6) 28%, rgba(50,210,220,0.65) 42%, rgba(120,255,220,0.6) 56%, rgba(60,120,240,0.65) 70%, rgba(50,210,220,0.65) 84%),
      radial-gradient(circle at 20% 24%, rgba(200,250,255,0.9) 0 1.6px, transparent 2px),
      radial-gradient(circle at 60% 14%, rgba(200,250,255,0.8) 0 1.3px, transparent 1.7px),
      radial-gradient(circle at 82% 42%, rgba(200,250,255,0.85) 0 1.5px, transparent 1.9px),
      radial-gradient(circle at 38% 58%, rgba(200,250,255,0.8) 0 1.3px, transparent 1.7px),
      radial-gradient(circle at 12% 82%, rgba(200,250,255,0.85) 0 1.5px, transparent 1.9px),
      radial-gradient(circle at 70% 88%, rgba(200,250,255,0.8) 0 1.3px, transparent 1.7px);
    background-size: 220% 220%, 34px 34px, 30px 30px, 36px 36px, 32px 32px, 30px 30px, 34px 34px;
  }

  .auto-sig{
    position:absolute; bottom:48px; left:6px; right:6px; z-index:2;
    font-family:'Caveat',cursive; font-size:20px; line-height:1; color:rgba(255,255,255,0.88);
    text-shadow:0 1px 2px rgba(0,0,0,0.5);
    transform:rotate(-6deg); pointer-events:none; white-space:nowrap; overflow:hidden; text-overflow:clip;
  }

  /* ---------- INVENTORY tab ---------- */
  .inv-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:14px; }
  .inv-card{
    padding:12px; display:flex; gap:12px; cursor:pointer;
    transition: transform .15s ease, box-shadow .15s ease;
  }
  .inv-card:hover{ transform:translateY(-3px); box-shadow:0 8px 18px rgba(0,0,0,0.22); }
  /* locked cards just get a gold ring + a small badge on the thumbnail — never a dark overlay,
     so the name/brand/badges stay exactly as readable as an unlocked card */
  .inv-card.locked{ box-shadow:0 0 0 2px var(--gold), 0 3px 10px rgba(0,0,0,0.12); }
  .inv-thumb{ display:flex; flex-direction:column; align-items:center; gap:6px; flex-shrink:0; position:relative; }
  .lock-badge{
    position:absolute; top:-8px; right:-8px; width:20px; height:20px; border-radius:50%;
    background:linear-gradient(180deg,#f3dd8a,var(--gold)); box-shadow:0 2px 5px rgba(0,0,0,0.35), 0 0 0 2px var(--paper);
    display:flex; align-items:center; justify-content:center; font-size:11px; z-index:2;
  }
  /* shared by every card thumbnail — Inventory, Binder (both use .inv-card), and Market Buy */
  .swatch{
    width:58px; height:80px; border-radius:5px; flex-shrink:0; position:relative; overflow:hidden;
    display:flex; align-items:center; justify-content:center;
    box-shadow:inset 0 0 0 1px rgba(255,255,255,0.25), 0 2px 5px rgba(0,0,0,0.25);
  }
  .swatch svg{ width:62%; height:auto; position:relative; z-index:1; filter:drop-shadow(0 2px 3px rgba(0,0,0,0.35)); }
  .swatch::after{
    content:""; position:absolute; top:-60%; left:-30%; width:40%; height:220%;
    background:linear-gradient(120deg, transparent, rgba(255,255,255,0.5), transparent);
    transform:rotate(20deg);
  }
  .thumb-value{
    font-family:'Space Mono',monospace; font-size:13px; font-weight:700; white-space:nowrap;
    padding:3px 8px; border-radius:6px; text-align:center;
    background:linear-gradient(180deg,#f3dd8a,var(--gold)); color:#2a2205;
    box-shadow:0 1px 3px rgba(212,175,55,0.4);
  }
  .inv-card .info{ flex:1; min-width:0; }
  /* single-line + ellipsis, same as .pull-card's name/brand — a long name or brand+team combo
     wrapping to a 2nd line would grow just that one card and knock its buttons out of line with
     every other card in the grid */
  .inv-card .p-name{ font-family:'Bebas Neue',sans-serif; font-size:16px; line-height:1.05; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .inv-card .p-brand{ font-family:'Space Mono',monospace; font-size:9.5px; color:#8a7960; margin-bottom:4px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  /* shown on any card tile/inspect view with a known costBasis — see costBasisHTML. Reuses the
     same .profit-pos/.profit-neg color pair the Analytics Profit Tracker uses, so "green means
     you're up" reads the same everywhere in the game rather than just in one screen. */
  .p-cost{ font-family:'Space Mono',monospace; font-size:9.5px; color:#8a7960; margin-bottom:4px; }
  .profit-pos{ color:var(--green); }
  .profit-neg{ color:var(--red); }
  .tags{ display:flex; gap:5px; flex-wrap:wrap; margin:4px 0; }
  /* reserves a pill's worth of height even when a card has no auto/mem/numbered/insert/etc.
     badges to show — otherwise cards without any land their action buttons a row higher than
     cards with badges sitting right next to them, an inconsistent-looking grid */
  .extra-tags{ min-height:20px; }
  .pill{ font-family:'Space Mono',monospace; font-size:9px; padding:2px 6px; border-radius:8px; background:#e7dcc4; color:#5a4c3a;}
  .pill.graded{ background:var(--gold); color:#2a2205; font-weight:700;}
  .pill.auto{ background:#111; color:#ffd23f; font-weight:700; border:1px solid #ffd23f; }
  .pill.mem{ background:#6b4f27; color:#f3ecdd; }
  .pill.diecut{ background:#3a3a3a; color:#f3ecdd; }
  .pill.rookie{ background:#1f5c3a; color:#eafff0; font-weight:700; }
  .pill.numbered{ background:#111; color:#ffd23f; font-weight:700; }
  .pill.hot{ background:linear-gradient(90deg,#c1443c,#e0793a); color:#fff; font-weight:700; }
  .pill.cold{ background:linear-gradient(90deg,#2c5f7a,#3ec6e0); color:#fff; font-weight:700; }
  .pill.value{
    font-size:14px; font-weight:700; padding:3px 9px;
    background:linear-gradient(180deg,#f3dd8a,var(--gold)); color:#2a2205;
    box-shadow:0 1px 3px rgba(212,175,55,0.4);
  }
  .pill.numbered.oneofone{ box-shadow:0 0 6px rgba(255,210,63,0.9); }
  .pill.insert{ color:#fff; font-weight:700; text-shadow:0 1px 2px rgba(0,0,0,0.5); }
  .inv-actions{ display:grid; grid-template-columns:1fr 1fr; gap:6px; margin-top:8px; }
  .inv-actions .mini-btn:only-child{ grid-column:1 / -1; }
  .mini-btn{
    font-family:'Space Mono',monospace; font-size:10px; padding:6px 4px; border-radius:4px;
    border:1px solid var(--counter); background:transparent; color:var(--counter); cursor:pointer;
    text-align:center; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
    transition: transform .1s ease, background .15s ease, box-shadow .15s ease;
  }
  /* deliberately no transform on hover — .mini-btn is the single most-hovered interactive
     element in the whole game (Accept/Decline/Keep/Sell/Grade/List/every mini action everywhere),
     which made it the worst offender for a real, reported bug: a translateY on the SAME element
     whose :hover pseudo-class triggers it shifts that element's own hit-tested box the instant the
     cursor is near the edge the shift moves — un-hovering it, which reverts the shift, which
     re-hovers it, forever, as long as the cursor sits on that now-oscillating boundary. Reads as a
     flicker that gets WORSE the closer to the edge you are, exactly because that's the zone where
     each shift flips hover on/off. background/color/box-shadow alone still read as a clear hover
     state without ever moving the box that decides whether it's hovered. */
  .mini-btn:hover:not(:disabled){ background:var(--counter); color:var(--paper); box-shadow:0 3px 8px rgba(0,0,0,0.25); }
  .mini-btn:disabled{ opacity:0.35; cursor:not-allowed; }
  .mini-btn.primary{ background:linear-gradient(180deg,#d9635a,var(--red)); border-color:var(--red); color:#fff; }
  .mini-btn.primary:hover:not(:disabled){ background:#a3352e; }
  /* action colors kept consistent everywhere a card can be sold/listed/graded: red = sell,
     blue = list (matches .bulk-btn.list), gold = grade (matches .bulk-btn.grade) */
  .mini-btn.sell{ background:linear-gradient(180deg,#d9635a,var(--red)); border-color:var(--red); color:#fff; }
  .mini-btn.sell:hover:not(:disabled){ background:#a3352e; }
  .mini-btn.list{ background:linear-gradient(180deg,#6a94c7,var(--blue)); border-color:var(--blue); color:#eaf2fb; }
  .mini-btn.list:hover:not(:disabled){ background:#2f557f; }
  .mini-btn.grade{ background:linear-gradient(180deg,#e6c458,var(--gold)); border-color:var(--gold); color:#2a2205; }
  .mini-btn.grade:hover:not(:disabled){ background:#b8923a; }

  /* ---------- AUCTIONS tab ---------- */
  /* Buy/Sell toggle on the left, the compact "Set All" master slider (Sell view only) pinned to
     the right at the same height — see masterSellControlHTML() in script.js */
  .auction-toggle-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:16px; flex-wrap:wrap; }
  .auction-toggle{ display:flex; gap:6px; margin-bottom:16px; }
  .auction-toggle-row .auction-toggle{ margin-bottom:0; }
  .toggle-btn{
    font-family:'Bebas Neue',sans-serif; font-size:15px; letter-spacing:0.5px;
    padding:7px 24px; border-radius:20px; cursor:pointer; border:1.5px solid var(--counter);
    background:transparent; color:var(--counter);
    transition: background .15s ease, color .15s ease, transform .1s ease;
  }
  .toggle-btn:hover{ background:rgba(212,175,55,0.14); border-color:var(--gold); }
  .toggle-btn.active{
    background:linear-gradient(180deg, var(--counter-light), var(--counter)); color:var(--paper);
    box-shadow:0 3px 8px rgba(0,0,0,0.25);
  }
  .auctions-badges{ position:absolute; top:20px; right:24px; display:flex; align-items:flex-start; gap:12px; }
  .auctions-badges .market-timer{ position:static; }
  .auctions-badges .grades-badge{ position:static; }
  .market-timer{ position:absolute; top:20px; right:24px; width:38px; height:38px; }
  .market-timer svg{ width:100%; height:100%; transform:rotate(-90deg); }
  .market-timer .timer-track{ fill:none; stroke:rgba(59,42,30,0.15); stroke-width:3; }
  .market-timer .timer-fill{
    fill:none; stroke-width:3; stroke-linecap:round;
    transition: stroke-dashoffset 1s linear, stroke 1s linear;
  }
  .price-tag{
    font-family:'Space Mono',monospace; font-size:9px; font-weight:700; text-align:center;
    padding:3px 7px; border-radius:5px; white-space:nowrap; letter-spacing:0.2px;
  }
  .price-tag.tier-steal{ background:linear-gradient(180deg,#5fb377,var(--green)); color:#eafff0; }
  .price-tag.tier-under{ background:linear-gradient(180deg,#a9d9b6,#5fb377); color:#123018; }
  .price-tag.tier-comp{ background:linear-gradient(180deg,#e0d5b8,var(--cardboard-dark)); color:#3b2a1e; }
  .price-tag.tier-over{ background:linear-gradient(180deg,#d9635a,var(--red)); color:#ffecea; }

  /* market cards: fixed top (image + header) and a footer pinned to the bottom of the card via
     margin-top:auto, so variable badge/tag content in the middle never pushes the Buy button or
     price to a different spot from one card to the next */
  .market-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(250px,1fr)); gap:14px; align-items:stretch; }
  .market-card{
    padding:12px; cursor:pointer;
    transition: transform .15s ease, box-shadow .15s ease;
    display:flex; flex-direction:column;
  }
  .market-card:hover{ transform:translateY(-3px); box-shadow:0 8px 18px rgba(0,0,0,0.22); }
  .market-card-top{ display:flex; gap:10px; align-items:flex-start; }
  .market-card-head{ flex:1; min-width:0; }
  .market-card-head .p-name{ font-family:'Bebas Neue',sans-serif; font-size:16px; line-height:1.1; }
  .market-card-head .p-brand{ font-family:'Space Mono',monospace; font-size:9.5px; color:#8a7960; margin:2px 0 6px; }
  .market-card-badges{ margin-top:8px; }
  .market-card-footer{
    margin-top:auto; padding-top:12px; display:flex; justify-content:space-between; align-items:flex-end; gap:10px;
  }
  .market-price-col{ display:flex; flex-direction:column; gap:1px; }
  .ask-price{ font-family:'Space Mono',monospace; font-size:18px; font-weight:700; color:var(--counter); }
  .comp-price{ font-family:'Space Mono',monospace; font-size:10px; color:#8a7960; }
  .market-buy-btn{
    font-family:'Space Mono',monospace; font-size:11px; font-weight:700; letter-spacing:0.3px;
    padding:8px 20px; border-radius:5px; cursor:pointer; border:1.5px solid var(--green);
    background:linear-gradient(180deg,#5fb377,var(--green)); color:#eafff0;
    transition: transform .1s ease, filter .15s ease; flex-shrink:0;
  }
  .market-buy-btn:hover:not(:disabled){ filter:brightness(1.08); }
  .market-buy-btn:disabled{ opacity:0.4; cursor:not-allowed; }
  .grading-queue{ margin-bottom:18px; }
  .listing-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(240px,1fr)); gap:14px; }
  .listing{
    padding:14px; position:relative; cursor:pointer;
    transition: transform .18s ease, box-shadow .18s ease;
  }
  .listing:hover{ transform:translateY(-3px); box-shadow:0 10px 20px rgba(0,0,0,0.25); }
  /* right-click (data-price-lockable) or the lock button both toggle this — same gold-ring
     treatment .inv-card.locked already uses for the (unrelated) Inventory sell-lock */
  .listing.price-locked{ box-shadow:0 0 0 2px var(--gold), 0 3px 10px rgba(0,0,0,0.12); }
  .listing .live-dot{
    display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--red);
    margin-right:5px; animation:pulse 1.1s infinite;
  }
  @keyframes pulse{ 0%,100%{opacity:1;} 50%{opacity:0.3;} }
  /* small swatch of the actual card next to its status/name/brand — see listingTopHTML() */
  .listing-top{ display:flex; gap:10px; align-items:flex-start; margin-bottom:8px; }
  .listing-head{ flex:1; min-width:0; }
  .listing .status{ font-family:'Space Mono',monospace; font-size:10px; color:#8a7960; letter-spacing:0.5px; text-transform:uppercase; margin-bottom:6px;}
  .listing .p-name{ font-family:'Bebas Neue',sans-serif; font-size:19px; line-height:1;}
  .listing .p-brand{ font-family:'Space Mono',monospace; font-size:9.5px; color:#8a7960;}
  .listing .bid{ font-family:'Space Mono',monospace; font-size:22px; font-weight:700; color:var(--green);}
  .listing .bid.ended{ color:var(--counter); }
  /* comp (bottom-left) and the ask (bottom-right, see sellAskPriceHTML) sized up from the shared
     defaults so both prices are easy to read at a glance without hunting for the slider's pill */
  .listing .comp-price{ font-size:12.5px; }
  .listing .ask-col{ align-items:flex-end; text-align:right; }
  .listing .ask-col .ask-price{ font-size:20px; }
  .listing .bid.ended.profit{ color:var(--green); }
  .listing .bid.ended.even{ color:var(--gold); }
  .listing .bid.ended.loss{ color:var(--red); }
  /* Ask-price slider (comp +/-200%, 10% steps) — see sellTierControlHTML()/setListingSellOffset()
     in script.js. Track is a smooth red->gold->green gradient (red=under comp, gold=comp,
     green=over comp), continuous rather than 3 fixed bands since the ask is now a real number,
     not a preset; the thumb recolors to match which side of comp it's on via the .low/.high
     class script.js keeps in sync with the slider's value (.average = default gold, no override
     needed). */
  .sell-tier-control{ margin-bottom:10px; }
  /* Buyer Offer row (offerRowHTML in script.js) — a small inline callout, not a modal, so it
     doesn't interrupt browsing the rest of the Sell grid the way the email offer flow's dedicated
     card layout does; distinct gold-on-dark treatment so it reads as "something needs a decision"
     at a glance among otherwise-plain listing tiles. */
  .offer-row{
    display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px;
    background:linear-gradient(160deg,#2a2013,#1a140c); border:1.5px solid var(--gold); border-radius:7px;
    padding:8px 10px; margin-bottom:10px;
  }
  .offer-row-text{ font-family:'Inter',sans-serif; font-size:11.5px; color:var(--paper); line-height:1.4; }
  .offer-badge{
    display:inline-block; font-family:'Space Mono',monospace; font-size:9.5px; font-weight:700;
    letter-spacing:0.5px; text-transform:uppercase; color:#1a140c; background:var(--gold);
    border-radius:4px; padding:2px 6px; margin-right:6px;
  }
  .offer-price{ font-family:'Space Mono',monospace; font-weight:700; color:var(--gold); }
  .offer-actions{ display:flex; gap:6px; flex-shrink:0; }
  .sell-tier-slider{
    -webkit-appearance:none; appearance:none; width:100%; height:6px; border-radius:3px;
    margin:2px 0 6px; outline:none; cursor:pointer;
    background:linear-gradient(90deg, var(--red), var(--gold) 50%, var(--green));
  }
  .sell-tier-slider::-webkit-slider-thumb{
    -webkit-appearance:none; appearance:none; width:16px; height:16px; border-radius:50%;
    background:var(--gold); border:2px solid #8a6a1a; box-shadow:0 1px 3px rgba(0,0,0,0.4); cursor:pointer;
  }
  .sell-tier-slider::-moz-range-thumb{
    width:16px; height:16px; border-radius:50%;
    background:var(--gold); border:2px solid #8a6a1a; box-shadow:0 1px 3px rgba(0,0,0,0.4); cursor:pointer;
  }
  .sell-tier-slider.low::-webkit-slider-thumb{ background:var(--red); border-color:#7a2a24; }
  .sell-tier-slider.low::-moz-range-thumb{ background:var(--red); border-color:#7a2a24; }
  .sell-tier-slider.high::-webkit-slider-thumb{ background:var(--green); border-color:#2a5a3a; }
  .sell-tier-slider.high::-moz-range-thumb{ background:var(--green); border-color:#2a5a3a; }
  .sell-tier-label{ display:flex; align-items:baseline; gap:6px; flex-wrap:wrap; }
  .sell-tier-pill{
    font-family:'Bebas Neue',sans-serif; font-size:12px; letter-spacing:0.5px; padding:1.5px 8px;
    border-radius:8px; color:#fff;
  }
  .sell-tier-pill.low{ background:var(--red); }
  .sell-tier-pill.average{ background:var(--cardboard-dark); color:#3b2a1e; }
  .sell-tier-pill.high{ background:var(--green); }
  .no-sale-tag{ color:var(--red); font-weight:700; }
  .sell-tier-row{ display:flex; align-items:center; justify-content:space-between; gap:8px; }
  /* price-lock — shields one card's ask from the master "Set All Prices" slider below; has no
     effect on the card's own slider, which stays fully usable locked or not */
  .price-lock-btn{
    flex-shrink:0; width:24px; height:24px; padding:0; border-radius:5px; cursor:pointer;
    font-size:12px; line-height:1; display:flex; align-items:center; justify-content:center;
    background:rgba(0,0,0,0.06); border:1px solid rgba(0,0,0,0.12);
    filter:grayscale(1) opacity(0.55);
    transition: filter .12s ease, background .12s ease, border-color .12s ease;
  }
  .price-lock-btn:hover{ filter:grayscale(1) opacity(0.85); }
  .price-lock-btn.locked{
    filter:none; background:rgba(212,175,55,0.18); border-color:rgba(212,175,55,0.55);
  }
  .price-lock-btn.locked:hover{ filter:brightness(1.1); }

  /* ---------- compact "Set All" slider — same ask-price control as each listing's own, just
     bulk-applied to every still-live, unlocked listing at once (setAllListingSellOffsets). Sits
     inline in the Buy/Sell toggle row, right-aligned at the same height as those buttons — see
     .auction-toggle-row below. Full detail (locked-card count, etc.) lives in its title tooltip
     rather than as visible text, to keep this small. */
  .master-sell-control{
    display:flex; align-items:center; gap:8px;
    background:rgba(0,0,0,0.05); border:1px solid rgba(0,0,0,0.14); border-radius:20px;
    padding:6px 12px;
  }
  .master-sell-title{
    font-family:'Bebas Neue',sans-serif; font-size:12px; letter-spacing:0.5px; color:var(--counter);
    white-space:nowrap;
  }
  .master-sell-control .sell-tier-slider{ width:110px; margin:0; }
  .master-sell-control .sell-tier-label{ display:flex; }

  /* mirrors .market-card-footer's layout — price info bottom-left (reuses .market-price-col /
     .comp-price, same classes the Buy-side market card uses), action button bottom-right, same
     "organized like the other cards" look across both sides of Auctions */
  .listing-footer{ display:flex; justify-content:space-between; align-items:flex-end; gap:10px; margin-top:10px; }
  .collect-btn{
    font-family:'Bebas Neue',sans-serif; font-size:14px; letter-spacing:0.5px;
    background:linear-gradient(180deg,#f3dd8a,var(--gold)); color:#2a2205; border:none; border-radius:5px;
    padding:8px 16px; cursor:pointer; flex-shrink:0;
    box-shadow:0 3px 8px rgba(212,175,55,0.4), inset 0 1px 0 rgba(255,255,255,0.5);
    transition: transform .12s ease, filter .15s ease;
  }
  .collect-btn:hover{ filter:brightness(1.1); }
  .collect-btn.no-sale{ background:linear-gradient(180deg,#cfc6b4,#a89c86); box-shadow:0 3px 8px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.4); }
  /* "blue = list" convention, same as .bulk-btn.list / .mini-btn.list elsewhere */
  .collect-btn.relist{ background:linear-gradient(180deg,#6a94c7,var(--blue)); color:#eaf2fb; box-shadow:0 3px 8px rgba(62,111,166,0.35), inset 0 1px 0 rgba(255,255,255,0.3); }
  .no-sale-actions{ display:flex; gap:6px; flex-shrink:0; }
  .no-sale-actions .collect-btn{ padding:8px 12px; }

  /* ---------- Inbox (email) tab ---------- */
  .email-list{ display:flex; flex-direction:column; gap:12px; }
  .email-card{ padding:14px; }
  .email-head{ display:flex; justify-content:space-between; align-items:flex-start; gap:10px; margin-bottom:6px; }
  .email-sender{ font-family:'Bebas Neue',sans-serif; font-size:16px; line-height:1.1; }
  .email-addr{ font-family:'Space Mono',monospace; font-size:9.5px; color:#8a7960; }
  .risk-badge{
    font-family:'Space Mono',monospace; font-size:9px; font-weight:700; letter-spacing:0.3px;
    padding:3px 8px; border-radius:10px; color:#fff; white-space:nowrap; flex-shrink:0;
  }
  .risk-badge.risk-low{ background:var(--green); }
  .risk-badge.risk-average{ background:var(--blue); }
  .risk-badge.risk-high{ background:var(--red); }
  .email-subject{ font-family:'Bebas Neue',sans-serif; font-size:15px; margin:4px 0 2px; color:var(--counter); }
  .email-body{ font-size:13px; line-height:1.4; color:#5a4c3a; margin-bottom:10px; }
  .email-footer{ display:flex; justify-content:space-between; align-items:center; margin-bottom:10px; }
  .email-count{ font-family:'Space Mono',monospace; font-size:11px; color:#8a7960; }
  .email-price{ font-family:'Space Mono',monospace; font-size:19px; font-weight:700; color:var(--counter); }
  .email-expiry{ font-family:'Space Mono',monospace; font-size:10px; color:#8a7960; margin-bottom:8px; }
  .email-expiry.expiry-soon{ color:var(--red); }
  .email-actions{ display:grid; grid-template-columns:1fr 1fr; gap:6px; }

  .empty-panel{
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    min-height:300px; gap:8px; color:#6b5c46; text-align:center;
  }
  .empty-panel .big{ font-family:'Bebas Neue',sans-serif; font-size:24px; color:var(--counter); }
  /* used where real content (e.g. Loans' "Available Lines" tier cards) follows right after the
     empty state — the full 300px centered treatment above just pushes that content off-screen
     for no reason, so this cuts it down to a compact inline banner instead */
  .empty-panel.compact{ min-height:0; padding:18px 0 22px; }

  /* ---------- card inspect modal ---------- */
  .card-modal{
    position:fixed; inset:0; z-index:400;
    display:flex; align-items:center; justify-content:center;
    opacity:0; pointer-events:none; transition:opacity .25s ease;
  }
  .card-modal.open{ opacity:1; pointer-events:auto; }
  /* extra-content case only (see .inspect-info.has-extra below, which handles the normal-viewport
     case by scrolling just the info panel) — this is a last-resort fallback for a viewport too
     short for even the fixed-size card + close button to fit at all. No padding-bottom, so a
     scroll here only ever reveals real content, never blank filler past the last element. */
  .card-modal.has-extra{ align-items:flex-start; overflow-y:auto; padding:46px 0 20px; }
  .card-modal-backdrop{
    position:absolute; inset:0; background:rgba(10,8,5,0.82); backdrop-filter:blur(3px);
  }
  .card-modal-inner{
    position:relative; z-index:2; display:flex; flex-direction:column; align-items:center; gap:14px;
  }
  /* extra-content case (currently only Trending's "expanded data" click, see openTrendingDetail /
     trendingStatsHTML) — the info panel carries a real chart + stat grid on top of the usual name/
     rarity block, way more than the 260px column was ever sized for. Cap the whole modal to the
     viewport and let it scroll internally, and on wide-enough screens go side-by-side (card left,
     data right) instead of stacking, so nothing runs off the bottom of the screen. */
  .card-modal-close{
    position:absolute; top:-42px; right:0; width:34px; height:34px; border-radius:50%;
    background:var(--paper); color:var(--ink); border:none; font-size:20px; line-height:1; cursor:pointer;
    box-shadow:0 4px 10px rgba(0,0,0,0.4); transition:background .15s ease, color .15s ease;
  }
  .card-modal-close:hover{ background:var(--red); color:#fff; }

  /* prev/next through the list the inspect modal was opened from (currently just a box's reveal
     spread, see inspectNav in script.js) — wraps the card itself so the arrows sit right at its
     edges no matter the viewport, styled like a chunky arcade/gacha "next" button (gold-rimmed
     coin, punchy press feedback, a slow idle nudge) rather than a flat generic chevron */
  .inspect-card-wrap{ position:relative; }
  .card-modal-nav{
    position:absolute; top:50%; transform:translateY(-50%) scale(1); z-index:3;
    width:46px; height:46px; border-radius:50%; cursor:pointer; padding:0;
    background:radial-gradient(circle at 32% 28%, var(--counter-light), var(--counter) 70%);
    border:2.5px solid var(--gold);
    display:none; align-items:center; justify-content:center;
    box-shadow:0 4px 12px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.25), 0 0 0 0 rgba(212,175,55,0.6);
    transition:background .15s ease, transform .15s ease, box-shadow .2s ease, border-color .15s ease;
  }
  .card-modal-nav svg{
    width:20px; height:20px; fill:none; stroke:var(--gold); stroke-width:3.2;
    stroke-linecap:round; stroke-linejoin:round; transition:stroke .15s ease;
  }
  .card-modal-nav.show{ display:flex; animation:navNudge 2.4s ease-in-out infinite; }
  .card-modal-nav.show.card-modal-next{ animation-name:navNudgeRight; }
  .card-modal-nav:hover{
    border-color:#fff2c2; transform:translateY(-50%) scale(1.12);
    box-shadow:0 6px 16px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.3), 0 0 14px 2px rgba(212,175,55,0.65);
    animation-play-state:paused;
  }
  .card-modal-nav:hover svg{ stroke:#fff2c2; }
  .card-modal-nav:active{ transform:translateY(-50%) scale(0.9); }
  .card-modal-prev{ left:-58px; }
  .card-modal-next{ right:-58px; }
  @keyframes navNudge{
    0%,100%{ transform:translateY(-50%) translateX(0); }
    50%{ transform:translateY(-50%) translateX(-4px); }
  }
  @keyframes navNudgeRight{
    0%,100%{ transform:translateY(-50%) translateX(0); }
    50%{ transform:translateY(-50%) translateX(4px); }
  }
  @media (max-width:700px){
    .card-modal-nav{ width:38px; height:38px; }
    .card-modal-nav svg{ width:16px; height:16px; }
    .card-modal-prev{ left:-46px; }
    .card-modal-next{ right:-46px; }
  }
  @media (max-width:600px){
    /* not enough room off either side of the card on a narrow phone screen — pull the arrows
       back onto the card's own edge instead of letting them run off into the viewport margin */
    .card-modal-prev{ left:-6px; }
    .card-modal-next{ right:-6px; }
  }

  /* ---------- CONFIRM MODAL (themed replacement for the native browser confirm()) ---------- */
  .confirm-modal{
    position:fixed; inset:0; z-index:500;
    display:flex; align-items:center; justify-content:center;
    opacity:0; pointer-events:none; transition:opacity .2s ease;
  }
  .confirm-modal.open{ opacity:1; pointer-events:auto; }
  .confirm-modal-backdrop{ position:absolute; inset:0; background:rgba(10,8,5,0.82); backdrop-filter:blur(3px); }
  .confirm-modal-inner{
    position:relative; z-index:2; width:min(90vw,380px);
    background:linear-gradient(160deg,#fbf6e8,var(--paper) 55%); border-radius:10px;
    border:2px solid var(--cardboard-dark); padding:22px 22px 18px;
    box-shadow:0 20px 50px rgba(0,0,0,0.5);
    animation: inspectPop .25s ease backwards;
  }
  .confirm-modal-title{
    font-family:'Bebas Neue',sans-serif; font-size:20px; letter-spacing:0.5px; color:var(--red);
    margin-bottom:8px;
  }
  .confirm-modal-msg{ font-size:14px; line-height:1.5; color:var(--ink); margin-bottom:18px; }
  .confirm-modal-actions{ display:grid; grid-template-columns:1fr 1fr; gap:8px; }

  /* ---------- "digging through the box" minigame ---------- */
  .minigame-modal{
    position:fixed; inset:0; z-index:550;
    display:flex; align-items:center; justify-content:center;
    opacity:0; pointer-events:none; transition:opacity .2s ease;
  }
  .minigame-modal.open{ opacity:1; pointer-events:auto; }
  .minigame-backdrop{ position:absolute; inset:0; background:rgba(10,8,5,0.88); backdrop-filter:blur(3px); }
  .minigame-inner{
    position:relative; z-index:2; width:min(90vw,420px);
    background:linear-gradient(160deg,#fbf6e8,var(--paper) 55%); border-radius:12px;
    border:2px solid var(--cardboard-dark); padding:24px;
    box-shadow:0 24px 60px rgba(0,0,0,0.55);
    animation: inspectPop .25s ease backwards;
    text-align:center;
  }
  .minigame-title{ font-family:'Bebas Neue',sans-serif; font-size:22px; letter-spacing:0.5px; color:var(--counter); }
  .minigame-round-label{
    font-family:'Space Mono',monospace; font-size:10.5px; color:#8a7960; letter-spacing:0.5px;
    margin:4px 0 18px;
  }
  .minigame-track{
    position:relative; height:26px; border-radius:6px; background:#2a2118;
    box-shadow:inset 0 2px 6px rgba(0,0,0,0.5); overflow:hidden; margin-bottom:18px;
  }
  .minigame-zone{
    position:absolute; top:0; bottom:0; background:linear-gradient(180deg,#6fce8a,var(--green));
    box-shadow:0 0 12px rgba(76,138,94,0.6) inset;
  }
  .minigame-marker{
    position:absolute; top:-3px; bottom:-3px; width:4px; background:#fff;
    box-shadow:0 0 8px rgba(255,255,255,0.9); transform:translateX(-50%); border-radius:2px;
  }
  .minigame-result{ font-family:'Bebas Neue',sans-serif; font-size:16px; min-height:22px; margin-top:12px; }
  .minigame-result.success{ color:var(--green); }
  .minigame-result.fail{ color:#8a7960; }

  .inspect-card{
    /* also carries the glass-gloss highlight so the inspect-back face (never a .pull-card, so it
       can't define this itself) still gets one via inheritance */
    --gloss: inset 0 1px 0 rgba(255,255,255,0.5),
             inset 40px -70px 70px -45px rgba(255,255,255,0.35),
             inset -30px 40px 60px -40px rgba(255,255,255,0.15);
    width:260px; height:364px; position:relative; cursor:pointer; perspective:1200px;
    transform-style:preserve-3d; transition:transform .6s cubic-bezier(.3,.6,.3,1);
    animation: inspectPop .3s ease backwards;
  }
  @keyframes inspectPop{ 0%{ transform:scale(0.75); opacity:0; } 100%{ transform:scale(1); opacity:1; } }
  .inspect-card.flipped{ transform:rotateY(180deg); }

  .inspect-face{
    position:absolute; inset:0; border-radius:14px; overflow:hidden;
    backface-visibility:hidden; -webkit-backface-visibility:hidden;
    box-shadow:0 18px 40px rgba(0,0,0,0.55), var(--gloss);
  }
  /* overrides .pull-card's own white/cream placeholder background (meant to sit behind a portrait
     before one loads) — left in place here, any pixel-level gap between the <img> and its box
     (unavoidable at the sub-pixel level any time the box is an integer pixel size, which it
     always is) would show through as a stark white sliver instead of just blending into the dark
     modal behind it */
  .inspect-face.pull-card{ width:100%; height:100%; border-width:4px; animation:none; background:#0a0a0a; }
  .inspect-card .pull-card:hover{ transform:none; }
  /* the inspect face itself carries nothing but the art now — no card-top/card-bottom/badges/
     mem-swatch/auto-sig — so the zoomed-in view shows the artwork with nothing drawn over it, any
     baked-in card text included. That metadata all lives in .inspect-info below instead. */
  .inspect-face.pull-card .portrait svg{ width:52%; }
  /* the front face's art: a real <img> (not a CSS background-image) so it composites reliably
     regardless of GPU/driver — see openCardInspectCard's comment. Sits exactly inside the
     4px border (inset:0 on an absolutely-positioned child measures from the padding edge), with
     the rarity/insert color wash layered on top via a second, later sibling. */
  .inspect-face-img{ position:absolute; inset:0; width:100%; height:100%; object-fit:contain; display:block; }
  .inspect-face-wash{ position:absolute; inset:0; pointer-events:none; }

  .inspect-back{
    transform:rotateY(180deg);
    border:4px solid var(--gold);
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px;
  }
  .inspect-back::before{
    content:""; position:absolute; inset:10px; border:1.5px solid rgba(255,255,255,0.35); border-radius:8px; z-index:1; pointer-events:none;
  }
  .inspect-back .back-monogram{
    width:58px; height:58px; border-radius:50%; border:2.5px solid; background:rgba(0,0,0,0.3);
    display:flex; align-items:center; justify-content:center;
    font-family:'Bebas Neue',sans-serif; font-size:24px; position:relative; z-index:2; margin-bottom:2px;
  }
  .inspect-back .back-mark{
    font-family:'Bebas Neue',sans-serif; font-size:26px; letter-spacing:2px;
    text-shadow:0 0 14px rgba(0,0,0,0.5); position:relative; z-index:2; text-align:center; padding:0 16px;
  }
  .inspect-back .back-sub{
    font-family:'Space Mono',monospace; font-size:10px; letter-spacing:3px; color:rgba(255,255,255,0.65);
    text-transform:uppercase; position:relative; z-index:2;
  }
  .inspect-back .back-foot{
    position:absolute; bottom:12px; left:0; right:0; text-align:center; z-index:2;
    font-family:'Space Mono',monospace; font-size:8.5px; letter-spacing:1px; color:rgba(255,255,255,0.4);
  }

  /* ---------- inspect info bar: rarity/set/badges/name/brand, moved off the zoomed-in card face
     entirely (see cardInspectInfoHTML) into its own strip underneath, so nothing the game draws
     ever sits on top of the artwork you zoomed in to actually look at */
  .inspect-info{
    width:260px; display:flex; flex-direction:column; gap:6px;
    background:rgba(22,18,13,0.82); border:1px solid rgba(255,255,255,0.1); border-radius:10px;
    padding:10px 14px; box-shadow:0 8px 20px rgba(0,0,0,0.4);
  }
  .inspect-info-row{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
  /* pinned to the right end of the badge row via margin-left:auto — the row usually has spare
     width once the rarity/set/HOT badges are laid out, so a compact addition (currently just
     Trending's trend badge, see cardInspectInfoHTML's topExtraHTML) fits there for free instead
     of costing its own row further down */
  .inspect-info-row-end{ margin-left:auto; }
  .inspect-info-row-end .trend-badge{ font-size:11px; }
  .inspect-info-row .set-monogram{ width:22px; height:22px; font-size:10px; }
  .inspect-info-row .card-badges{ gap:4px; }
  .inspect-info-row .cbadge{ font-size:9px; padding:3px 7px; }
  .inspect-info-row .rarity-tag{ font-size:11px; padding:4px 8px; }
  .inspect-info-name{
    font-family:'Bebas Neue',sans-serif; font-size:22px; line-height:1.05; color:var(--paper);
  }
  .inspect-info-brand{
    font-family:'Space Mono',monospace; font-size:11px; color:rgba(243,236,221,0.7);
  }

  /* widened variant for Trending's expanded-data view — the info panel itself is the ONLY thing
     that scrolls, and only as far as its own real content (max-height caps it to whatever room is
     actually left under the fixed-size card; overflow-y:auto then only activates, and only scrolls
     as far, as genuine overflow requires) so wheeling over the popup can never reveal blank space
     below the last stat tile the way scrolling the whole modal could. See openCardInspectCard. */
  .inspect-info.has-extra{
    width:min(92vw, 380px);
    max-height:max(160px, calc(100vh - 520px));
    overflow-y:auto;
  }
  .trending-detail-chart .trending-chart{ height:76px; }
  .trending-detail-chart .chart-bar{ max-width:20px; }
  .trending-detail-stats{
    display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:10px;
  }
  .trending-detail-stats .stat-tile{ min-width:0; flex:none; padding:8px 10px; }
  .trending-detail-stats .stat-tile .num{ font-size:16px; }
  .trending-detail-stats .trend-tile{ grid-column:1 / -1; }

  .inspect-hint{
    font-family:'Space Mono',monospace; font-size:11px; color:rgba(243,236,221,0.6); letter-spacing:0.5px;
  }

  /* toast */
  #toast{
    position:fixed; top:54px; left:50%; transform:translateX(-50%) translateY(-14px) scale(0.96);
    background:linear-gradient(160deg,#241c12,var(--ink)); color:var(--paper);
    border:1.5px solid var(--gold);
    font-family:'Inter',sans-serif; font-weight:700; font-size:15px; line-height:1.35;
    padding:13px 22px; border-radius:9px; text-align:center;
    opacity:0; pointer-events:none;
    transition: opacity .22s ease, transform .3s cubic-bezier(.2,.85,.3,1.35);
    box-shadow: 0 14px 34px rgba(0,0,0,0.5), 0 0 0 1px rgba(212,175,55,0.15), 0 0 26px rgba(212,175,55,0.3);
    z-index:600; max-width:min(90vw, 520px);
  }
  #toast.show{ opacity:1; transform:translateX(-50%) translateY(0) scale(1); }

  /* ---------- Buyer Offer slide-in alerts (renderOfferAlerts() in script.js) ---------- a
     surfaced offer is genuinely rare at a normal comp-priced ask (~5% chance per listing — see
     OFFER_CHANCE_CURVE), and easy to miss entirely if it only ever landed quietly in the Activity
     feed, so it gets its own top-right notification instead, independent of whichever screen is
     currently open. Stacks (newest on top) since more than one can be pending at once. */
  .offer-alerts{
    position:fixed; top:20px; right:20px; z-index:650;
    display:flex; flex-direction:column; gap:10px; width:min(90vw, 300px);
    pointer-events:none; /* re-enabled per-card below so the empty gaps between cards don't eat clicks */
  }
  .offer-alert-card{
    pointer-events:auto;
    display:flex; gap:10px; align-items:flex-start;
    background:linear-gradient(160deg,#241c12,var(--ink)); color:var(--paper);
    border:1.5px solid var(--gold); border-radius:10px; padding:12px;
    box-shadow: 0 14px 34px rgba(0,0,0,0.5), 0 0 0 1px rgba(212,175,55,0.15), 0 0 26px rgba(212,175,55,0.25);
    animation: offerAlertIn .35s cubic-bezier(.2,.85,.3,1.35);
  }
  .offer-alert-card.leaving{ animation: offerAlertOut .22s ease forwards; }
  @keyframes offerAlertIn{
    from{ opacity:0; transform:translateX(40px) scale(0.96); }
    to{ opacity:1; transform:translateX(0) scale(1); }
  }
  @keyframes offerAlertOut{
    from{ opacity:1; transform:translateX(0) scale(1); }
    to{ opacity:0; transform:translateX(40px) scale(0.96); }
  }
  .offer-alert-card .swatch{ width:44px; height:60px; flex-shrink:0; }
  .offer-alert-body{ flex:1; min-width:0; }
  .offer-alert-title{
    font-family:'Space Mono',monospace; font-size:9.5px; font-weight:700; letter-spacing:0.5px;
    text-transform:uppercase; color:var(--gold); margin-bottom:3px;
  }
  .offer-alert-name{ font-family:'Inter',sans-serif; font-weight:700; font-size:13px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .offer-alert-price{ font-family:'Space Mono',monospace; font-size:12px; color:rgba(243,236,221,0.75); }
  .offer-alert-price b{ color:var(--gold); font-size:15px; }
  .offer-alert-comp{ font-family:'Space Mono',monospace; font-size:10.5px; color:rgba(243,236,221,0.5); margin-bottom:8px; }
  .offer-alert-actions{ display:grid; grid-template-columns:1fr 1fr 1fr; gap:5px; }
  .offer-alert-actions .mini-btn{ padding:6px 4px; font-size:11px; }
  /* Review defaults to the app's own tan (cardboard) theme color rather than the red
     .mini-btn.primary used elsewhere — the alert popup is the only place a plain, un-classed
     mini-btn should read as tan (it's the "just look, don't decide yet" option) */
  .offer-alert-actions .mini-btn{ background:var(--cardboard); border-color:var(--cardboard-dark); color:#3b2a1e; }
  .offer-alert-actions .mini-btn:hover:not(:disabled){ background:var(--cardboard-dark); color:#2a1d12; }
  /* accept/decline colors aren't scoped to the popup — the inline offer row on the Sell tab
     listing tile (offerRowHTML) uses these same two classes and should match exactly */
  .mini-btn.accept{ background:linear-gradient(180deg,#5fb377,var(--green)); border-color:var(--green); color:#eafff0; }
  .mini-btn.accept:hover:not(:disabled){ background:#3a6c48; }
  .mini-btn.decline{ background:linear-gradient(180deg,#d9635a,var(--red)); border-color:var(--red); color:#fff; }
  .mini-btn.decline:hover:not(:disabled){ background:#a3352e; }
  .offer-alert-close{
    position:absolute; top:6px; right:8px; background:none; border:none; color:rgba(243,236,221,0.5);
    font-size:14px; line-height:1; cursor:pointer; padding:2px;
  }
  .offer-alert-close:hover{ color:var(--paper); }
  .offer-alert-card{ position:relative; }

  /* brief gold pulse on the actual listing tile when "Review" jumps the player to it in Auctions */
  .listing.offer-jump-highlight{ animation: offerJumpPulse 1.5s ease; }
  @keyframes offerJumpPulse{
    0%, 100%{ box-shadow:none; }
    15%, 45%{ box-shadow:0 0 0 3px var(--gold), 0 0 24px rgba(212,175,55,0.55); }
  }

  /* ---------- Collection Checklist (Binder tab, checklistHTML in script.js) ---------- compact
     tiles, denser than .inv-grid's full card layout — this is a checklist, not a card browser, so
     each entry only needs a small thumbnail + name, not the full info block. */
  .checklist-section{ margin-bottom:22px; }
  .checklist-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(84px,1fr)); gap:10px; }
  .checklist-tile{
    position:relative; display:flex; flex-direction:column; align-items:center; gap:6px;
    padding:8px 4px; border-radius:8px; text-align:center;
    background:rgba(59,42,30,0.06); border:1px solid var(--cardboard-dark);
  }
  .checklist-tile.owned{ cursor:pointer; transition: transform .15s ease, box-shadow .15s ease; }
  .checklist-tile.owned:hover{ transform:translateY(-3px); box-shadow:0 8px 16px rgba(0,0,0,0.22); }
  .checklist-tile.needed{ opacity:0.55; }
  .checklist-tile .swatch{ width:56px; height:76px; }
  .checklist-silhouette{ background:rgba(59,42,30,0.15); }
  .checklist-tile-name{
    font-family:'Inter',sans-serif; font-size:10.5px; font-weight:600; color:var(--counter);
    line-height:1.25; overflow:hidden; text-overflow:ellipsis; display:-webkit-box;
    -webkit-line-clamp:2; -webkit-box-orient:vertical;
  }
  .checklist-tile.needed .checklist-tile-name{ color:#8a7960; font-weight:400; }
  .checklist-hot-dot{ position:absolute; top:4px; right:4px; font-size:11px; }
  .checklist-cold-dot{ position:absolute; top:4px; left:4px; font-size:11px; }

  /* ---------- ANALYTICS tab ---------- */
  .analytics-section-title{
    font-family:'Bebas Neue',sans-serif; font-size:16px; letter-spacing:1px; color:var(--counter);
    margin:22px 0 10px; text-transform:uppercase;
  }
  .analytics-stats{ display:flex; gap:12px; flex-wrap:wrap; }
  .stat-tile{
    font-family:'Space Mono',monospace; text-align:center; min-width:120px; flex:1;
    background:rgba(59,42,30,0.08); border:1.5px solid var(--cardboard-dark); border-radius:9px;
    padding:10px 16px;
  }
  .stat-tile .label{
    display:block; font-size:10px; letter-spacing:1.5px; text-transform:uppercase;
    color:#8a7960; margin-bottom:4px;
  }
  .stat-tile .num{ display:block; font-size:20px; font-weight:700; color:var(--counter); }
  .stat-tile.trend-tile{ min-width:170px; }
  .stat-tile.trend-tile .num{ font-size:15px; }

  .trend-badge{ display:inline-flex; align-items:center; gap:4px; font-weight:700; }
  .trend-up{ color:var(--green); }
  .trend-down{ color:var(--red); }
  .trend-flat{ color:#8a7960; }
  .stat-tile.trend-up{ border-color:var(--green); }
  .stat-tile.trend-down{ border-color:var(--red); }

  .loan-repay-row{ display:flex; gap:10px; flex-wrap:wrap; margin:14px 0 22px; }

  .sales-chart{
    display:flex; align-items:flex-end; gap:4px; height:140px; padding:10px 8px 0;
    background:rgba(59,42,30,0.06); border:1px solid var(--cardboard-dark); border-radius:8px;
  }
  .chart-bar-col{
    flex:1; height:100%; display:flex; flex-direction:column; justify-content:flex-end;
    align-items:center; gap:4px; min-width:6px;
  }
  .chart-bar{
    width:100%; max-width:22px; border-radius:3px 3px 0 0;
    background:linear-gradient(180deg,#e6c458,var(--gold));
    box-shadow:0 0 6px rgba(212,175,55,0.35);
    transition: height .2s ease;
  }
  .chart-bar.today{ background:linear-gradient(180deg,#6fce8a,var(--green)); box-shadow:0 0 8px rgba(76,138,94,0.5); }
  .chart-bar-label{ font-family:'Space Mono',monospace; font-size:9px; color:#8a7960; }

  /* ---------- TRENDING tab ---------- */
  /* denser than the old single-row layout — 6-10 tiles comfortably per row so the whole point
     (scan by image, glance the price/trend, click if you want more) actually works at a glance */
  .trending-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(148px,1fr)); gap:12px; margin-bottom:22px; }
  .trending-card{
    background:rgba(59,42,30,0.06); border:1px solid var(--cardboard-dark); border-radius:9px;
    padding:10px;
  }
  .trending-card.rumor{ border-color:var(--gold); background:rgba(212,175,55,0.08); }
  .trending-card.has-card{ cursor:pointer; transition:transform .15s ease, box-shadow .15s ease; }
  .trending-card.has-card:hover{ transform:translateY(-3px); box-shadow:0 8px 16px rgba(0,0,0,0.22); }
  .trade-row.has-card{ cursor:pointer; }
  .trade-row.has-card:hover{ border-color:var(--gold); }
  .trending-card-art{ display:flex; justify-content:center; margin-bottom:8px; }
  .trending-card-art .swatch{ width:100%; height:100px; }
  .trending-silhouette{ background:rgba(59,42,30,0.15); }
  .trending-card-top{ display:flex; align-items:center; justify-content:space-between; gap:6px; margin-bottom:6px; flex-wrap:wrap; }
  .trending-card-name{
    font-family:'Bebas Neue',sans-serif; font-size:16px; letter-spacing:0.5px; color:var(--counter);
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .trending-card-sub{ font-family:'Space Mono',monospace; font-size:10px; color:#8a7960; margin-bottom:6px; }
  .trending-card-price{ font-family:'Space Mono',monospace; font-size:15px; font-weight:700; color:var(--gold); margin-bottom:4px; }
  .trending-rumor-note{ font-family:'Inter',sans-serif; font-size:11px; color:var(--counter); line-height:1.35; font-style:italic; }
  .rumor-pill{ background:linear-gradient(180deg,#f3dd8a,var(--gold)); color:#2a2205; font-weight:700; }
  .trending-chart{ height:44px; padding:5px 5px 0; gap:2px; }
  .trending-chart .chart-bar{ max-width:12px; box-shadow:none; }
  .trending-no-data{ font-family:'Space Mono',monospace; font-size:11px; color:#8a7960; padding:14px 0; text-align:center; }
  .trending-filter-bar{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:12px; }
  .trending-filter-label{
    display:flex; align-items:center; gap:6px; font-family:'Space Mono',monospace; font-size:11.5px;
    color:#6b5c46; letter-spacing:0.5px; text-transform:uppercase;
  }
  .trending-min-price{ width:80px; }
  .trending-filter-count{ font-family:'Space Mono',monospace; font-size:11px; color:#8a7960; margin-left:auto; }

  .analytics-columns{ display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:24px; margin-top:6px; }
  .demand-list{ display:flex; flex-direction:column; gap:9px; }
  .demand-row{
    display:grid; grid-template-columns:130px 1fr auto auto; align-items:center; gap:10px;
    font-size:12.5px;
  }
  .demand-label{ font-family:'Inter',sans-serif; font-weight:600; color:var(--counter); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .demand-bar-track{ background:rgba(0,0,0,0.12); border-radius:6px; height:9px; overflow:hidden; }
  .demand-bar-fill{ height:100%; background:linear-gradient(90deg, var(--accent2), var(--gold)); border-radius:6px; }
  .demand-figures{ font-family:'Space Mono',monospace; font-size:11.5px; color:var(--counter); white-space:nowrap; }
  .demand-count{ color:#8a7960; }
  .rarity-dot{ display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:6px; vertical-align:middle; }

  .trade-list{ display:flex; flex-direction:column; gap:6px; max-height:420px; overflow-y:auto; }
  .trade-row{
    display:grid; grid-template-columns:1fr 90px 90px 110px; align-items:center; gap:10px;
    font-family:'Space Mono',monospace; font-size:12px;
    background:rgba(59,42,30,0.06); border:1px solid var(--cardboard-dark); border-radius:7px;
    padding:8px 12px;
  }
  .trade-name{ font-family:'Inter',sans-serif; font-weight:600; color:var(--counter); display:flex; flex-direction:column; gap:2px; overflow:hidden; }
  .trade-sub{ font-family:'Space Mono',monospace; font-size:10.5px; font-weight:400; color:#8a7960; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .trade-figure{ text-align:right; white-space:nowrap; }
  .trade-cost, .trade-sale{ color:var(--counter); }
  .trade-profit{ font-weight:700; color:#8a7960; }
  .trade-row.profit-pos .trade-profit{ color:var(--green); }
  .trade-row.profit-neg .trade-profit{ color:var(--red); }
  @media (max-width:560px){
    .trade-row{ grid-template-columns:1fr auto; grid-template-areas:"name profit" "cost sale"; }
    .trade-name{ grid-area:name; }
    .trade-profit{ grid-area:profit; }
    .trade-cost{ grid-area:cost; text-align:left; }
    .trade-sale{ grid-area:sale; }
  }

  /* ---------- REVIEWS tab ---------- */
  .review-breakdown-list{ margin-bottom:6px; }
  .review-breakdown-row{
    display:grid; grid-template-columns:32px 1fr 28px; align-items:center; gap:10px;
    font-family:'Space Mono',monospace; font-size:12px;
  }
  .review-breakdown-label{ color:var(--counter); }
  .review-breakdown-count{ color:#8a7960; text-align:right; }

  .review-row{
    display:grid; grid-template-columns:58px 1fr; gap:12px;
    background:rgba(59,42,30,0.06); border:1px solid var(--cardboard-dark); border-radius:7px;
    padding:10px 12px;
  }
  .review-row:not(.has-card){ grid-template-columns:1fr; }
  .review-row.has-card{ cursor:pointer; }
  .review-row.has-card:hover{ border-color:var(--gold); }
  .review-row .swatch{ width:58px; height:80px; }
  .review-stars{ font-size:13px; letter-spacing:1px; white-space:nowrap; color:#8a7960; }
  .review-stars.great, .review-stars.good{ color:var(--green); }
  .review-stars.bad, .review-stars.awful{ color:var(--red); }
  .review-top{ display:flex; flex-wrap:wrap; align-items:baseline; gap:8px; margin-bottom:3px; }
  .review-buyer{ font-family:'Inter',sans-serif; font-weight:600; color:var(--counter); font-size:12.5px; }
  .review-sub{ font-family:'Space Mono',monospace; font-size:10.5px; color:#8a7960; }
  .review-comment{ font-family:'Inter',sans-serif; font-size:12.5px; color:var(--counter); line-height:1.4; }
  @media (max-width:560px){
    .review-row{ grid-template-columns:1fr; }
  }

  @media (max-width:560px){
    .marquee h1{ font-size:32px; }
    .register .cash{ font-size:20px; }
  }

  /* ============ CONTROLLER (Xbox / PS5) VIRTUAL CURSOR ============ */
  /* while a controller is actively driving navigation (stick OR D-pad), the real OS pointer is
     suppressed everywhere on the page — the virtual arrow (stick mode) or gold outline (D-pad mode)
     stands in for it instead. A genuine physical mouse move is the only thing that brings it back. */
  html.gamepad-nav, html.gamepad-nav *{ cursor:none !important; }

  /* anchored at the arrow's visual TIP, not the icon box's center — the SVG's point sits near the
     top-left of its 24x24 viewBox (see the path in the HTML), so centering the whole box on (cx,cy)
     put the hit-test coordinate ~12-17px away from what the player actually sees the arrow touching,
     making hover/click land on the wrong element right next to whatever it looked like it was over */
  #gamepadCursor{
    position:fixed; left:0; top:0; width:34px; height:34px; z-index:900;
    pointer-events:none; transform:translate(-16.7%,-8.3%); opacity:0;
    transition:opacity .15s ease;
  }
  #gamepadCursor.show{ opacity:1; }
  #gamepadCursor svg{ width:100%; height:100%; filter:drop-shadow(0 2px 4px rgba(0,0,0,0.6)); }
  #gamepadCursor.pressed svg{ transform:scale(0.85); }

  /* bright, saturated green rather than the game's muted --green (#4C8A5E) — the whole UI is
     gold/brown, so a gold outline blended in and was easy to lose track of; this reads clearly
     against every background in the game */
  .gamepad-hover{
    outline:3px solid #39e07a !important;
    outline-offset:2px;
    box-shadow:0 0 0 5px rgba(57,224,122,0.3) !important;
  }
  select.gamepad-hover.gamepad-select-active{
    outline:3px solid #3E6FA6 !important;
    box-shadow:0 0 0 5px rgba(62,111,166,0.3) !important;
  }

  /* the D-pad's stand-in for a native <select> popup (which it can't drive once opened) — shows
     every option at once right under the grabbed dropdown, current choice highlighted, so cycling
     through it is never a blind guess */
  .gamepad-select-list{
    position:fixed; z-index:950; max-height:min(280px, 50vh); overflow-y:auto;
    background:var(--paper,#F3ECDD); color:var(--ink,#16120D);
    border:2px solid var(--cardboard-dark,#6b4a2c); border-radius:7px;
    box-shadow:0 14px 32px rgba(0,0,0,0.5);
    font-family:'Inter',sans-serif; font-size:13px;
  }
  .gamepad-select-option{ padding:8px 12px; white-space:nowrap; }
  .gamepad-select-option.active{ background:#39e07a; color:#08341c; font-weight:700; }

  #controllerHint{
    position:fixed; left:50%; bottom:14px; transform:translateX(-50%);
    z-index:900; pointer-events:none; opacity:0; transition:opacity .25s ease;
    font-family:'Inter',sans-serif; font-weight:600; font-size:12px; letter-spacing:0.3px;
    background:rgba(10,8,5,0.82); color:var(--paper,#f2e9d8);
    border:1px solid rgba(212,175,55,0.4); border-radius:20px; padding:7px 16px;
    display:flex; gap:14px; white-space:nowrap;
  }
  #controllerHint.show{ opacity:1; }
  #controllerHint b{ color:var(--gold,#d4af37); }
