:root {
  /* Surfaces step *up* from the page rather than down into it, so a card
     reads as a card on its own — that elevation is what carries most
     component boundaries here, in place of an outline around everything. */
  --bg: #0b0b0e;
  --panel: #131318;
  --panel-2: #17171d;
  /* --line is now reserved for things you can act on: buttons, inputs,
     chips, and selected/hover/focus states. Static containers separate
     with --hairline, which should be barely perceptible on its own. */
  --hairline: rgba(255, 255, 255, 0.06);
  --line: rgba(255, 255, 255, 0.14);
  --line-strong: rgba(255, 255, 255, 0.4);
  --text: #f5f5f5;
  --text-dim: rgba(245, 245, 245, 0.55);
  --text-faint: rgba(245, 245, 245, 0.32);
  --glow: 0 0 40px rgba(255, 255, 255, 0.12);
  /* Dense terminal-style shell: one slim fixed topbar carrying wordmark,
     nav and stat pills, in place of the old centered hero header. */
  --accent: #e6e6eb;
  --accent-dim: rgba(230, 230, 235, 0.16);
  --accent-line: rgba(230, 230, 235, 0.5);
  --accent-hover: rgba(230, 230, 235, 0.5);
  /* Sticky bars that blur what scrolls under them. */
  --panel-blur: rgba(19, 19, 24, 0.94);
  /* Not themed: see .reveal-rarity-banner. Same value --line-strong has
     here, so the reveal is unchanged in dark. */
  --reveal-banner: rgba(255, 255, 255, 0.4);
  --topbar-h: 60px;
  /* Corner scale. Every radius in the app is one of these, chosen by what
     the thing is: xs for thumbnails in rows, sm for inputs, rows and wells
     inside cards, md for tiles and tall buttons inside pop-ups, lg for
     cards, xl for panels and pop-ups, 2xl for full-width bands, pill for
     single-line buttons, chips and tabs. It's the set Home, Drops and the
     pop-ups had already settled on, extended to everything else. */
  --r-xs: 8px;
  --r-sm: 12px;
  --r-md: 16px;
  --r-lg: 20px;
  --r-xl: 24px;
  --r-2xl: 28px;
  --r-pill: 999px;
  --surface-1: #131318;
  --surface-2: #1a1a20;

  /* --- Theme-aware neutrals -------------------------------------------
     These were hardcoded until the light theme existed, and the values
     here are exactly what they were, so the dark theme renders the same
     as it did before there was anything to switch. The light theme
     redefines them (and only them) below. */
  color-scheme: dark;
  --text-inverse: #000;                  /* type on a --text/--accent fill */
  --text-inverse-dim: rgba(0, 0, 0, 0.55);
  --inverse-tint: rgba(0, 0, 0, 0.12);   /* a chip sitting on such a fill */
  --well: #000;                          /* photo backdrop, and the reveal stage */
  --hover-bg: rgba(255, 255, 255, 0.05);
  --hover-bg-strong: rgba(255, 255, 255, 0.08);
  --hover-surface: #171717;              /* opaque hover on a card */
  --control-fill: rgba(255, 255, 255, 0.06); /* a button, instead of an outline */
  --control-fill-hover: rgba(255, 255, 255, 0.12);
  /* A label sitting on a product photo. */
  --chip-over-media: rgba(11, 11, 14, 0.74);
  --track: rgba(255, 255, 255, 0.08);    /* progress/meter groove */
  --shadow-card: rgba(0, 0, 0, 0.65);
  --shadow-modal: rgba(0, 0, 0, 0.85);
  --shadow-toast: rgba(0, 0, 0, 0.5);
  /* Money and status. Bright on black, too pale on white — the light
     theme darkens them rather than picking different hues. */
  --positive: #4ade80;
  /* The green button (Open, Deposit, Cash Out, claims): flat green, a thin
     black keyline, dark green type — the same in both themes. */
  --open-green: #7bfc7e;
  --open-green-hover: #6ef071;
  --open-ink: #112a14;
  --negative: #f87171;
  --warning: #fbbf24;
  --gold: #f2b84b;
}

/* --- Light theme ------------------------------------------------------
   Set by the rail's theme toggle, which writes data-theme on <html> and
   remembers it. Nothing outside this block knows which theme is running:
   the whole switch is these values.

   Surfaces still step *up* from the page, as they do in dark — the page
   is the grey and cards are white, rather than the page being white and
   cards being outlined. That keeps elevation carrying the component
   boundaries in both themes instead of introducing borders in one. */
:root[data-theme="light"] {
  color-scheme: light;
  /* Warm neutrals, not grey ones. Every value here sits on a single warm
     hue (~38deg) instead of the blue-grey the first pass used — that's the
     whole difference between "dark mode turned off" and the off-white a
     shop front is built on. The page is the beige and cards lift toward a
     warm white, so surfaces still step *up* the way they do in dark. */
  --bg: #f5f2ec;
  --panel: #fffdf9;
  --panel-2: #fffdf9;
  --hairline: rgba(38, 32, 22, 0.09);
  --line: rgba(38, 32, 22, 0.16);
  --line-strong: rgba(38, 32, 22, 0.42);
  --text: #1c1813;
  /* Both measured against the two surfaces they actually sit on (#f5f2ec
     page, #fffdf9 card): dim ~6.3:1, faint ~4.5:1. The old faint was 0.46,
     which is fine on near-black and 2.9:1 here — it was carrying most of
     the "can't read that" in this theme on its own. */
  --text-dim: rgba(28, 24, 19, 0.72);
  --text-faint: rgba(28, 24, 19, 0.62);
  --glow: 0 0 40px rgba(38, 32, 22, 0.1);
  --accent: #1c1813;
  --accent-dim: rgba(38, 32, 22, 0.08);
  --accent-line: rgba(38, 32, 22, 0.28);
  --accent-hover: rgba(38, 32, 22, 0.12);
  --panel-blur: rgba(255, 253, 249, 0.92);
  --surface-1: #fffdf9;
  --surface-2: #f1ede4;

  --text-inverse: #fffdf9;
  --text-inverse-dim: rgba(255, 253, 249, 0.66);
  --inverse-tint: rgba(255, 253, 249, 0.18);
  /* Product shots are mostly cut out on white, so a warm near-white well
     keeps them from sitting in a black box on a light page. */
  --well: #f3efe7;
  --hover-bg: rgba(38, 32, 22, 0.05);
  --hover-bg-strong: rgba(38, 32, 22, 0.08);
  --hover-surface: #f3efe7;
  --control-fill: rgba(38, 32, 22, 0.05);
  --control-fill-hover: rgba(38, 32, 22, 0.1);
  --chip-over-media: rgba(255, 253, 249, 0.92);
  --track: rgba(38, 32, 22, 0.1);
  /* Far lighter than the dark theme's: a 0.85-alpha black shadow that
     reads as depth on near-black reads as soot on white. Warm-tinted, so
     a card's shadow doesn't turn the beige under it grey. */
  --shadow-card: rgba(58, 46, 30, 0.14);
  --shadow-modal: rgba(58, 46, 30, 0.2);
  --shadow-toast: rgba(58, 46, 30, 0.16);
  --positive: #15803d;
  --negative: #dc2626;
  --warning: #b45309;
  --gold: #96701d;
}

/* Colours that can't come from a token, because they're written straight
   onto the element by JS from RARITY_META — five hues picked to glow on
   black, three of which are close to invisible on white. Darkening the
   rendered element keeps each rarity's hue (and so the learned colour
   coding) instead of duplicating the palette in JS and having two places
   to keep in step. The border on these chips is the same colour, and a
   filter takes it along. */
:root[data-theme="light"] .prize-modal-rarity,
:root[data-theme="light"] #pullDetailRarity {
  filter: brightness(0.62) saturate(1.45);
}

/* Held for the two frames it takes to swap themes. Two reasons, and the
   second is the load-bearing one:
     - a theme change should land at once, not as fifty elements easing
       between palettes at their own durations, which reads as a smear
     - elements that transition a property fed by a custom property (the
       rail's tabs and the sound button, which ease background/border/
       colour) don't get re-resolved when the attribute driving those
       properties is removed from :root — they keep the old theme's
       colours until something else forces a recalc. Taking the
       transition away for the swap is what makes them update. */
:root.theme-switching,
:root.theme-switching *,
:root.theme-switching *::before,
:root.theme-switching *::after {
  transition: none !important;
}

/* The streak heatmap ramps up in opacity toward the accent, which means
   toward white in dark and toward black in light — the one place the ramp
   has to be restated rather than tokenised. */
:root[data-theme="light"] .streak-tile.level-1 { background: rgba(38, 32, 22, 0.1); border-color: rgba(38, 32, 22, 0.16); }
:root[data-theme="light"] .streak-tile.level-2 { background: rgba(38, 32, 22, 0.3); }
:root[data-theme="light"] .streak-tile.level-3 { background: rgba(38, 32, 22, 0.55); border-color: rgba(38, 32, 22, 0.62); color: var(--text-inverse); }

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, "Helvetica Neue", Arial, sans-serif;
  display: flex;
  position: relative;
}

/* --- App shell: one fixed header, nothing down the side -----------------
   Dense, data-forward layout in place of the old centered hero header. One
   bar holds all of it: wordmark, nav, wallet state, and the two utility
   switches. Below it the content column has the full width to centre in. */

.shell {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 100vh;
}

.shell-body {
  display: flex;
  flex: 1;
  min-height: 0;
  /* The topbar is fixed, so it no longer holds this down itself. */
  padding-top: var(--topbar-h);
}

/* --- Nav ------------------------------------------------------------------
   A row of words in the header. It was a 76px icon rail down the left,
   which charged every screen the same 76px forever so that four
   destinations could be pictures instead of their own names — and pushed
   the centred content off-centre by half of it. Mobile keeps the element as
   a fixed bottom tab bar (see the mobile query); everything horizontal here
   is scoped to desktop so the two don't have to argue. */

.rail { display: flex; align-items: center; }
.rail-nav { display: flex; align-items: center; }

.nav-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 58px;
  padding: 8px 4px;
  background: transparent;
  border: none;
  border-radius: var(--r-pill);
  /* dim, not faint: with the icon gone the word is the whole target, and
     faint sits at 2.75:1 on the dark bar. */
  color: var(--text-dim);
  font-size: 0.58rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.nav-tab .icon { width: 18px; height: 18px; }
/* More: three dots and a word in the bar; the menu drops under it (on a
   phone it rises above the bottom bar). Items are rows: icon, name, V2. */
.nav-more { position: relative; display: flex; }
.nav-more .nav-more-btn .nav-more-dots { display: inline-block; width: 16px; height: 16px; margin-right: 5px; }
.nav-more.open .nav-more-btn, .nav-more:has(.nav-tab.active) .nav-more-btn { color: var(--text); }
.nav-more-menu {
  position: absolute;
  top: calc(100% + 10px);
  left: 0;
  z-index: 80;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 210px;
  padding: 6px;
  border-radius: 16px;
  background: var(--panel);
  box-shadow: 0 18px 50px var(--shadow-toast), 0 0 0 1px var(--hairline);
}
.nav-more-menu[hidden] { display: none; }
.nav-more-menu .nav-tab {
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 0.72rem;
  letter-spacing: 0.6px;
}
.nav-more-menu .nav-tab .icon { display: inline-block; width: 18px; height: 18px; }
.nav-more-menu .nav-tab:hover { background: var(--control-fill); }
.nav-more-menu .nav-tab.active { background: var(--control-fill); color: var(--text); }
.nav-more-menu .nav-v2 { position: static; margin-left: auto; height: 16px; padding: 0 5px; font-size: 0.56rem; }

/* V2: a green tag on tabs for features still to come (Odds, Flip, Rewards), so
   they read as previews rather than part of the site as it stands. */
.nav-tab { position: relative; }
.nav-v2 {
  display: inline-grid;
  place-items: center;
  height: 14px;
  margin-left: 5px;
  padding: 0 4px;
  border-radius: 4px;
  background: oklch(0.8751 0.2471 147.45);
  color: oklch(0.256 0.062 150.2);
  font-size: 0.5rem;
  font-weight: 800;
  letter-spacing: 0.2px;
  line-height: 1;
  vertical-align: 1px;
}
@media (max-width: 640px) {
  .nav-more { flex: 1; }
  .nav-more-btn { width: 100%; }
  .nav-more .nav-more-btn .nav-more-dots { width: 18px; height: 18px; margin: 0; }
  .nav-more-menu { position: fixed; top: auto; left: auto; right: 10px; bottom: calc(var(--bottom-nav-h) + 10px); min-width: 230px; }
  .nav-more-menu .nav-tab { flex: none; padding: 12px; font-size: 0.78rem; }
  /* Bottom bar: on the icon's top-right corner, clear of the label. */
  .nav-v2 { position: absolute; top: 0; left: calc(50% + 5px); height: 12px; margin: 0; padding: 0 3px; font-size: 0.45rem; }
}
/* No pill: the tab you're on is simply the dark word among grey ones.
   Weight stays put so the words don't shift sideways on click. */
.nav-tab:hover { color: var(--text); background: transparent; }
.nav-tab.active {
  background: transparent;
  color: var(--text);
}

@media (min-width: 641px) {
  .rail { flex: 0 0 auto; margin-left: 10px; }
  .rail-nav { gap: 2px; }
  .nav-tab {
    flex-direction: row;
    width: auto;
    gap: 0;
    padding: 8px 13px;
    font-size: 0.68rem;
    letter-spacing: 0.8px;
  }
  /* Written out, the glyph is a second name for the same thing. */
  .nav-tab .icon { display: none; }
}

/* Theme and sound: a vertical stack pinned to the bottom-right corner, on
   the card surface (white in light mode) with a hairline ring and a soft
   shadow, so they lift off whatever page is behind them without shouting.
   The recent-pulls dock owns the bottom-left. */
.rail-bottom {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.rail-bottom .mute-btn {
  background: var(--surface-1);
  color: var(--text-faint);
  box-shadow: 0 0 0 1px var(--hairline), 0 4px 14px rgba(0, 0, 0, 0.1);
}
:root[data-theme="light"] .rail-bottom .mute-btn { background: #fff; }
.rail-bottom .mute-btn:hover {
  background: var(--surface-1);
  color: var(--text-dim);
  transform: scale(1.08);
}
:root[data-theme="light"] .rail-bottom .mute-btn:hover { background: #fff; }

.mute-btn {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--control-fill);
  color: var(--text-dim);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
  border: none;
}
.mute-btn:hover { color: var(--text); background: var(--control-fill-hover); }
.mute-btn .icon-volume-muted { display: none; }
.mute-btn.muted .icon-volume { display: none; }
.mute-btn.muted .icon-volume-muted { display: block; }

/* Theme toggle — same 36px circle as the sound button; it's the same kind
   of control. The icon shows the theme you'd switch *to*, so in dark you
   see a sun. */
.theme-btn .icon-theme-moon { display: none; }
:root[data-theme="light"] .theme-btn .icon-theme-sun { display: none; }
:root[data-theme="light"] .theme-btn .icon-theme-moon { display: block; }

.shell-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 25;
  flex: 0 0 auto;
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 0 24px;
}
/* The blur is painted by a layer inside the bar rather than by the bar
   itself, because backdrop-filter makes an element the containing block for
   any fixed-position descendant — and the nav now lives in here, where
   mobile still needs it to pin itself to the bottom of the viewport as a tab
   bar. On the pseudo-element it blurs exactly the same pixels and traps
   nothing. */
.topbar::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--panel-blur);
  backdrop-filter: blur(10px);
}

.topbar-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}
/* Clickable (goes to Drops) but deliberately inert-looking — no hover, no
   press state. It reads as the wordmark, not a button.

   Set as type rather than the plate logo: that artwork was a distressed
   wordmark inside a heavy rounded-rect frame, which at topbar size was a
   lot of ink for one word, and being white artwork it needed inverting on
   a light page. Anton is the nearest web face to the lettering inside it —
   single-weight heavy condensed grotesque, flat terminals. */
.brand-logo {
  display: block;
  padding: 0;
  background: none;
  border: none;
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-size: 1.6rem;
  line-height: 1;
  letter-spacing: 1.5px;
  color: var(--text);
  cursor: pointer;
}

.topbar-stats {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
/* A bar of fixed height can't afford a second row, so the wallet never
   wraps — and it never shrinks either, because a squeezed flex line would
   spill its pills leftward over the nav rather than narrow them. */
@media (min-width: 641px) {
  .topbar { gap: 12px; }
  .topbar-stats { flex: 0 0 auto; flex-wrap: nowrap; gap: 6px; }
}

/* Between the phone breakpoint and a comfortable desktop, four groups want
   one 60px line and there isn't room for all of them at full size. Nav and
   balances are what the bar is for; the streak pill, the add-funds plus and
   the username are each one click away inside Account. */
@media (min-width: 641px) and (max-width: 1010px) {
  .topbar { padding: 0 14px; gap: 8px; }
  .rail { margin-left: 0; }
  .nav-tab { padding: 8px 6px; letter-spacing: 0.3px; }
  .nav-v2 { margin-left: 3px; }
  #streakStat { display: none; }
}
/* Just above the phone breakpoint, where the four words themselves are
   most of the bar. */
@media (min-width: 641px) and (max-width: 740px) {
  .topbar { padding: 0 10px; gap: 6px; }
  .nav-tab { padding: 8px 6px; }
}

.icon { vertical-align: -2px; flex: 0 0 auto; }

.wallet-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--surface-2);
  border: none;
  border-radius: 999px;
  font-size: 0.7rem;
  letter-spacing: 0.3px;
  color: var(--text-dim);
}
.wallet-item b {
  color: var(--text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  transition: color 0.2s ease, transform 0.2s ease;
  display: inline-block;
}
.wallet-item b.pulse {
  color: var(--gold);
  transform: scale(1.2);
}

.stat-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px 8px 8px;
  background: var(--surface-2);
  border-radius: 999px;
  font: inherit;
  font-size: 0.68rem;
  color: var(--text-dim);
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
  border: none;
}
.stat-pill:hover { background: var(--control-fill-hover); color: var(--text); }
.stat-pill b { color: var(--text); font-variant-numeric: tabular-nums; }

.ring {
  --pct: 0;
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  border-radius: 50%;
  position: relative;
  background: conic-gradient(var(--accent) calc(var(--pct) * 3.6deg), var(--line) 0deg);
}
.ring::after {
  content: "";
  position: absolute;
  inset: 2.5px;
  border-radius: 50%;
  background: var(--surface-2);
}


/* Just the profile picture: no name beside it, so a long username can't
   push the wallet around. */
.avatar-btn {
  display: flex;
  align-items: center;
  padding: 0;
  background: none;
  border-radius: 50%;
  cursor: pointer;
  border: none;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.avatar-btn:hover { transform: scale(1.06); box-shadow: 0 0 0 2px var(--line-strong); }
.avatar-btn .avatar-circle { width: 32px; height: 32px; }
/* The avatar is Account's door on desktop: it shows when you're there. */
.avatar-btn.active { box-shadow: 0 0 0 2px var(--text); }
@media (min-width: 641px) {
  .nav-tab-account { display: none; }
}

.avatar-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  overflow: hidden;
  color: #fff;
  font-size: 0.62rem;
  font-weight: 800;
  flex: 0 0 auto;
}
.avatar-circle img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.avatar-lg { width: 56px; height: 56px; font-size: 1.1rem; }

/* 1180 was drawn around a 76px rail eating the left edge; with the rail
   gone the same number left a wide empty margin down both sides instead of
   giving the grids the room. */
.shell-main main {
  flex: 1;
  width: 100%;
  max-width: 1360px;
  margin: 0 auto;
  padding: 32px 32px 48px;
}

.eyebrow { display: none; }

.screen { display: none; }
.screen.active { display: block; }

/* The crate-opening screen (reel/boxes/reveal) is short relative to the
   viewport and was just sitting at the top of `main` with a big dead gap
   below — center the whole block vertically in the available space
   instead. The other screens (Drops picker, Marketplace, Account) stay
   plain block flow; they're meant to scroll, not center. */
/* A single open sets no tier label at all (see startRound) — collapse the
   heading rather than leaving its margin behind as a gap. */
#gameTierLabel:empty { display: none; }

#screen-game.active {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - var(--topbar-h) - 68px);
}
/* The status bar (Playing with Cash, Fairness) stays up under the header;
   the crates sit in the space below it, a little above its middle: the
   spacer above them takes less of the free space than the one below. */
.game-spacer { flex: 0.5 1 0; }
#screen-game.active::after { content: ""; flex: 1.6 1 0; }

.screen-title {
  text-align: left;
  font-weight: 700;
  font-size: 1.3rem;
  letter-spacing: 0.3px;
  text-transform: none;
  color: var(--text);
  margin: 0 0 24px;
}

/* --- Category screen --- */

.game-top-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.game-top-bar .back-btn { margin-bottom: 0; }

.game-top-bar-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.paying-with-badge {
  font-size: 0.72rem;
  color: var(--text-dim);
  letter-spacing: 0.5px;
  padding: 4px 12px;
  border-radius: 999px;
  border: none;
}

.fairness-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.68rem;
  letter-spacing: 0.3px;
  color: var(--text-dim);
  padding: 4px 12px;
  background: var(--surface-2);
  border-radius: 999px;
  cursor: pointer;
  border: none;
}
.fairness-badge:hover { border-color: var(--line-strong); color: var(--text); }
.fairness-badge.verified { color: var(--positive); border-color: rgba(74, 222, 128, 0.4); }

.fairness-modal-card { max-width: 380px; text-align: left; }
.fairness-modal-card .payment-modal-title { text-align: center; }
.fairness-modal-card .payment-modal-hint { text-align: center; }

.fairness-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 0;
  border-bottom: 1px solid var(--hairline);
}
.fairness-row-label {
  font-size: 0.6rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}
.fairness-row-value {
  font-family: monospace;
  font-size: 0.72rem;
  color: var(--text);
  word-break: break-all;
}

.fairness-status {
  margin: 16px 0;
  padding: 8px 16px;
  border-radius: var(--r-sm);
  font-size: 0.75rem;
  font-weight: 600;
  text-align: center;
}
.fairness-status.pending { background: var(--surface-2); color: var(--text-faint); }
.fairness-status.verified { background: rgba(74, 222, 128, 0.12); color: var(--positive); }

.fairness-note {
  font-size: 0.66rem;
  line-height: 1.5;
  color: var(--text-faint);
  margin-bottom: 16px;
}

/* --- Credit-earned toast --- */

.credit-toast {
  position: fixed;
  /* Below the header, not over it: at 24px it sat on the nav. */
  top: calc(var(--topbar-h) + 14px);
  left: 50%;
  z-index: 200;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 24px;
  background: var(--text);
  color: var(--text-inverse);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  border-radius: 999px;
  box-shadow: 0 12px 30px var(--shadow-toast);
  opacity: 0;
  transform: translate(-50%, -16px);
  transition: opacity 0.3s ease, transform 0.3s ease;
  pointer-events: none;
}
.credit-toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}
.credit-toast-icon { font-size: 1rem; }

/* Three across: the six crates make two even rows, and a line's three
   price points (Sneakers $125 / $250 / $1,000) make one. */
.category-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  align-items: stretch;
}
@media (max-width: 900px) {
  .category-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.category-wrap {
  display: flex;
  flex-direction: column;
  gap: 8px;
  height: 100%;
}

.category-card {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  background: var(--panel);
  border: none;
  border-radius: var(--r-lg);
  padding: 24px 32px 32px;
  text-align: center;
  transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}

.category-card:hover {
  transform: translateY(-4px);
  border-color: var(--line-strong);
  box-shadow: var(--glow);
}

.category-payment-badges {
  position: absolute;
  top: 14px;
  right: 14px;
  display: flex;
  gap: 8px;
}

.category-icon-badge {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--surface-2);
  border: none;
  color: var(--text-dim);
}
.category-icon-badge svg { width: 15px; height: 15px; }

.category-box-canvas {
  display: block;
  width: 165px;
  height: 165px;
  margin: 8px auto 2px;
}

.category-tier-line {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  margin-bottom: 8px;
}

.category-tier-name {
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: 0.3px;
}
/* One hue per product category, mid-toned so the same value carries on
   near-black and on off-white — the crates are categories now, not metals,
   so there is no silver to go invisible on a light page. Matches the
   fallback finishes in boxViewer's TIER_SKINS. */
.category-tier-name.tier-name-sneakers { color: #d4794e; }
.category-tier-name.tier-name-streetwear { color: #5b8dd9; }
.category-tier-name.tier-name-collectibles { color: #c9942f; }
.category-tier-name.tier-name-cards { color: #d64545; }

.category-tier-price {
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--text);
}

.category-powered-by {
  display: block;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--text-faint);
  margin-bottom: 8px;
}
/* Keeps cards without a "Powered by" line the same height as ones with it,
   so the tier row stays aligned. */
.category-powered-by-spacer {
  display: block;
  height: 21px;
}

.category-qty {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 16px;
}

.qty-btn {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  border: none;
}
.qty-btn:hover { background: var(--text); color: var(--text-inverse); }

.qty-value {
  min-width: 22px;
  font-size: 0.95rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.qty-max-btn {
  padding: 4px 12px;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  background: var(--control-fill);
  border-radius: 999px;
  color: var(--text-dim);
  cursor: pointer;
  border: none;
}
.qty-max-btn:hover { color: var(--text); background: var(--control-fill-hover); }
.qty-max-btn.active { background: var(--text); color: var(--text-inverse); }

.category-open-btn {
  margin-top: 16px;
  padding: 12px 0;
  background: var(--text);
  color: var(--text-inverse);
  border: none;
  border-radius: var(--r-pill);
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.category-open-btn:hover { transform: translateY(-2px); }

/* Pity progress, shown under the tier badge/price */
.pity-bar {
  margin-top: 16px;
  text-align: left;
}
.pity-bar-label {
  display: block;
  font-size: 0.6rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 4px;
}
.pity-bar-track {
  height: 4px;
  border-radius: var(--r-pill);
  background: var(--track);
  overflow: hidden;
}
.pity-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent));
  border-radius: var(--r-pill);
  transition: width 0.3s ease;
}

.prize-dropdown {
  background: var(--panel);
  border: none;
  border-radius: var(--r-lg);
  overflow: hidden;
}

.prize-dropdown-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  font-size: 0.68rem;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-dim);
}

.odds-toggle-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-faint);
  cursor: pointer;
  border: none;
}
.odds-toggle-btn svg { width: 13px; height: 13px; }
.odds-toggle-btn:hover { color: var(--text); background: var(--control-fill-hover); }
.odds-toggle-btn.active { color: var(--text); background: var(--surface-2); }

.odds-panel {
  padding: 16px 16px;
  border-bottom: 1px solid var(--hairline);
  background: var(--surface-1);
}

.odds-live-header {
  font-size: 0.68rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 8px;
}

.odds-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.odds-bucket {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 12px;
  background: var(--surface-2);
  border: none;
  border-radius: var(--r-sm);
}
.odds-bucket-rarity {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.odds-bucket-range {
  font-size: 0.7rem;
  color: var(--text-faint);
}
.odds-bucket-pct {
  font-size: 1rem;
  font-weight: 800;
  color: var(--text);
}

.prize-list {
  max-height: 280px;
  overflow-y: auto;
  border-top: 1px solid var(--hairline);
}

/* Mobile-only disclosure for the list above (see the mobile media query
   near the end of this file) — inert on desktop, where .prize-list is
   always shown and this checkbox/label pair stays hidden. */
.prize-list-toggle-input { display: none; }
.prize-list-toggle-label { display: none; }

/* --- Drops: one tier as its own page ----------------------------------
   Clicking a tier card promotes it: the other three wraps drop out, the
   grid collapses to that one card, and the Pulls panel — which the list
   view no longer shows at all — comes up with its odds and full prize
   catalog already open. The card is the same DOM node throughout, so its
   spinning 3D box carries straight over instead of re-initializing.
   Mobile sizing overrides live in the max-width:640px block. */

.category-wrap:not(.drop-detail-active) .prize-dropdown { display: none; }
.category-wrap:not(.drop-detail-active) .category-card { cursor: pointer; }

.drop-detail-back {
  display: none;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  padding: 8px 16px;
  background: var(--surface-2);
  border: none;
  border-radius: 999px;
  color: var(--text-dim);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  cursor: pointer;
}
.drop-detail-back:hover { color: var(--text); border-color: var(--line-strong); }
body.drop-detail-open .drop-detail-back { display: inline-flex; }
body.drop-detail-open #screen-category .screen-title { display: none; }
/* The pulls carousel stays, narrowed to this tier — see openTierDetail. */
body.drop-detail-open #recentPulls { max-width: 1000px; margin-left: auto; margin-right: auto; }

/* minmax(0,...) rather than a bare 1fr: the full prize list's long
   product names give the column a wide min-content, which a bare 1fr
   honors and the page then scrolls sideways. The max-width keeps the
   single card from stretching the full content width on a desktop
   viewport; it's wider than a phone, so mobile ignores it. */
body.drop-detail-open .category-list {
  grid-template-columns: minmax(0, 1fr);
  max-width: 560px;
  margin: 0 auto;
}
body.drop-detail-open .category-wrap:not(.drop-detail-active) { display: none; }

/* Nothing left to choose between here, so drop the list view's lift. */
.drop-detail-active .category-card:hover { transform: none; box-shadow: none; }

/* Both disclosures open, and their triggers gone with them — .hidden is
   an !important rule, so unhiding the odds panel needs one too. */
.drop-detail-active .odds-panel.hidden { display: block !important; }
.drop-detail-active .odds-toggle-btn,
.drop-detail-active .prize-list-toggle-label { display: none; }

/* The "Pulls" header shipped above the odds, so the panel opened
   "Pulls / Live Odds / <buckets> / <the actual pulls>" — the heading sat
   over the wrong section. Reorder it to head the prize list it names,
   leaving Live Odds to open the panel on its own. */
.drop-detail-active .prize-dropdown { display: flex; flex-direction: column; }
.drop-detail-active .odds-panel { order: 1; }
.drop-detail-active .prize-dropdown-header { order: 2; }
.drop-detail-active .prize-list { order: 3; display: block; max-height: 300px; }

/* Desktop turns the page on its side: the tier card takes a fixed left
   column and Pulls fills the rest, rather than the phone's single stack
   leaving most of the width empty and the prize list below the fold. The
   row is sized to the viewport so the catalog scrolls inside it instead
   of the page scrolling. */
@media (min-width: 641px) {
  body.drop-detail-open .category-list { max-width: 1000px; }
  .drop-detail-active {
    flex-direction: row;
    align-items: stretch;
    gap: 24px;
    /* Short enough that the tier's pulls carousel below shows above the
       fold, without starving the prize list it's borrowing from. */
    height: calc(100vh - var(--topbar-h) - 240px);
    min-height: 420px;
  }
  .drop-detail-active .category-card {
    flex: 0 0 320px;
    justify-content: center;
  }
  .drop-detail-active .category-box-canvas { width: 200px; height: 200px; }
  /* Same tidy-up the mobile grid gets: the odd one out (Legendary, with
     five rarities in two columns) spans rather than leaving a gap. */
  .drop-detail-active .odds-grid > .odds-bucket:last-child:nth-child(2n + 1) {
    grid-column: 1 / -1;
  }
  .drop-detail-active .prize-dropdown { flex: 1 1 auto; min-width: 0; }
  .drop-detail-active .prize-list {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
    overflow-y: auto;
  }
}

/* --- A crate page's "What's inside": tier tabs over prize tiles -------
   One tier at a time, so a crate with forty prizes is five short looks
   rather than one long scroll. Tiles are the same white tile, tier-colour
   edge as the stacks on the cards, at a size you can see the piece. */
.prize-browser { border-top: none; padding: 0 16px 16px; }
.prize-tabs {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  gap: 6px;
  padding: 2px 0 12px;
  background: var(--panel);
  overflow-x: auto;
  scrollbar-width: none;
}
.prize-tabs::-webkit-scrollbar { display: none; }
.prize-tab {
  flex: 0 0 auto;
  padding: 7px 14px;
  border: 1.5px solid transparent;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text-dim);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.prize-tab:hover { color: var(--text); }
.prize-tab.active {
  border-color: var(--rarity-color);
  background: color-mix(in srgb, var(--rarity-color) 14%, var(--panel));
  color: color-mix(in srgb, var(--rarity-color) 70%, var(--text));
}
/* A tier with nothing left still opens (you can see what went), but reads
   as spent. */
.prize-tab.is-out:not(.active) { opacity: 0.5; }
.prize-tiles {
  display: grid;
  align-content: start;
  grid-template-columns: repeat(auto-fill, minmax(116px, 1fr));
  gap: 10px;
}
.prize-tile { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.prize-tile-img {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  padding: 10px;
  border: 1.5px solid var(--rarity-color);
  border-radius: var(--r-sm);
  background: #fff;
}
.prize-tile-img img { width: 100%; height: 100%; object-fit: contain; }
.prize-tile-name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.72rem;
  line-height: 1.3;
  color: var(--text);
}
.prize-tile-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; margin-top: auto; }
.prize-tile-foot b { font-size: 0.82rem; color: var(--text); }
.prize-tile-foot span { font-size: 0.66rem; font-weight: 600; color: var(--text-faint); white-space: nowrap; }
.prize-tile.is-gone { opacity: 0.4; }
.prize-tile.is-gone img { filter: grayscale(1); }
@media (max-width: 640px) {
  .prize-browser { padding: 0 12px 12px; }
  .prize-tiles { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; }
  .prize-tabs { gap: 5px; }
  .prize-tab { flex: 1 1 auto; padding: 6px 8px; font-size: 0.66rem; }
  .prize-tile-img { padding: 6px; }
}
/* The odds boxes open their tier's tab. */
.drop-detail-active .odds-bucket[data-prize-tab] { cursor: pointer; transition: background 0.15s ease; }
.drop-detail-active .odds-bucket[data-prize-tab]:hover { background: var(--control-fill-hover); }
/* The card's own What's inside row would repeat the panel beside it. */
.drop-detail-active .category-card .whats-left { display: none; }
/* The crate's page holds still and the prizes scroll: on desktop the two
   columns fit the screen (the crate card doesn't move), and only the
   tiles under the tabs scroll, inside their own panel. The page itself
   scrolls on past them to the crate's recent pulls. */
.drop-detail-active .prize-list.prize-browser {
  display: flex;
  flex-direction: column;
  min-height: 0;
  max-height: none;
  overflow: hidden;
  padding-bottom: 0;
}
.drop-detail-active .prize-tabs { position: static; flex: 0 0 auto; }
.drop-detail-active .prize-tiles {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-bottom: 16px;
  scrollbar-width: thin;
}
@media (max-width: 640px) {
  .drop-detail-active .prize-tiles { max-height: 70vh; padding-bottom: 12px; }
}
@media (min-width: 641px) {
  .drop-detail-active { height: calc(100vh - var(--topbar-h, 60px) - 120px); min-height: 560px; }
  /* Odds on one line, so the prizes get the height. */
  .drop-detail-active .odds-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .drop-detail-active .odds-grid > .odds-bucket:last-child:nth-child(2n + 1) { grid-column: auto; }
}
/* How many are left in the tier, beside its name: the lower tiers hold
   far more. */
.prize-tab-n { margin-left: 5px; font-weight: 600; opacity: 0.65; }

/* --- Recent pulls: a live ticker of pulls across the platform (yours +
   a simulated cast, same pattern as the marketplace/leaderboard) --- */

.recent-pulls {
  /* Full width of the crate-card row, not a narrower
     centered strip — no max-width of its own. */
  margin: 48px 0 0;
}

.recent-pulls h3 {
  text-align: center;
  font-size: 0.68rem;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 12px;
  font-weight: 500;
}

/* New pulls land at the left (newest-first) and pop in in place — see
   renderRecentPulls — while everything already in the row FLIP-animates
   sliding right to make room, edges fading via mask. No continuous
   auto-scroll: it only moves when a pull genuinely arrives. */
.recent-pulls-viewport {
  overflow-x: auto;
  -webkit-mask-image: linear-gradient(to right, transparent, black 32px, black calc(100% - 32px), transparent);
  mask-image: linear-gradient(to right, transparent, black 32px, black calc(100% - 32px), transparent);
}

.recent-pulls-list {
  display: flex;
  gap: 16px;
  padding: 4px 2px 12px;
}

.recent-pull-item {
  flex: 0 0 auto;
  width: 168px;
  padding: 16px 16px 16px;
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-md);
  text-align: center;
  cursor: pointer;
  transition: transform 0.15s ease, border-color 0.15s ease;
}
.recent-pull-item:hover { transform: translateY(-3px); border-color: var(--line-strong); }
.recent-pull-item.static { cursor: default; }
.recent-pull-item.static:hover { transform: none; border-color: var(--line); }

.recent-pull-item img {
  width: 104px;
  height: 104px;
  object-fit: contain;
  background: var(--well);
  border-radius: var(--r-sm);
  margin: 0 auto 12px;
  display: block;
}

.recent-pull-price {
  display: block;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 8px;
}

.recent-pull-item .tier-badge {
  margin-bottom: 8px;
  font-size: 0.62rem;
  padding: 4px 8px;
}

.recent-pull-user {
  display: block;
  font-size: 0.66rem;
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.recent-pull-user.you { color: var(--accent); }

/* --- Game screen --- */

.back-btn {
  background: none;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 0.85rem;
  letter-spacing: 0.5px;
  margin-bottom: 8px;
  padding: 4px 0;
}
.back-btn:hover { color: var(--text); }

/* Slot-machine reel */

.reel {
  position: relative;
  width: 100%;
  max-width: 600px;
  height: 190px;
  /* Top margin matches .box-row's top padding below, so the boxes sit at
     the same height whether the reel is spinning or has handed off to the
     picked/revealed boxes — no vertical jump on the cut between them. */
  margin: 80px auto 32px;
  overflow: hidden;
  background: var(--panel);
  border: none;
  border-radius: var(--r-lg);
  box-shadow: var(--glow);
}

.reel::before,
.reel::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 60px;
  z-index: 2;
  pointer-events: none;
}
.reel::before { left: 0; background: linear-gradient(90deg, var(--well) 0%, transparent 100%); }
.reel::after { right: 0; background: linear-gradient(270deg, var(--well) 0%, transparent 100%); }

.reel-track {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  display: flex;
  will-change: transform, filter;
}

.reel-track.spinning {
  animation: reelBlur 2.4s ease forwards;
}

@keyframes reelBlur {
  0% { filter: blur(7px); }
  65% { filter: blur(3px); }
  100% { filter: blur(0); }
}

.reel-cell {
  height: 100%;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

.reel-cell img {
  width: 84%;
  height: 84%;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
}

.reel-slot-lines {
  position: absolute;
  inset: 0;
  display: flex;
  z-index: 1;
  pointer-events: none;
}
.reel-slot-lines span {
  flex: 1 0 auto;
  border-right: 1px solid var(--hairline);
}
.reel-slot-lines span:last-child { border-right: none; }

.box-row {
  display: flex;
  justify-content: center;
  column-gap: 24px;
  row-gap: 96px;
  padding: 80px 0 8px;
  flex-wrap: wrap;
}

.box-slot {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 190px;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}

.box-row:not(.hidden) .box-slot {
  opacity: 1;
  transform: translateY(0);
}
.box-row:not(.hidden) .box-slot:nth-child(2) { transition-delay: 0.08s; }
.box-row:not(.hidden) .box-slot:nth-child(3) { transition-delay: 0.16s; }

.box-canvas {
  width: 190px;
  height: 190px;
  display: block;
  cursor: pointer;
}

.box-slot.locked .box-canvas { cursor: default; }

.box-caption {
  margin-top: 8px;
  font-size: 0.75rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-faint);
  transition: color 0.2s ease;
}

.box-slot.you .box-caption { color: var(--text); font-weight: 600; }

.price-card {
  --rarity-color: var(--line-strong);
  position: absolute;
  top: -6px;
  left: 50%;
  z-index: 3;
  width: 168px;
  text-align: center;
  /* No background, no border: the card is a rendered slab on a transparent
     ground, so the chrome would be a second box around it. drop-shadow
     follows the slab's own silhouette; a box-shadow would ring the PNG. */
  filter: drop-shadow(0 10px 16px rgba(0, 0, 0, 0.32));
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, 10px) scale(0.82);
  transition: opacity 0.45s var(--spring),
              transform 0.45s var(--spring);
}

.box-slot.open .price-card {
  opacity: 1;
  transform: translate(-50%, -66px) scale(1);
}

/* A genuine near-miss: one of the two crates you didn't pick outranked the
   one you got. This never affects odds — it's just an honest emotional
   beat on a real outcome. */
.box-slot.near-miss .price-card {
  animation: nearMissPulse 1.4s ease-out 1;
}

/* Keyframes beat a plain declaration, so while this ran it painted the
   rectangular box-shadow straight back over the transparent PNG — which is
   exactly what the frame around the glow was. drop-shadow stacks and
   respects alpha, so the rarity light blooms off the case's edge. */
@keyframes nearMissPulse {
  0%, 100% { filter: drop-shadow(0 10px 16px rgba(0, 0, 0, 0.32)); }
  30% {
    filter: drop-shadow(0 10px 16px rgba(0, 0, 0, 0.32))
            drop-shadow(0 0 14px var(--rarity-color));
  }
}

.helper-text {
  text-align: center;
  color: var(--text-dim);
  font-size: 0.85rem;
  letter-spacing: 0.5px;
  margin: 8px 0 24px;
}

.primary-btn {
  display: block;
  margin: 0 auto;
  padding: 12px 48px;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-inverse);
  background: var(--text);
  border: none;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.primary-btn:hover { transform: translateY(-2px); }

/* Full width of the page, the same 1360px column and gutters as <main>
   above it. It sits in a flex column, where auto side margins alone
   shrink it to its content, hence the explicit width. */
.app-footer {
  display: none;
  box-sizing: border-box;
  width: 100%;
  max-width: 1360px;
  margin: 64px auto 0;
  padding: 0 32px;
}
/* Home only. Drops, Marketplace and Account are working screens you
   scroll through, and Rewards shares Account's screen — a footer under any
   of them is dead weight at the end of a long scroll; Home is the site's
   front page, which is where it belongs. min-width so this never fights
   the mobile media query's own footer rule on specificity; the :has()
   compound selector here outranks a plain .app-footer{display:none}. */
@media (min-width: 641px) {
  main:has(#screen-home.active) + .app-footer {
    display: block;
  }
}

.app-footer-main {
  display: flex;
  flex-wrap: wrap;
  gap: 48px;
  justify-content: space-between;
  padding: 48px 0;
  border-top: 1px solid var(--hairline);
}

.app-footer-brand { flex: 1 1 280px; max-width: 440px; }

.app-footer-logo {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text);
  font-size: 1.05rem;
  font-weight: 900;
  letter-spacing: 0.5px;
  margin-bottom: 16px;
}

.app-footer-tagline {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--text-faint);
}
.app-footer-tagline a { color: var(--text-dim); }
.app-footer-tagline a:hover { color: var(--text); }

.app-footer-columns {
  display: flex;
  flex-wrap: wrap;
  gap: 48px;
}

.app-footer-col {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 130px;
}
.app-footer-col h4 {
  margin: 0 0 4px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text);
}

.app-footer-link {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 0;
  font-size: 0.76rem;
  color: var(--text-faint);
  cursor: pointer;
  text-align: left;
}
.app-footer-link:hover { color: var(--text); }

.app-footer-social {
  display: flex;
  gap: 8px;
}
.app-footer-prefs { display: flex; gap: 8px; }
/* Same look as the social buttons beside them. */
.app-footer-prefs .mute-btn {
  width: 32px;
  height: 32px;
  background: var(--surface-2);
  color: var(--text-dim);
}
.app-footer-prefs .mute-btn:hover { color: var(--text); background: var(--control-fill-hover); }
@media (min-width: 641px) {
  .app-footer-prefs-col { display: none; }
}
.app-footer-social-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-dim);
  cursor: pointer;
  text-decoration: none;
  border: none;
}
.app-footer-social-btn:hover { color: var(--text); background: var(--control-fill-hover); }

/* --- Won-prize modal --- */

.prize-modal {
  --rarity-color: var(--line-strong);
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.82);
  backdrop-filter: blur(6px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
  padding: 24px;
}

.prize-modal.visible {
  opacity: 1;
  pointer-events: auto;
}

.prize-modal-card {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 300px;
  background: var(--panel-2);
  /* No outline, like everything else: rarity reads from the glow and the
     rarity pill, not from a hairline around the card. */
  border: none;
  border-radius: var(--r-xl);
  padding: 32px 32px 32px;
  text-align: center;
  box-shadow: 0 24px 70px var(--shadow-modal), 0 0 40px -6px var(--rarity-color);
  opacity: 1;
  transform: scale(0.85) translateY(8px);
  transition: transform 0.4s var(--spring), opacity 0.3s ease;
}

.prize-modal.visible .prize-modal-card {
  transform: scale(1) translateY(0);
}

/* While the fullscreen reveal FX is playing, the prize itself (image, name,
   price) stays completely hidden — it only appears once the FX is done, so
   there's no "shown, then hidden, then shown again" flash. */
.prize-modal.revealing .prize-modal-card {
  opacity: 0;
  transform: scale(0.6);
  pointer-events: none;
}
/* Same for the reveal's own body (photo, price, name, buttons): the FX
   plays on an empty stage, and the prize pops in once it's done. */
.slab-reveal .slab-reveal-body { transition: transform 0.4s var(--spring), opacity 0.25s ease; }
.prize-modal.slab-reveal.revealing .slab-reveal-body {
  opacity: 0;
  transform: scale(0.6);
  pointer-events: none;
}

.prize-modal-rarity {
  display: inline-block;
  font-size: 0.62rem;
  letter-spacing: 2px;
  text-transform: uppercase;
  padding: 4px 12px;
  /* A tint of the rarity's colour rather than an outline in it. */
  border: none;
  background: color-mix(in srgb, currentColor 15%, transparent);
  border-radius: 999px;
  margin-bottom: 16px;
}

.streak-badge {
  display: block;
  margin-top: 16px;
  font-size: 0.7rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--gold);
}

/* --- Fullscreen reveal FX (vortex / particles / shockwave) --------------
   Lives directly under #prizeModal (not inside the card) so it immerses
   the whole viewport instead of being boxed into the card. */

.reveal-fx {
  position: fixed;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}

.prize-modal.revealing .reveal-fx {
  opacity: 1;
}

.reveal-rarity-banner {
  position: fixed;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
}

.prize-modal.revealing .reveal-rarity-banner {
  opacity: 1;
}

.reveal-rarity-banner span {
  font-size: clamp(2.2rem, 9vw, 6rem);
  font-weight: 800;
  letter-spacing: 8px;
  text-transform: uppercase;
  /* The banner plays over the modal's own black scrim, which is black in
     both themes, so its type stays light in both.

     It asked for --rarity-color, but nothing ever sets that on the modal
     itself — app.js sets it on the card and on the .reveal-fx layer, and
     the banner is a sibling of both. So it always fell through to
     .prize-modal's default of --line-strong, which is a translucent white
     in dark (what this has always looked like) and turned near-black the
     moment a light theme existed. Naming the colour directly keeps dark
     exactly as it was and stops it riding on that fallback. */
  color: var(--reveal-banner);
  text-shadow: 0 0 40px var(--reveal-banner), 0 0 90px var(--reveal-banner);
  animation: rarityBannerPop var(--fx-duration, 1.2s) cubic-bezier(0.25, 0.6, 0.3, 1) forwards;
}

@keyframes rarityBannerPop {
  0% { transform: scale(0.5); opacity: 0; }
  18% { transform: scale(1.1); opacity: 1; }
  30% { transform: scale(1); }
  82% { opacity: 1; }
  100% { transform: scale(1.2); opacity: 0; }
}

.reveal-vortex {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 62vmin;
  height: 62vmin;
  margin: -31vmin 0 0 -31vmin;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    transparent 0%,
    var(--rarity-color) 12%,
    transparent 28%,
    transparent 50%,
    var(--rarity-color) 62%,
    transparent 78%,
    transparent 100%
  );
  filter: blur(3vmin);
  opacity: 0.7;
  animation: vortexSpin var(--fx-duration, 1.2s) cubic-bezier(0.25, 0.6, 0.3, 1) forwards;
}

@keyframes vortexSpin {
  0% { transform: rotate(0deg) scale(1.4); opacity: 0.85; }
  70% { opacity: 0.55; }
  100% { transform: rotate(760deg) scale(0.1); opacity: 0; }
}

.reveal-rays {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 130vmax;
  height: 130vmax;
  margin: -65vmax 0 0 -65vmax;
  background: repeating-conic-gradient(
    from 0deg,
    var(--rarity-color) 0deg 4deg,
    transparent 4deg 18deg
  );
  opacity: 0.16;
  animation: raysSpin var(--fx-duration, 1.2s) linear forwards;
  mix-blend-mode: screen;
}

@keyframes raysSpin {
  0% { transform: rotate(0deg); opacity: 0.24; }
  100% { transform: rotate(-200deg); opacity: 0; }
}

.reveal-flash {
  position: fixed;
  inset: 0;
  background: var(--rarity-color);
  opacity: 0;
  animation: flashPulse var(--fx-duration, 1.2s) ease-out forwards;
}

@keyframes flashPulse {
  0%, 78% { opacity: 0; }
  84% { opacity: var(--climax, 0.2); }
  100% { opacity: 0; }
}

.reveal-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 10px;
  margin: -4px 0 0 -4px;
  border: 2px solid var(--rarity-color);
  border-radius: 50%;
  opacity: 0;
  animation: ringExpand var(--fx-duration, 1.2s) ease-out forwards;
  animation-delay: calc(var(--fx-duration, 1.2s) * 0.7);
}

@keyframes ringExpand {
  0% { width: 10px; height: 10px; margin: -4px 0 0 -4px; opacity: var(--climax, 0.2); }
  100% { width: 160vmax; height: 160vmax; margin: -80vmax 0 0 -80vmax; opacity: 0; }
}

.reveal-particle {
  position: absolute;
  top: 50%;
  left: 50%;
  border-radius: 50%;
  background: var(--rarity-color);
  box-shadow: 0 0 8px var(--rarity-color);
  opacity: 0;
  animation: particleIn var(--fx-duration, 1.2s) ease-in forwards;
  animation-delay: var(--delay, 0s);
}

@keyframes particleIn {
  0% {
    transform: translate(-50%, -50%) rotate(var(--angle)) translateX(var(--dist)) scale(0.5);
    opacity: 0;
  }
  18% { opacity: 1; }
  100% {
    transform: translate(-50%, -50%) rotate(calc(var(--angle) + 200deg)) translateX(0) scale(1.3);
    opacity: 0;
  }
}

.prize-modal-image {
  display: block;
  width: 150px;
  height: 150px;
  object-fit: contain;
  margin: 0 auto 16px;
  background: var(--well);
  border-radius: var(--r-md);
}

.prize-modal-name {
  margin: 0 0 8px;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.3px;
}

.prize-modal-price {
  margin: 0 0 24px;
  font-size: 1.6rem;
  font-weight: 800;
}

.prize-modal-actions {
  display: flex;
  gap: 8px;
}

.modal-btn {
  flex: 1;
  padding: 12px 0;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.modal-btn:hover { transform: translateY(-2px); }

.modal-btn-solid {
  background: var(--text);
  color: var(--text-inverse);
  border: none;
}

.modal-btn-outline {
  background: transparent;
  color: var(--text);
  border: none;
  background: var(--control-fill);
}

/* The one accent color in an otherwise monochrome app (neon-leaning
   green, gradient + glow so it doesn't feel flat/overpowering) — reused
   on every "this is the button you actually want to tap" moment:
   Deposit, Cash Out on a reveal, and Try Again after a round.
   Specificity is bumped (button.deposit-btn, not just .deposit-btn) so
   it reliably wins over each button's own base class (.exit-btn,
   .primary-btn) regardless of which is later in this file. */
button.deposit-btn {
  background: var(--open-green);
  color: var(--open-ink);
  border: 1.5px solid #000;
  border-radius: 9px;
  box-shadow: none;
}
button.deposit-btn:hover { background: var(--open-green-hover); box-shadow: none; }
button.deposit-btn:disabled { background: var(--control-fill); color: var(--text-faint); border-color: var(--line); }
.deposit-btn .exit-btn-sub { color: rgba(17, 42, 20, 0.62); }

/* --- Payment method picker --- */

.payment-modal-card {
  max-width: 320px;
}

.payment-modal-title {
  margin: 0 0 24px;
  font-size: 1rem;
  font-weight: 600;
}
.payment-modal-title span { color: var(--text-dim); }

.payment-modal-options {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
}

.payment-option {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 16px 8px;
  background: var(--panel-2);
  border-radius: var(--r-md);
  color: var(--text);
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease, background 0.15s ease;
  border: none;
}
.payment-option:hover {
  border-color: var(--line-strong);
  transform: translateY(-2px);
  background: var(--hover-surface);
}
.payment-option-icon { font-size: 1.6rem; }
.payment-option-label {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.5px;
}
.payment-option-balance {
  font-size: 0.68rem;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.payment-modal-hint {
  margin: 0 0 24px;
  font-size: 0.68rem;
  line-height: 1.5;
  color: var(--text-faint);
}

/* --- Marketplace --- */

.market-shell {
  display: flex;
  align-items: flex-start;
  gap: 24px;
}

.market-filters {
  flex: 0 0 220px;
  position: sticky;
  top: calc(var(--topbar-h) + 20px);
  display: flex;
  flex-direction: column;
  gap: 16px;
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-lg);
  padding: 16px;
}

/* Mobile-only "Filters" sheet trigger + backdrop (see the mobile media
   query near the end of this file) — inert on desktop, where
   .market-filters is always the visible sticky sidebar and these stay
   hidden/no-op. */
.market-filters-toggle-input { display: none; }
.market-filters-toggle-btn { display: none; }
.market-filters-backdrop { display: none; }

.market-filter-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.market-filter-label {
  font-size: 0.62rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}

.market-filter-select {
  width: 100%;
  background: var(--surface-2);
  border: none;
  color: var(--text);
  border-radius: var(--r-sm);
  padding: 8px 8px;
  font-size: 0.72rem;
  cursor: pointer;
}

.market-content {
  flex: 1;
  min-width: 0;
}

.market-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.market-chip {
  padding: 8px 16px;
  border-radius: 999px;
  background: var(--control-fill);
  color: var(--text-dim);
  font-size: 0.66rem;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  cursor: pointer;
  border: none;
}
.market-chip:hover { background: var(--control-fill-hover); color: var(--text); }
:root[data-theme="light"] .market-chip { background: var(--panel); }
.market-chip.active {
  background: var(--accent-dim);
  color: var(--accent);
  font-weight: 700;
  border-color: var(--accent-line);
}
/* The value chips wear the same solid colours as the verdict badges on
   the cards, so the filter and what it filters for read as one thing:
   compact pills, dimmed until picked, a ring when on. */
#marketFmvFilter .market-chip {
  padding: 5px 10px;
  font-size: 0.56rem;
  font-weight: 700;
  letter-spacing: 0.8px;
  white-space: nowrap;
}
#marketFmvFilter .fmv-chip { color: #fff; opacity: 0.55; }
#marketFmvFilter .fmv-chip:hover { color: #fff; opacity: 0.85; }
#marketFmvFilter .fmv-good-deal { background: #15803d; --chip-color: #15803d; }
#marketFmvFilter .fmv-fair { background: #5f6672; --chip-color: #5f6672; }
#marketFmvFilter .fmv-chip.active {
  color: #fff;
  opacity: 1;
  box-shadow: 0 0 0 2px var(--surface-1), 0 0 0 4px var(--chip-color);
}

.market-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 16px;
}

/* --- Card component: one shape reused for marketplace, vault, listings,
   and shipped items — image with an overlaid rarity badge, name, a thin
   divider, then a currency + price row. */

.market-item {
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-lg);
  overflow: hidden;
  cursor: pointer;
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.market-item:hover {
  transform: translateY(-3px);
  border-color: var(--rarity-color, var(--line-strong));
  box-shadow: 0 10px 24px -10px var(--rarity-color, rgba(0, 0, 0, 0.6));
}
.market-item.static { cursor: default; }
.market-item.static:hover { transform: none; box-shadow: none; }

/* One card, one surface: the photo sits inset in the card's own fill with
   the same margin all round, its corners following the card's. A separate
   backdrop behind the photo (--well) was nearly the page colour in light
   mode, so the card read as a narrow photo perched on a wider, lighter,
   square-shouldered slab. */
.market-item-media {
  position: relative;
  aspect-ratio: 1 / 1;
  padding: 8px 8px 0;
}
.market-item img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  padding: 8px;
  border-radius: var(--r-sm);
  background: #fff;
}

/* Labels live in the card body, not over the photograph. On the shot they
   landed on whatever the product happened to be at that corner — a shoe, a
   figure's head — and a label you have to look past isn't doing its job. */
.market-item-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-bottom: 6px;
}

.market-item-rarity,
.market-item-fmv,
.market-item-size {
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 0.52rem;
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Solid fill, white type. As an outline the verdict was the same weight as
   everything else on the card; filled, it's the thing you see first, which
   is the point of grading a price at all. */
.market-item-fmv { color: #fff; }
.market-item-fmv.fmv-good-deal { background: #15803d; }
.market-item-fmv.fmv-fair { background: #5f6672; }
.market-item-fmv.fmv-over { background: #c2321f; }

/* The size is a spec, not a verdict — it stays quiet next to the badge. */
.market-item-size { background: var(--surface-2); color: var(--text-dim); }
/* Offer flag on a vault card — opposite corner to the size pill, green so
   it reads as something waiting on you rather than another spec. */
.market-item-offer-flag {
  position: absolute;
  top: 8px;
  left: 8px;
  font-size: 0.52rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 4px 8px;
  border-radius: 999px;
  color: #052e16;
  background: #4ade80;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}
.market-item.has-offer { border-color: rgba(74, 222, 128, 0.35); }

.market-item-body {
  padding: 8px 12px 12px;
}

.market-item-name {
  display: block;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 8px;
}

.market-item-divider {
  height: 1px;
  background: var(--hairline);
  margin-bottom: 8px;
}

.market-item-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.market-item-price {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text);
}
.market-item-price .icon { width: 12px; height: 12px; color: var(--text-faint); }

.market-item-offer-only {
  font-size: 0.66rem;
  color: var(--text-faint);
  font-style: italic;
}

.market-item-seller {
  font-size: 0.6rem;
  color: var(--text-faint);
  letter-spacing: 0.3px;
}
.market-item-seller.you { color: var(--accent); }

.market-empty {
  grid-column: 1 / -1;
  text-align: center;
  color: var(--text-faint);
  font-size: 0.78rem;
  padding: 32px 0;
}

/* --- Account: sidebar (identity + wallet + section nav) + content pane --- */

.account-shell {
  display: flex;
  align-items: flex-start;
  gap: 24px;
}

.account-sidebar {
  flex: 0 0 232px;
  position: sticky;
  top: calc(var(--topbar-h) + 70px);
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.account-avatar-block {
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-lg);
  padding: 24px 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
}

.account-username-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: none;
  color: var(--text);
  font-size: 0.88rem;
  font-weight: 700;
  cursor: pointer;
  padding: 0;
}
.account-username-btn:hover { color: var(--accent); }
.account-username-btn::after {
  content: "";
  width: 11px;
  height: 11px;
  opacity: 0.5;
  background: currentColor;
  mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/></svg>') center/contain no-repeat;
}

.referral-link-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: var(--accent-dim);
  border-radius: 999px;
  color: var(--accent);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: pointer;
  border: none;
}
.referral-link-btn:hover { background: var(--accent-hover); }

.account-wallet-card {
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-lg);
  padding: 8px 16px;
}
.wallet-card-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  font-size: 0.72rem;
  color: var(--text-faint);
}
.wallet-card-row b { color: var(--text); font-size: 0.82rem; font-variant-numeric: tabular-nums; }
.wallet-card-row b.positive { color: var(--positive); }
.wallet-card-divider { height: 1px; background: var(--hairline); }

.account-wallet-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.account-nav {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 4px;
  background: var(--panel-blur);
  backdrop-filter: blur(10px);
  border: none;
  border-radius: var(--r-pill);
  padding: 8px;
  margin-bottom: 24px;
  position: sticky;
  top: calc(var(--topbar-h) + 12px);
  z-index: 10;
}

.account-nav-item {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 16px;
  background: transparent;
  border: none;
  border-radius: var(--r-pill);
  color: var(--text-dim);
  font-size: 0.76rem;
  font-weight: 600;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.account-nav-item:hover { background: var(--hover-bg); color: var(--text); }
.account-nav-item.active { background: var(--accent-dim); color: var(--accent); }

/* Icon is mobile-only (see the mobile media query near the end of this
   file, which swaps label-only for icon-only) — desktop keeps the
   text-label tabs as-is. */
.account-nav-item-icon { display: none; }
/* Mobile-only alternate glyph; the mobile block below flips which one shows. */
.account-nav-item-icon-mobile { display: none; }

/* Mobile-only tab — see the mobile media query near the end of this
   file. Desktop already shows the sidebar (avatar/balances) permanently
   alongside every section, so a dedicated Profile tab would be redundant
   there. */
.account-nav-item[data-group="profile"] { display: none; }
/* Mobile-only "More" — opens the footer as an overlay there (see the
   mobile media query); desktop already shows the footer inline, so this
   button and the footer's own close control both stay hidden here. */
#accountMoreBtn { display: none; }
.app-footer-close-btn { display: none; }

.account-content {
  flex: 1;
  min-width: 0;
}

/* Desktop: the nav bar belongs over the content it switches, not stretched
   across the profile card as well. Flattening the shell with
   display:contents lets the sidebar and content become grid items of the
   screen itself, so the nav can take the right-hand column's first row
   while the sidebar rises to sit alongside it. Mobile stacks everything
   in one column and is handled in the max-width:640px block. */
@media (min-width: 641px) {
  #screen-account.active {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    /* The sidebar spans both rows, so with two auto rows its height gets
       distributed across them and a short section (Clips, My Listings)
       inflates row 1, dropping the toggle bar well below the nav. A
       flexible second row takes that slack instead, so the toggle sits
       the same distance under the nav whatever is selected. */
    grid-template-rows: auto 1fr;
    column-gap: 24px;
    align-items: start;
  }
  .account-shell { display: contents; }
  .account-nav { grid-column: 2; grid-row: 1; }
  .account-content { grid-column: 2; grid-row: 2; }
  .account-sidebar {
    grid-column: 1;
    grid-row: 1 / span 2;
    /* Level with the nav now, rather than offset to clear it. */
    top: calc(var(--topbar-h) + 12px);
  }
}

/* Rewards is its own rail tab: none of Account's chrome belongs to it. The
   group icons go at every width, and on desktop the sidebar goes too —
   repeating the profile card and balances beside Streaks was the same
   duplication mobile never had. */
body:has(.nav-tab[data-account-group="rewards"].active) .account-nav { display: none; }

@media (min-width: 641px) {
  body:has(.nav-tab[data-account-group="rewards"].active) .account-sidebar { display: none; }
  body:has(.nav-tab[data-account-group="rewards"].active) #screen-account.active {
    grid-template-columns: minmax(0, 1fr);
  }
  body:has(.nav-tab[data-account-group="rewards"].active) .account-content { grid-column: 1; }
}

.account-section { display: none; }
.account-section.active { display: block; }
/* A divider only where two sections are genuinely stacked and visible.
   The :not() matters: a group's non-selected sections keep .active and are
   hidden with .toggle-hidden, and sibling combinators don't care about
   display — so Referral was inheriting a rule and 33px of offset from the
   hidden Leaderboard above it, sitting lower than the other two tabs. */
.account-section.active:not(.toggle-hidden) + .account-section.active:not(.toggle-hidden) {
  margin-top: 8px;
  padding-top: 32px;
  border-top: 1px solid var(--hairline);
}

/* Second-level toggle within a nav group (My Items vs Portfolio, Clips vs
   History vs Cashed Out vs Shipped, ...) — a segmented pill switch that
   shows one section at a time instead of stacking a group's sections down
   the page. Only the toggle belonging to the active nav group shows; the
   click handler in app.js sets .toggle-group-active, otherwise all four
   would stack regardless of which tab you're on.

   .toggle-hidden needs the !important: the initial hidden state ships in
   the markup, and Portfolio carries both .active and .toggle-hidden. */
.account-toggle { display: none; }
.account-toggle.toggle-group-active {
  display: flex;
  gap: 2px;
  background: var(--surface-2);
  border: none;
  border-radius: 999px;
  padding: 4px;
  margin-bottom: 24px;
}
.account-toggle-label {
  flex: 1;
  border: none;
  background: transparent;
  color: var(--text-dim);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-align: center;
  line-height: 1.25;
  padding: 8px 8px;
  border-radius: 999px;
  cursor: pointer;
}
.account-toggle-label:hover { color: var(--text); }
.account-toggle-label.active { background: var(--accent-dim); color: var(--accent); }
.toggle-hidden { display: none !important; }

/* --- Activity feed ------------------------------------------------------
   One row shape for every kind of event, so a mixed list reads as a single
   list rather than four stitched together. */

.activity-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-sm);
  margin-bottom: 8px;
}
.activity-row[data-listing] { cursor: pointer; }
.activity-row[data-listing]:hover { border-color: var(--line); }
.activity-row.pinned { border-color: rgba(251, 191, 36, 0.45); }

.activity-row img {
  width: 40px;
  height: 40px;
  object-fit: contain;
  background: #fff;
  border-radius: var(--r-xs);
  flex: 0 0 auto;
}
.activity-row-info { flex: 1; min-width: 0; }
.activity-row-name {
  display: block;
  font-size: 0.76rem;
  color: var(--text);
  margin-bottom: 4px;
}
.activity-row-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.activity-row-sub,
.activity-row-time {
  font-size: 0.62rem;
  color: var(--text-faint);
}
.activity-row-value {
  flex: 0 0 auto;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.activity-row-value.big { color: var(--warning); }

/* Which kind of event the row is. */
.history-tag {
  flex: 0 0 auto;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.54rem;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  background: var(--surface-2);
  color: var(--text-faint);
}
.history-tag-opened { color: #93c5fd; background: rgba(147, 197, 253, 0.12); }
.history-tag-cashedout { color: var(--positive); background: rgba(74, 222, 128, 0.12); }
.history-tag-shipped { color: var(--warning); background: rgba(251, 191, 36, 0.12); }
.history-tag-sent { color: #c4b5fd; background: rgba(196, 181, 253, 0.12); }
.history-tag-listed { color: #5eead4; background: rgba(94, 234, 212, 0.12); }
.history-tag-offer-in { color: #fda4af; background: rgba(253, 164, 175, 0.12); }
.history-tag-offer-out { color: #fdba74; background: rgba(253, 186, 116, 0.12); }

.activity-row .offer-actions { flex: 0 0 auto; }

/* --- Rewards: one page ---------------------------------------------------
   Was a Streaks/Leaderboard/Referral toggle; the three answered the same
   question, so they're cards on a single grid instead. Two columns on
   desktop with the wider half carrying the progress/leaderboard/calendar
   spine; one column on a phone. */

.rewards-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 24px;
}
.rewards-title {
  margin: 0;
  font-size: 1.6rem;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text);
}
.rewards-stats {
  display: flex;
  align-items: stretch;
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-lg);
  overflow: hidden;
}
.rewards-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 12px 24px;
}
.rewards-stat + .rewards-stat { border-left: 1px solid var(--hairline); }
.rewards-stat b {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--text);
}
.rewards-stat span {
  font-size: 0.54rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}

.rewards-grid {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}
.rewards-col {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}
.rewards-col-main { flex: 1.55; }
.rewards-col-side { flex: 1; }

.rewards-card {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 24px;
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-lg);
}
.rewards-card-title {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.rewards-card-title em {
  font-style: normal;
  margin-left: 8px;
  color: var(--text-faint);
  text-transform: none;
  letter-spacing: 0.3px;
}

/* Weekly progress */
.rewards-week-body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 24px;
}
.rewards-week-count { display: flex; flex-direction: column; gap: 4px; }
.rewards-week-value { font-size: 0.9rem; color: var(--text-dim); }
.rewards-week-value b { font-size: 2rem; font-weight: 800; color: var(--text); }
.rewards-week-note { font-size: 0.68rem; color: var(--text-faint); }
.rewards-week-strip { display: flex; gap: 8px; }
.rewards-day { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.rewards-day-name {
  font-size: 0.54rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}
.rewards-day-box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--r-xs);
  background: var(--surface-2);
  border: none;
  font-size: 0.76rem;
  color: var(--text-faint);
}
.rewards-day.hit .rewards-day-box {
  border-color: var(--line-strong);
  color: var(--text);
  font-size: 0.9rem;
}
.rewards-day.future .rewards-day-box { opacity: 0.55; }
.rewards-week-track {
  height: 4px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}
.rewards-week-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #5eead4, #16a34a);
  transition: width 0.3s ease;
}

/* Leaderboard card */
/* These blocks used to sit in a plain block-flow section where
   `margin: 0 auto` centred them at a max-width. As flex items in a column
   card, auto side margins shrink-wrap them instead — the leaderboard came
   out 231px wide in a 660px card. Let them fill their card. */
.rewards-card > .leaderboard-list,
.rewards-card > .referral-panel {
  max-width: none;
  margin: 0;
  width: 100%;
}
.rewards-leaderboard .leaderboard-list { gap: 8px; }
.rewards-more {
  align-self: flex-end;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  cursor: pointer;
}
.rewards-more:hover { color: var(--text); }
.rewards-more.expanded span { transform: rotate(90deg); }
.rewards-more span { display: inline-block; transition: transform 0.2s ease; }

/* Leaderboard pager */
.leaderboard-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.leaderboard-you-note {
  font-size: 0.62rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}
.leaderboard-pager-controls { display: flex; align-items: center; gap: 8px; }
.leaderboard-page-label {
  font-size: 0.66rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  min-width: 40px;
  text-align: center;
}
.leaderboard-page-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  border: none;
}
.leaderboard-page-btn:hover:not(:disabled) { background: var(--control-fill-hover); }
.leaderboard-page-btn:disabled { opacity: 0.35; cursor: default; }

/* How you earn more */
.rewards-earn-list { display: flex; flex-direction: column; gap: 8px; }
.rewards-earn-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 16px;
  background: var(--surface-2);
  border-radius: var(--r-sm);
}
.rewards-earn-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--surface-1);
  color: var(--text-dim);
  flex: 0 0 auto;
}
.rewards-earn-label { flex: 1; min-width: 0; font-size: 0.76rem; color: var(--text); }
/* Takes you to the Clips tab, for anyone unsure what a clip is here. */
.rewards-earn-help {
  flex: 0 0 auto;
  padding: 4px 12px;
  background: var(--control-fill);
  border-radius: 999px;
  color: var(--text-dim);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  cursor: pointer;
  border: none;
}
.rewards-earn-help:hover { color: var(--text); background: var(--control-fill-hover); }

.rewards-earn-value {
  flex: 0 0 auto;
  font-size: 0.76rem;
  font-weight: 800;
  color: var(--text);
  white-space: nowrap;
}

/* Each task carries its own proof: a link goes in, a human checks it. The
   form wraps below the label on a narrow card rather than squeezing it. */
.rewards-earn-row { flex-wrap: wrap; }
.rewards-earn-form {
  display: flex;
  gap: 8px;
  flex: 1 0 100%;
}
.rewards-earn-input {
  flex: 1;
  min-width: 0;
  padding: 8px 12px;
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-sm);
  color: var(--text);
  font-size: 0.7rem;
}
.rewards-earn-input:focus { outline: none; border-color: var(--line-strong); }
.rewards-earn-submit {
  flex: 0 0 auto;
  padding: 8px 16px;
  background: var(--control-fill);
  border-radius: 999px;
  color: var(--text);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: pointer;
  border: none;
}
.rewards-earn-submit:hover { background: var(--control-fill-hover); }
.rewards-earn-connect {
  flex: 0 0 auto;
  padding: 8px 16px;
  background: var(--control-fill);
  border-radius: 999px;
  color: var(--text);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: pointer;
  border: none;
}
.rewards-earn-connect:hover { background: var(--control-fill-hover); }

.rewards-earn-state {
  flex: 0 0 auto;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.rewards-earn-state.pending { color: var(--warning); background: rgba(251, 191, 36, 0.12); }
.rewards-earn-state.verified { color: var(--positive); background: rgba(74, 222, 128, 0.12); }

.referral-count span {
  color: var(--text-faint);
  text-transform: none;
  letter-spacing: 0.2px;
}

/* Referral card */
.referral-share-block { display: flex; flex-direction: column; gap: 2px; }
.referral-share-label {
  font-size: 0.58rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}
.referral-count {
  font-size: 0.62rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}

@media (max-width: 900px) {
  /* One column: the wrappers dissolve so the cards become items of the grid
     itself, and `order` puts them back into the reading sequence the two
     columns interleave into — main, side, main, side... */
  /* align-items:flex-start is a *horizontal* constraint once the grid
     stacks, which shrink-wrapped every card to its content and pushed the
     page 49px wider than the viewport. */
  .rewards-grid { flex-direction: column; align-items: stretch; }
  .rewards-col { display: contents; }
  .rewards-week { order: 1; }
  .rewards-raffle { order: 2; }
  .rewards-leaderboard { order: 3; }
  .rewards-referral { order: 4; }
  .rewards-earn { order: 5; }
}

.account-section-header {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 32px 0 16px;
}
.account-section-header:first-child { margin-top: 0; }
.account-section-header h3 {
  margin: 0;
  font-size: 0.78rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}

.count-badge {
  font-size: 0.62rem;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  border: none;
  color: var(--text-faint);
}

/* --- Offers --- */

.offers-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.offer-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  background: var(--panel);
  border: none;
  border-radius: var(--r-sm);
  flex-wrap: wrap;
}

.offer-row img {
  width: 40px;
  height: 40px;
  object-fit: contain;
  background: var(--well);
  border-radius: var(--r-xs);
  flex: 0 0 auto;
}

.offer-row-info {
  flex: 1;
  min-width: 140px;
  font-size: 0.72rem;
  color: var(--text-dim);
}
.offer-row-info b { color: var(--text); }

.offer-row-amount {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text);
}

.offer-status {
  font-size: 0.6rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 4px 8px;
  border-radius: 999px;
  border: none;
  color: var(--text-dim);
  background: var(--control-fill);
}
.offer-status.accepted { color: var(--positive); border-color: var(--positive); }
.offer-status.declined { color: var(--negative); border-color: var(--negative); }
.offer-status.countered { color: var(--gold); border-color: var(--gold); }

.offer-actions {
  display: flex;
  gap: 8px;
}

.offer-btn {
  padding: 8px 12px;
  font-size: 0.62rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  border-radius: 999px;
  border: none;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  background: var(--control-fill);
}
.offer-btn:hover { background: var(--text); color: var(--text-inverse); }
.offer-btn.accept { border-color: var(--positive); color: var(--positive); }
.offer-btn.accept:hover { background: var(--open-green); border-color: #000; color: var(--open-ink); }
.offer-btn.decline { border-color: var(--negative); color: var(--negative); }
.offer-btn.decline:hover { background: #f87171; color: #000; }

.offers-empty {
  color: var(--text-faint);
  font-size: 0.75rem;
  text-align: center;
  padding: 8px 0;
}

/* --- Listing detail modal --- */

.listing-modal-card { max-width: 320px; }

.listing-seller {
  margin: 0 0 16px;
  font-size: 0.72rem;
  color: var(--text-faint);
}
.listing-seller b { color: var(--text-dim); }

.detail-meta {
  margin: -4px 0 16px;
  font-size: 0.68rem;
  color: var(--text-faint);
  letter-spacing: 0.3px;
}

.listing-market-data {
  margin-bottom: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--hairline);
  text-align: left;
}
.listing-market-value-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
  font-size: 0.72rem;
  color: var(--text-faint);
}
.listing-market-value {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text);
}

/* Thumbnail strip across the top of the listing modal: step arrows either
   side of a scrolling row of every item in the grid it was opened from. */
.listing-strip {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 12px;
  height: 84px;
  padding: 0 24px;
  background: rgba(0, 0, 0, 0.35);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.listing-strip-thumbs {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 4px 2px;
  scrollbar-width: none;
}
.listing-strip-thumbs::-webkit-scrollbar { display: none; }
.listing-strip-thumb {
  flex: 0 0 auto;
  width: 52px;
  height: 52px;
  padding: 5px;
  border: none;
  border-radius: var(--r-sm);
  background: #fff;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.listing-strip-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: var(--r-xs);
}
.listing-strip-thumb:hover { opacity: 1; transform: translateY(-2px); }
/* Selected: full strength, lifted, and a shadow under it — no ring. */
.listing-strip-thumb.active { opacity: 1; transform: translateY(-3px); box-shadow: 0 8px 18px rgba(0, 0, 0, 0.35); }

.listing-nav-arrow {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  border: none;
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s ease, color 0.15s ease;
}
.listing-nav-arrow:hover { background: #fff; color: #000; }
.listing-nav-arrow:disabled { opacity: 0.25; cursor: default; pointer-events: none; }
/* Room for the strip above the card. */
.listing-modal.has-strip { padding-top: 108px; }
.listing-modal.has-strip .detail-modal-card { max-height: calc(100vh - 132px); }
@media (max-width: 640px) {
  .listing-strip { height: 68px; padding: 0 8px; gap: 6px; }
  .listing-strip-thumb { width: 44px; height: 44px; }
  .listing-nav-arrow { width: 32px; height: 32px; }
  .listing-modal.has-strip { padding-top: 84px; }
  .listing-modal.has-strip .detail-modal-card { max-height: calc(100vh - 104px); }
}

.listing-offers {
  margin-top: 24px;
  text-align: left;
}
.listing-offers h4 {
  margin: 0 0 8px;
  font-size: 0.65rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-faint);
}

.listing-close-btn {
  margin: 16px auto 0;
  display: block;
}

/* --- Item detail: price-action chart + offers --- */

.item-detail-card { max-width: 340px; }

/* --- Shared fixed-size landscape detail card: marketplace listing, Vault
   item, Portfolio position. Same footprint regardless of content — image
   + key facts in a left column, chart/offers/actions in a scrollable
   right column. The reveal is a slab and shares none of this — see
   .slab-reveal. */

.detail-modal-card {
  width: 100%;
  max-width: 860px;
  height: 580px;
  padding: 0;
  text-align: left;
  display: flex;
  overflow: hidden;
}

.detail-layout {
  display: flex;
  width: 100%;
  height: 100%;
}

.detail-media {
  flex: 0 0 390px;
  height: 100%;
  padding: 32px 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  text-align: center;
  border-right: 1px solid var(--hairline);
}
.detail-media .prize-modal-image {
  width: 320px;
  height: 320px;
  margin: 0 0 8px;
}
.detail-media .prize-modal-name {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.detail-media-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}
.detail-media-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: transparent;
  border: none;
  border-radius: 999px;
  color: var(--text-dim);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
  background: var(--control-fill);
}
.detail-media-btn:hover { background: var(--text); color: var(--text-inverse); }
.detail-media-btn:disabled { opacity: 0.5; cursor: default; }
.detail-media-btn:disabled:hover { background: transparent; color: var(--text-dim); }

.detail-content {
  flex: 1;
  min-width: 0;
  height: 100%;
  /* Top padding is deliberately generous — .detail-close-btn floats above
     this column at top:14px, and .price-chart carries its own -6px top
     margin, so a plain 32px would let the two intersect. */
  padding: 56px 32px 32px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow-y: auto;
}

.detail-close-btn {
  position: absolute;
  top: 14px;
  right: 18px;
  z-index: 3;
  margin: 0;
}

@media (max-width: 640px) {
  /* .detail-media used to refuse to shrink (flex: 0 0 auto) inside a
     fixed-height card — its own content (image/name/price/meta/seller)
     ran taller than the card, so .detail-content (the market-value chart
     and offers) got squeezed to a sliver and was effectively invisible.
     Scrolling the whole card as one unit, instead of splitting a fixed
     media block from an independently-scrolled content block, fixes it
     regardless of how tall either section's content happens to be. */
  /* The goal on mobile is fitting everything on screen with no scroll at
     all, not just "less" scroll — so the media block switches from a
     stacked column to a compact left-image/right-info row (a photo on
     its own line ate too much height), and the chart/paddings shrink too. */
  .detail-modal-card { height: auto; max-height: 90vh; overflow-y: auto; flex-direction: column; }
  .detail-layout { flex-direction: column; height: auto; }
  .detail-close-btn {
    position: sticky;
    top: 0;
    left: auto;
    display: block;
    width: 100%;
    text-align: right;
    padding: 8px 16px;
    margin: 0;
    background: var(--panel-2);
    border-bottom: 1px solid var(--hairline);
    z-index: 5;
  }
  /* Grid rather than a flex row: as a row the name, price, meta and
     seller each became their own narrow column beside the image and the
     title broke onto four lines. The image takes a fixed column and
     everything else stacks in the second one. */
  .detail-media {
    flex: 0 0 auto;
    width: 100%;
    padding: 16px;
    border-right: none;
    border-bottom: 1px solid var(--hairline);
    display: grid;
    grid-template-columns: 80px minmax(0, 1fr);
    align-items: start;
    text-align: left;
    gap: 4px 16px;
  }
  .detail-media .prize-modal-image {
    width: 80px;
    height: 80px;
    margin: 0;
    grid-column: 1;
    grid-row: 1 / -1;
    align-self: center;
  }
  .detail-media > *:not(.prize-modal-image) { grid-column: 2; }
  .detail-media .prize-modal-name {
    max-width: 100%;
    white-space: normal;
    font-size: 0.8rem;
    line-height: 1.25;
  }
  .detail-media .prize-modal-price { font-size: 0.95rem; }
  .detail-media .detail-meta { margin: 0 0 4px; }
  .detail-media .listing-seller { text-align: left; }
  .detail-media-actions { justify-content: flex-start; margin-top: 4px; }
  .detail-content {
    flex: 0 0 auto;
    height: auto;
    padding: 12px 16px 16px;
    justify-content: flex-start;
    overflow-y: visible;
    gap: 4px;
  }
  .detail-content .price-chart { height: 56px; margin: 0 0 2px; }
}

.price-chart {
  width: 100%;
  height: 90px;
  margin: -8px 0 4px;
}
.price-chart-svg { width: 100%; height: 100%; display: block; }
/* Direction comes from the class buildPriceChartSVG puts on the <svg>; the
   colour comes from the theme. */
.price-chart-svg.up { fill: var(--positive); stroke: var(--positive); }
.price-chart-svg.down { fill: var(--negative); stroke: var(--negative); }
.price-chart-caption {
  display: block;
  font-size: 0.6rem;
  color: var(--text-faint);
  text-align: center;
  margin-bottom: 24px;
}

/* .modal-btn carries flex:1 so a row of them splits the width evenly. A
   button placed directly in .detail-content is in a *column* flex instead,
   where that grows it vertically — Sell Share Value came out 228px tall for
   12px of padding. Applies to Remove Listing in the same slot. */
/* Sell-amount quick fractions. The number input's spinner arrows are
   removed with them: you either type a figure or take a fraction, and the
   1-at-a-time steppers were useful for neither. */
.amount-input::-webkit-outer-spin-button,
.amount-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.amount-input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* Still used by the Withdraw modal's Max button. */
.amount-max-btn {
  flex: 0 0 auto;
  padding: 0 16px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  background: transparent;
  border: none;
  color: var(--text);
  border-radius: var(--r-pill);
  cursor: pointer;
  background: var(--control-fill);
}
.amount-max-btn:hover { background: var(--text); color: var(--text-inverse); }

.amount-quick-row {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}
.amount-quick-row.hidden { display: none; }
.amount-quick-btn {
  flex: 1;
  padding: 8px 0;
  background: var(--surface-2);
  border: none;
  border-radius: 999px;
  color: var(--text-dim);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: pointer;
}
.amount-quick-btn:hover { color: var(--text); border-color: var(--line-strong); }
.amount-quick-btn.active {
  background: var(--accent-dim);
  border-color: var(--accent-line);
  color: var(--accent);
}

.detail-content > .modal-btn { flex: 0 0 auto; }

/* Send is an icon on the vault cards — the word sat next to "Ship" and the
   two read as the same action. */
.item-action-btn.item-action-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 34px;
  padding-left: 0;
  padding-right: 0;
}
.item-action-btn.item-action-icon svg { width: 14px; height: 14px; }

.item-detail-offers {
  margin-top: 4px;
  text-align: left;
}
.item-detail-offers h4 {
  margin: 0 0 8px;
  font-size: 0.65rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-faint);
}

.offer-row.platform-offer {
  border-color: var(--accent);
  background: var(--accent-dim);
  margin-bottom: 8px;
}

/* --- Recent pull detail modal --- */

.pull-detail-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: -8px 0 24px;
}
.pull-detail-user {
  font-size: 0.72rem;
  color: var(--text-faint);
}
.pull-detail-user.you { color: var(--accent); }

.pull-detail-go-btn {
  width: 100%;
  margin-bottom: 8px;
}

/* --- Amount prompt modal --- */

.amount-modal-card { max-width: 280px; }

.amount-input-row {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.amount-input {
  flex: 1;
  width: 100%;
  padding: 12px 16px;
  background: var(--panel-2);
  border: none;
  border-radius: var(--r-sm);
  color: var(--text);
  font-size: 1.1rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.amount-input:focus { outline: none; border-color: var(--text); }


/* --- Add Funds --- */

.add-funds-btn {
  cursor: pointer;
  color: var(--text);
  border-color: var(--line-strong);
}
.add-funds-btn:hover { background: var(--text); color: var(--text-inverse); }

.wallet-cash-btn {
  font-family: inherit;
  cursor: pointer;
}
.wallet-cash-btn:hover { border-color: var(--line-strong); }
/* The cash pill ends in the site's green + (the Deposit button's
   gradient), sitting just inside the pill's right edge. */
#walletCashBtn { padding: 5px 5px 5px 12px; gap: 8px; }
.wallet-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: 2px;
  border-radius: 50%;
  background: var(--open-green);
  color: var(--open-ink);
  box-shadow: inset 0 0 0 1.5px #000;
  transition: transform 0.15s ease, background 0.15s ease;
}
#walletCashBtn:hover .wallet-add { transform: scale(0.9); background: var(--open-green-hover); }
@media (max-width: 640px) {
  .wallet-add { width: 18px; height: 18px; }
  .wallet-add svg { width: 10px; height: 10px; }
  #walletCashBtn { padding: 3px 3px 3px 8px; }
}

/* --- Crate badge (Sneakers/Streetwear/Collectibles) --- */

.tier-badge {
  display: inline-block;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  margin-bottom: 8px;
  padding: 4px 8px;
  border-radius: 999px;
  border: none;
}
.tier-badge-sneakers { color: #d4794e; background: rgba(212, 121, 78, 0.14); }
.tier-badge-streetwear { color: #5b8dd9; background: rgba(91, 141, 217, 0.14); }
.tier-badge-collectibles { color: #c9942f; background: rgba(201, 148, 47, 0.16); }
.tier-badge-pokémon { color: #d64545; background: rgba(214, 69, 69, 0.13); }

/* --- Reveal exits: Cash Out / Keep --- */

.multiplier-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin: 8px 0 0;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0.5px;
}
.multiplier-badge.positive { color: var(--positive); }
.multiplier-badge-arrow { width: 12px; height: 12px; }

.exits-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 24px;
}

.exit-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 12px 8px;
  background: var(--control-fill);
  border-radius: var(--r-md);
  color: var(--text);
  cursor: pointer;
  text-align: center;
  transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease;
  border: none;
}
.exit-btn:hover { transform: translateY(-2px); background: var(--control-fill-hover); }
.exit-btn-label {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.exit-btn-sub {
  font-size: 0.6rem;
  color: var(--text-faint);
  text-align: center;
}
.exit-btn-primary {
  background: var(--text);
  color: var(--text-inverse);
  border-color: var(--text);
}
.exit-btn-primary .exit-btn-sub { color: var(--text-inverse-dim); }
.exit-btn-primary:hover { background: var(--text); opacity: 0.9; }

/* --- Payment error --- */

.payment-modal-error {
  margin: -8px 0 16px;
  font-size: 0.72rem;
  color: var(--negative);
}

.payment-option.insufficient {
  opacity: 0.45;
}

/* --- Marketplace filter rework --- */

.market-listed-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.7rem;
  color: var(--text-dim);
  letter-spacing: 0.5px;
  cursor: pointer;
}

.market-price-range {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text-faint);
  font-size: 0.75rem;
}

.market-price-input {
  width: 72px;
  padding: 8px 8px;
  background: var(--panel);
  border: none;
  border-radius: var(--r-sm);
  color: var(--text);
  font-size: 0.72rem;
}

.market-item-fmv {
  display: block;
  font-size: 0.56rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  margin-bottom: 4px;
}

.market-item-offer-only {
  display: block;
  font-size: 0.7rem;
  color: var(--text-faint);
  font-style: italic;
  margin-bottom: 4px;
}

/* --- Account summary + inventory item actions --- */

.account-block-note {
  font-size: 0.6rem;
  letter-spacing: 1px;
  text-transform: none;
  color: var(--text-faint);
  font-weight: 400;
  margin-left: 8px;
}

.item-archival {
  display: block;
  font-size: 0.58rem;
  color: var(--text-faint);
  margin-bottom: 8px;
}
.item-archival.soon { color: var(--gold); }
.item-archival.archived { color: var(--negative); }

.item-cashout-today {
  display: block;
  font-size: 0.62rem;
  color: var(--text-dim);
  margin-bottom: 8px;
}

.item-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
}
.item-action-btn {
  padding: 8px 0;
  font-size: 0.58rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  background: var(--control-fill);
  color: var(--text);
  border-radius: 999px;
  cursor: pointer;
  border: none;
}
.item-action-btn:hover { background: var(--text); color: var(--text-inverse); }
.item-action-btn:disabled { opacity: 0.3; cursor: default; }
.item-action-btn:disabled:hover { background: transparent; color: var(--text); }

/* --- Opening history --- */

.openings-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 700px;
  margin: 0 auto;
}
.opening-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  background: var(--panel);
  border: none;
  border-radius: var(--r-sm);
}
.opening-row.pinned { border-color: var(--gold); }
.opening-row img {
  width: 36px;
  height: 36px;
  object-fit: contain;
  background: var(--well);
  border-radius: var(--r-xs);
}
.opening-row-name { flex: 1; font-size: 0.75rem; color: var(--text); }
.opening-row-mult {
  font-family: monospace;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text);
}
.opening-row-mult.big { color: var(--gold); }
.opening-row-pin { font-size: 0.85rem; color: var(--gold); }

/* --- Leaderboard --- */

.leaderboard-list {
  max-width: 700px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.leaderboard-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 8px 16px;
  background: var(--panel);
  border: none;
  border-radius: var(--r-sm);
  font-size: 0.8rem;
  cursor: pointer;
  transition: border-color 0.15s ease;
}
.leaderboard-row:hover { border-color: var(--line-strong); }
.leaderboard-row.you {
  border-color: var(--accent);
  background: var(--accent-dim);
}
.leaderboard-rank {
  font-family: monospace;
  color: var(--text-faint);
  width: 24px;
}
.leaderboard-name { flex: 1; }
.leaderboard-xp { font-weight: 700; font-variant-numeric: tabular-nums; }

/* --- Referral panel --- */

.referral-panel {
  max-width: 700px;
  margin: 0 auto;
}
.referral-current {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  background: var(--panel);
  border: none;
  border-radius: var(--r-sm);
  margin-bottom: 16px;
}
.referral-current .share {
  font-size: 1.6rem;
  font-weight: 800;
}
.referral-current .next {
  font-size: 0.68rem;
  color: var(--text-faint);
  text-align: right;
}
.referral-progress-track {
  height: 4px;
  border-radius: var(--r-pill);
  background: var(--track);
  overflow: hidden;
  margin-bottom: 24px;
}
.referral-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #5eead4, #16a34a);
}
.referral-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.72rem;
  margin-bottom: 24px;
}
.referral-table th {
  text-align: left;
  padding: 8px 8px;
  color: var(--text-faint);
  font-size: 0.6rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line-strong);
}
.referral-table td {
  padding: 8px 8px;
  border-bottom: 1px solid var(--hairline);
  color: var(--text-dim);
}
.referral-table td:first-child { color: var(--text); font-weight: 700; }

.referral-claim {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 24px;
  background: var(--panel);
  border: none;
  border-radius: var(--r-sm);
  margin-bottom: 24px;
  text-align: left;
}
.referral-claim-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.referral-claim-label {
  font-size: 0.62rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}
.referral-claim-amount {
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--text);
}
/* Info + two buttons + an "or" doesn't fit one line in the column this card
   sits in — the actions couldn't shrink (flex:0 0 auto, 112px min per
   button) so Credits ran 42px past the card on desktop and 77px on a
   phone. They wrap onto their own line and share it. */
.referral-claim-actions {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  gap: 8px;
}
.referral-claim-actions .exit-btn {
  flex: 1;
  min-width: 0;
}
/* The two claims are alternatives, not a pair to collect — one small "or"
   says that without a sentence explaining it. */
.referral-claim-or {
  flex: 0 0 auto;
  align-self: center;
  font-size: 0.6rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* Claim buttons: a small label over a big amount, left-aligned, with the
   Credits bonus as a quiet outlined tag on the right, vertically centred. */
.claim-btn {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  text-align: left;
}
.claim-btn-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.claim-btn-label {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  opacity: 0.7;
}
.claim-btn-amount {
  font-size: 1.25rem;
  font-weight: 800;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.referral-claim-bonus {
  flex: 0 0 auto;
  padding: 3px 9px;
  border-radius: 999px;
  border: none;
  background: color-mix(in srgb, currentColor 14%, transparent);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  opacity: 0.75;
}
.deposit-btn .referral-claim-bonus {
  background: rgba(255, 255, 255, 0.28);
  color: #04160c;
  opacity: 1;
}

.referral-section-label {
  font-size: 0.62rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 8px;
}

/* --- Streaks: daily-play calendar + weekly raffle -------------------- */

.streak-top-row {
  display: flex;
  align-items: stretch;
  /* Wraps rather than crushing both columns past their basis — at narrower
     desktop widths two 320px panels don't fit and the text was breaking to
     one word per line. */
  flex-wrap: wrap;
  gap: 16px;
}
.streak-top-row > * { flex: 1 1 320px; min-width: 0; }

/* Both columns are a heading over a card, so the two headings sit on one
   line and — since the row stretches and each card takes the leftover
   height — the cards under them match. */
.streak-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.streak-panel-title {
  font-size: 0.78rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-weight: 600;
}
.streak-panel > .streak-summary,
.streak-panel > .streak-raffle-prize { flex: 1; }

.streak-summary {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  padding: 16px 24px;
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-lg);
}
.streak-summary-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.streak-count-block {
  flex: 0 0 auto;
  text-align: center;
  padding-right: 24px;
  border-right: 1px solid var(--hairline);
}
.streak-count-value {
  display: block;
  font-size: 2rem;
  font-weight: 800;
  color: var(--text);
  line-height: 1;
}
.streak-count-label {
  display: block;
  font-size: 0.62rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-top: 4px;
}

.streak-explainer {
  margin: 0;
  font-size: 0.74rem;
  line-height: 1.45;
  color: var(--text-dim);
}
.streak-explainer b { color: var(--text); }

.streak-raffle-badge {
  flex: 0 0 auto;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 8px 16px;
  border-radius: 999px;
  white-space: nowrap;
}
.streak-raffle-badge.qualified { color: var(--positive); background: rgba(74, 222, 128, 0.14); border: 1px solid rgba(74, 222, 128, 0.4); }
.streak-raffle-badge.pending { color: var(--text-faint); background: var(--surface-2); border: none; }

.streak-raffle-prize {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 16px;
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-lg);
}
.streak-raffle-prize img {
  width: 56px;
  height: 56px;
  object-fit: contain;
  background: var(--well);
  border-radius: var(--r-sm);
  flex: 0 0 auto;
}
/* Desktop has the height to spare now the two cards match — a bigger
   image keeps the prize card from reading as mostly empty beside the
   streak count. */
@media (min-width: 641px) {
  .streak-raffle-prize img { width: 88px; height: 88px; }
}
.streak-raffle-prize-info { flex: 1; min-width: 0; }
.streak-raffle-prize-name {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text);
}
.streak-raffle-prize-value {
  display: block;
  font-size: 0.7rem;
  color: var(--text-faint);
  margin-top: 4px;
}

.streak-calendar-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 8px;
  max-width: 420px;
  margin-bottom: 8px;
}
.streak-calendar-weekdays span {
  text-align: center;
  font-size: 0.6rem;
  color: var(--text-faint);
}

.streak-calendar {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 8px;
  max-width: 420px;
}

.streak-tile {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-sm);
  font-size: 0.62rem;
  color: var(--text-faint);
  background: var(--surface-2);
  border: none;
}
.streak-tile.empty { background: transparent; border-color: transparent; }
.streak-tile.level-1 { background: rgba(230, 230, 235, 0.22); border-color: rgba(230, 230, 235, 0.3); color: var(--text-dim); }
.streak-tile.level-2 { background: rgba(230, 230, 235, 0.42); border-color: var(--accent-line); color: var(--text); }
.streak-tile.level-3 { background: rgba(230, 230, 235, 0.66); border-color: rgba(230, 230, 235, 0.75); color: var(--text); }
.streak-tile.level-4 { background: var(--accent); border-color: var(--accent); color: var(--text-inverse); font-weight: 700; }
.streak-tile.today { outline: 2px solid var(--text); outline-offset: 1px; }

/* --- Clips: recorded pull videos (session-only) --- */

.clips-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 16px;
}

.clip-card {
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-lg);
  overflow: hidden;
}

.clip-card-placeholder {
  width: 100%;
  aspect-ratio: 16 / 10;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--well);
  color: var(--text-faint);
}

.clip-card-body { padding: 8px 12px 12px; }

.clip-card-name {
  display: block;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- Public shareable profile --- */

.public-profile {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
  background: var(--bg);
}

.public-profile-card {
  width: 100%;
  max-width: 420px;
  text-align: center;
  background: var(--surface-1);
  border: none;
  border-radius: var(--r-xl);
  padding: 32px 32px;
}

.public-profile-card .avatar-lg { margin: 0 auto 16px; width: 72px; height: 72px; font-size: 1.4rem; }

.public-profile-card h2 {
  margin: 0 0 24px;
  font-size: 1.3rem;
  font-weight: 800;
}

.public-profile-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--hairline);
  border: none;
  border-radius: var(--r-lg);
  overflow: hidden;
  margin-bottom: 32px;
}
.public-profile-stats > div { background: var(--surface-2); padding: 16px; }
.public-profile-stats dt {
  font-size: 0.6rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 8px;
}
.public-profile-stats dd {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.public-profile-subhead {
  font-size: 0.68rem;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: 500;
  margin: 0 0 12px;
}

.public-profile-card .recent-pulls-list { justify-content: center; margin-bottom: 24px; }

.public-profile-back { display: block; text-decoration: none; }

/* --- Add Funds: simulated crypto deposit / card / Apple Pay --- */

.add-funds-modal-card { max-width: 380px; text-align: left; }
.add-funds-modal-card .payment-modal-title { text-align: center; margin-bottom: 16px; }

.add-funds-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
  background: var(--surface-2);
  border-radius: var(--r-pill);
  padding: 4px;
}
.add-funds-tab {
  flex: 1;
  padding: 8px 0;
  background: transparent;
  border: none;
  border-radius: var(--r-pill);
  color: var(--text-faint);
  font-size: 0.72rem;
  font-weight: 700;
  cursor: pointer;
}
.add-funds-tab.active { background: var(--surface-1); color: var(--text); }

.deposit-address-box {
  background: var(--surface-2);
  border: none;
  border-radius: var(--r-sm);
  padding: 12px 16px;
  margin-bottom: 16px;
}
.deposit-address-label {
  display: block;
  font-size: 0.66rem;
  color: var(--text-faint);
  margin-bottom: 8px;
}
.deposit-address-label b { color: var(--text-dim); }
.deposit-address-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.deposit-address {
  flex: 1;
  min-width: 0;
  font-family: monospace;
  font-size: 0.72rem;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.deposit-copy-btn {
  flex: 0 0 auto;
  padding: 4px 12px;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  background: transparent;
  border: none;
  color: var(--text);
  border-radius: 999px;
  cursor: pointer;
}
.deposit-copy-btn:hover { background: var(--text); color: var(--text-inverse); }

.add-funds-card-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
}

.add-funds-note {
  font-size: 0.64rem;
  line-height: 1.5;
  color: var(--text-faint);
  margin: 16px 0 16px;
}

/* --- Withdraw: payout wallet whitelist + crypto withdrawal --- */

.withdraw-address-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 8px 0 8px;
}

.withdraw-address-empty {
  font-size: 0.68rem;
  color: var(--text-faint);
  margin: 8px 0 8px;
}

.withdraw-address-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  background: var(--surface-2);
  border: none;
  border-radius: var(--r-sm);
  cursor: pointer;
  text-align: left;
  color: var(--text);
  font: inherit;
}
.withdraw-address-item:hover { border-color: var(--line-strong); }
.withdraw-address-item.selected { border-color: var(--accent); background: var(--accent-dim); }

.withdraw-address-info { min-width: 0; }
.withdraw-address-nickname {
  display: block;
  font-size: 0.76rem;
  font-weight: 700;
}
.withdraw-address-detail {
  display: block;
  margin-top: 2px;
  font-size: 0.62rem;
  font-family: monospace;
  color: var(--text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.withdraw-address-chain {
  flex: 0 0 auto;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-faint);
}

.withdraw-add-address {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}

.field-input {
  width: 100%;
  padding: 8px 12px;
  background: var(--panel-2);
  border: none;
  border-radius: var(--r-sm);
  color: var(--text);
  font-size: 0.76rem;
}
.field-input:focus { outline: none; border-color: var(--text); }

.hidden { display: none !important; }

/* ==========================================================================
   Mobile (<=640px) — a real mobile pass, not the desktop shell squeezed
   down. Everything below is additive/overriding inside this one query, so
   nothing here touches desktop rendering. Bottom tab bar in place of the
   left rail, a condensed always-visible-essentials header, single-column
   stacking wherever desktop used a fixed sticky sidebar, tighter type and
   spacing throughout, and secondary detail (full prize catalog, "Powered
   by" lines, stat labels) tucked behind a tap or dropped entirely.
   ========================================================================== */

@media (max-width: 640px) {
  :root {
    /* The same scale a step tighter: phone-width cards with desktop
       corners start to read as pills. */
    --r-md: 14px;
    --r-lg: 16px;
    --r-xl: 20px;
    --r-2xl: 22px;
    --topbar-h: 52px;
    --bottom-nav-h: 60px;
    /* The floating Account group-icon bar, and the section toggle that
       sits beside it. Both are position:fixed, so they can't flex against
       each other — the pair is centred with arithmetic instead, which
       needs the nav's width to be a number rather than max-content.
       260px is exactly what its five 42px icons come to (5×42 + 4×8 gaps
       + 8px padding either side + 1px borders), so pinning it changes
       nothing about how it looks. */
    --account-nav-h: 56px;
    --account-nav-w: 260px;
    --account-toggle-w: 66px;
    --account-dock-gap: 8px;
    /* How far left the nav moves to keep nav + toggle centred as a pair. */
    --account-dock-shift: calc((var(--account-toggle-w) + var(--account-dock-gap)) / 2);
  }

  /* --- Bottom tab bar ----------------------------------------------- */

  /* The nav element lives in the header now, so its own background and
     padding come from here rather than from a desktop rail base. It pins
     itself to the bottom of the viewport: the header paints its blur on a
     pseudo-element precisely so a fixed child like this one still escapes
     it. */
  .rail {
    position: fixed;
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    height: var(--bottom-nav-h);
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    background: var(--surface-1);
    padding: 8px 8px;
    padding-bottom: max(8px, env(safe-area-inset-bottom));
    border-right: none;
    border-top: 1px solid var(--hairline);
    z-index: 40;
  }
  .rail-nav {
    flex-direction: row;
    width: auto;
    flex: 1;
    justify-content: space-around;
    gap: 0;
  }
  /* Icon over label: a bottom bar is read by shape, not by reading. */
  .nav-tab {
    flex-direction: column;
    width: auto;
    flex: 1;
    min-width: 0;
    padding: 4px 0;
    letter-spacing: 0.2px;
  }
  /* Mute lives in the footer's Social Media row on mobile (see the JS
     that reparents #muteBtn there) — the bottom bar is Drops/Market/
     Account only, nothing else. */
  .rail-bottom { display: none; }
  .mute-btn { width: 32px; height: 32px; }

  .shell-main main {
    padding: 16px 16px calc(var(--bottom-nav-h) + 24px);
  }

  /* --- Condensed header — logo, balances, avatar; the
     gamification stats and secondary actions live in their own screens
     already (Streaks/Referral tabs, Account's Add Funds button). --- */

  .topbar { padding: 0 12px; gap: 8px; }
  .brand-logo { font-size: 1.15rem; letter-spacing: 1px; }
  #referralStat { display: none; }
  /* The streak stays, as just its ring and number: the word is what
     doesn't fit, not the thing itself. */
  #streakStat { gap: 5px; padding: 4px 8px; font-size: 0.62rem; white-space: nowrap; }
  #streakStat .stat-pill-label { display: none; }
  .topbar-stats { flex-wrap: nowrap; gap: 4px; overflow-x: auto; scrollbar-width: none; }
  .topbar-stats::-webkit-scrollbar { display: none; }
  .wallet-item, .avatar-btn { font-size: 0.62rem; padding: 4px 8px; white-space: nowrap; }
  .avatar-btn { padding: 4px; gap: 0; }

  .screen-title { font-size: 1.05rem; margin-bottom: 16px; }

  /* --- Drops: tier cards ---------------------------------------------- */

  .category-list { gap: 8px; }
  .category-card { padding: 16px 8px 16px; }
  .category-box-canvas { width: 92px; height: 92px; margin: 4px auto 2px; }
  .category-payment-badges { top: 8px; right: 8px; gap: 4px; }
  .category-icon-badge { width: 22px; height: 22px; }
  .category-icon-badge svg { width: 11px; height: 11px; }
  .category-tier-name, .category-tier-price { font-size: 0.82rem; }
  .category-powered-by, .category-powered-by-spacer { display: none; }
  .pity-bar { margin-top: 8px; }
  .pity-bar-label { font-size: 0.54rem; }
  .category-qty { margin-top: 8px; gap: 8px; }
  .qty-btn { width: 24px; height: 24px; font-size: 0.8rem; }
  .qty-value { font-size: 0.82rem; min-width: 16px; }
  .qty-max-btn { padding: 4px 8px; }
  .category-open-btn { margin-top: 8px; padding: 8px 0; font-size: 0.68rem; }

  /* Live odds: five full-width buckets stacked in one column was mostly
     empty space to the right of each. Four across fits the row; what
     used to crop the content here wasn't the column count but the bare
     1fr — the widest price range ("$3,302–$11,005") set the track's
     min-content, so pin the tracks with minmax(0,…) and let the range
     wrap instead. Whatever's left over (Legendary, usually) takes the
     full width underneath rather than sitting as a quarter-width orphan. */
  .odds-panel { padding: 12px 12px; }
  .odds-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; }
  .odds-bucket { padding: 8px 8px; gap: 1px; }
  .odds-bucket-rarity { font-size: 0.5rem; letter-spacing: 0.4px; }
  .odds-bucket-range { font-size: 0.54rem; line-height: 1.2; }
  .odds-bucket-pct { font-size: 0.82rem; }
  .odds-grid > .odds-bucket:last-child:nth-child(4n + 1) { grid-column: 1 / -1; }

  .prize-dropdown-header { padding: 8px 12px; font-size: 0.6rem; }

  /* Tier page (structure is in the base cascade) — mobile sizing only. */
  .drop-detail-back { margin-bottom: 12px; padding: 8px 12px; font-size: 0.66rem; }
  .drop-detail-active .category-box-canvas { width: 132px; height: 132px; }
  .drop-detail-active .category-card { padding: 16px 16px; }
  /* Undo the list view's hide — the tier page has room for the credit. */
  .drop-detail-active .category-powered-by { display: flex; }

  /* --- Drops: picking screen (reel + 3 boxes) ------------------------- */

  /* Top padding clears the tier label ($1000 etc.), which the reveal
     cards float up into otherwise. */
  /* 3 slots + 2 gaps has to clear the 343px between the page gutters:
     104*3 + 8*2 = 328. A 16px gap tipped it to 344 and the third
     crate wrapped onto its own row. */
  .box-row { column-gap: 8px; row-gap: 48px; padding: 56px 0 8px; }
  .box-slot { width: 104px; }
  .box-canvas { width: 104px; height: 104px; }
  .box-caption { font-size: 0.62rem; }

  /* The reveal card kept its desktop 168px while the slot under it shrank
     to 104px, so each card overhung its neighbours by ~50px — the three
     of them landed on top of each other and the outer two ran off the
     side of the screen. Sized to sit inside the 118px slot pitch, with
     the contents scaled to match. */
  .price-card { width: 104px; }
  .box-slot.open .price-card { transform: translate(-50%, -52px) scale(1); }

  /* No "Go to Drops" arrow here — the bottom tab bar is the way back, and
     it deselects itself below so Drops reads as somewhere to return to.
     That leaves the two status badges to centre on their own. */
  .game-top-bar .back-btn { display: none; }
  .game-top-bar { justify-content: center; margin-bottom: 32px; }

  /* The badges sit under the header and the crates in the space below
     (see .game-spacer); this just drops the button away from the cards. */
  #playAgainBtn { margin-top: 32px; }

  /* Nothing in the tab bar is "where you are" mid-open: un-highlighting
     Drops is what tells you to tap it to get back out. */
  body:has(#screen-game.active) .nav-tab.active {
    background: transparent;
    border-color: transparent;
    color: var(--text-faint);
    font-weight: 400;
  }

  /* --- Recent Pulls ---------------------------------------------------- */

  .recent-pulls { margin-top: 24px; }
  .recent-pull-item { width: 118px; padding: 8px 8px 12px; }
  .recent-pull-item img { width: 72px; height: 72px; margin-bottom: 8px; }
  .recent-pull-price { font-size: 0.8rem; margin-bottom: 8px; }

  /* --- Marketplace: filters become a slide-up sheet -------------------- */

  /* Filters sits beside the title instead of stacked below it — on its
     own line it left a bigger gap under "Marketplace" than "Time to
     Choose" gets on Drops, for no reason. */
  .market-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 16px;
  }
  .market-title-row .screen-title { margin-bottom: 0; }
  /* Thumb reach: floated just above the tab bar rather than up beside the
     title, where it needed a second hand. Dimmed while the page is
     moving (body.is-scrolling, set in app.js) so it isn't sitting
     solidly over the grid you're scanning, and out of the way entirely
     once the sheet it opens is up. */
  .market-filters-toggle-btn {
    display: flex;
    align-items: center;
    gap: 8px;
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(var(--bottom-nav-h) + 12px);
    z-index: 41;
    margin: 0;
    padding: 8px 24px;
    background: var(--surface-2);
    border: none;
    border-radius: 999px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
    color: var(--text);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.3px;
    cursor: pointer;
    width: fit-content;
    transition: opacity 0.2s ease;
  }
  body.is-scrolling .market-filters-toggle-btn { opacity: 0.4; }
  .market-title-row:has(.market-filters-toggle-input:checked) .market-filters-toggle-btn {
    opacity: 0;
    pointer-events: none;
  }
  .market-shell { flex-direction: column; gap: 0; max-width: 100%; }
  .market-filters {
    position: fixed;
    left: 0;
    right: 0;
    top: auto;
    bottom: 0;
    flex: 0 0 auto;
    max-height: 78vh;
    margin: 0;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
    overflow-y: auto;
    transform: translateY(105%);
    transition: transform 0.28s ease;
    z-index: 60;
  }
  /* The toggle checkbox now lives inside .market-title-row (so Filters
     can sit beside the title) rather than directly beside .market-shell,
     so reaching .market-shell needs :has() on the wrapper first. */
  .market-title-row:has(.market-filters-toggle-input:checked) ~ .market-shell .market-filters { transform: translateY(0); }
  .market-filters-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.6);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.28s ease;
    z-index: 55;
  }
  .market-title-row:has(.market-filters-toggle-input:checked) ~ .market-shell .market-filters-backdrop { opacity: 1; pointer-events: auto; }
  .market-content { width: 100%; }

  /* --- Grids: Marketplace, Vault, Portfolio, Listings, Shipped share
     .market-item / .market-grid — pin to a tight 2-up instead of desktop's
     auto-fill(150px), for a clean grid feel instead of an odd 1.5-column
     wrap. --- */
  .market-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .market-item-name { font-size: 0.68rem; }
  .market-item-body { padding: 8px 8px 8px; }

  /* --- Account -------------------------------------------------------- */

  /* Stacking the shell turns .account-shell's align-items:flex-start into
     a *horizontal* constraint, so both columns shrink-wrap their content
     — which made every toggle bar and section a different width
     depending on what was selected (a lone listing tile gave ~210px, an
     empty Shipped state ~184px, a full offers list the whole 347px).
     Pin both to the full width so switching Clips/History/Cashed Out or
     My Listings/Offers never resizes the container around them. */
  /* Offer buttons wrap under the row here instead of squeezing the name
     into nothing. */
  .activity-row { flex-wrap: wrap; padding: 12px; gap: 8px 12px; }
  .activity-row .offer-actions { flex: 1 0 100%; justify-content: flex-start; }
  .activity-row-name { font-size: 0.72rem; }

  /* Clearance for the control row floating over the bottom of the screen
     (--account-nav-h plus its gaps — the section toggle rides alongside
     it rather than above it, so it adds no height). */
  #screen-account.active { padding-bottom: 64px; }

  .account-shell { flex-direction: column; gap: 16px; }
  .account-sidebar { position: static; width: 100%; flex-basis: auto; }
  .account-content { width: 100%; }
  .account-avatar-block { padding: 16px 12px; }
  .account-wallet-card { padding: 2px 16px; }
  .wallet-card-row { padding: 8px 0; font-size: 0.68rem; }
  /* Icons instead of words — 11 text tabs needed horizontal scrolling to
     see them all; icon-only tiles wrap onto two short rows that show
     everything at once, no scrolling needed. */
  /* Thumb reach again: the two rows of controls stack upward off the tab
     bar instead of sitting at the top of the screen — tab bar, then the
     group icons, then that group's section toggle, so everything you tap
     to get around is under your thumb. (The reverse of desktop, where
     they read top-down.) */
  /* Shrink-wrapped and centred rather than spanning the gutters: it holds
     five icons, so a full-width bar was mostly empty space on both sides.
     --nav-x carries the centring so the hide-on-scroll rule below can add
     its translateY without losing it. */
  .account-nav {
    position: fixed;
    left: 50%;
    right: auto;
    --nav-x: -50%;
    transform: translateX(var(--nav-x));
    width: var(--account-nav-w);
    max-width: calc(100% - 32px);
    top: auto;
    bottom: calc(var(--bottom-nav-h) + 8px);
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin-bottom: 0;
    z-index: 41;
  }
  /* Make room for the section toggle when a group has one, so the two
     read as one centred dock rather than a centred bar with something
     hanging off it. */
  body:has(.account-toggle.toggle-group-active) .account-nav {
    --nav-x: calc(-50% - var(--account-dock-shift));
  }

  body:has(.nav-tab[data-account-group="rewards"].active) #screen-account.active {
    padding-bottom: 56px;
  }

  /* Both bottom bars tuck away on the way down and come back when you
     scroll up or stop — the idle timer in app.js clears .scrolling-down,
     so "stopped" reads the same as "scrolling up" here. */
  .account-nav,
  .account-toggle.toggle-group-active {
    transition: transform 0.22s ease, opacity 0.22s ease;
  }
  /* Both keep their horizontal placement on the way out — a bare
     translateY would drop them back to the left edge. */
  body.is-scrolling.scrolling-down .account-toggle.toggle-group-active {
    transform: translateX(var(--toggle-x)) translateY(calc(100% + 16px));
    opacity: 0;
    pointer-events: none;
  }
  body.is-scrolling.scrolling-down .account-nav {
    transform: translateX(var(--nav-x)) translateY(calc(100% + 16px));
    opacity: 0;
    pointer-events: none;
  }
  .account-nav-item {
    flex: 0 0 auto;
    width: 42px;
    height: 38px;
    padding: 0;
  }
  .account-nav-item-icon { display: block; }
  .account-nav-item-label { display: none; }
  /* Swap the vault glyph for the box one (see index.html). */
  .account-nav-item-icon-mobile { display: block; }
  .account-nav-item-icon:has(+ .account-nav-item-icon-mobile) { display: none; }

  /* The streak card only needs the number and the "N more days to
     qualify" line on a phone — the explainer paragraph between them was
     the tallest thing in the section. Hidden rather than deleted so
     desktop keeps it and renderStreaks() can still write #streakGoalInline. */
  .streak-explainer { display: none; }
  /* No room for two columns — back to a stack, which with the explainer
     hidden leaves the count and its badge on one line as before. The
     row's flex-basis is a *height* once stacked, so it has to go. */
  .streak-top-row { flex-direction: column; gap: 8px; }
  .streak-top-row > * { flex: 0 0 auto; }
  .streak-summary-meta { flex: 0 0 auto; }

  /* Second-level toggle (structure is in the base cascade) — a vertical
     pill parked on the right end of the group icons, at the same height,
     instead of a full-width bar stacked above them. The icon bar only
     needs 260px of a 375px screen, so putting the two options in the
     space beside it costs a row of screen rather than taking one.
     --toggle-x puts its left edge one gap past the nav's right edge (see
     --account-dock-shift, which moves the nav left by half of what this
     pair adds). */
  .account-toggle.toggle-group-active {
    position: fixed;
    left: 50%;
    right: auto;
    --toggle-x: calc(var(--account-nav-w) / 2 + var(--account-dock-gap) - var(--account-dock-shift));
    transform: translateX(var(--toggle-x));
    width: var(--account-toggle-w);
    height: var(--account-nav-h);
    bottom: calc(var(--bottom-nav-h) + 8px);
    z-index: 41;
    flex-direction: column;
    gap: 2px;
    padding: 4px;
    margin-bottom: 0;
    border-radius: var(--r-md);
    /* Floating over the grid now, so both bars read as solid rather than
       leaning on a blur the content behind them shows through. */
    background: var(--surface-1);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  }
  .account-nav {
    background: var(--surface-1);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  }
  .account-toggle-label {
    font-size: 0.58rem;
    letter-spacing: 0.2px;
    padding: 2px;
    border-radius: var(--r-sm);
  }

  /* A dedicated Profile tab (avatar/username/referral link/balances/Add
     Funds/Withdraw) instead of that block sitting permanently above
     whichever section you're actually looking at — Holdings, Selling,
     etc. now show *only* their own content. */
  .account-nav-item[data-group="profile"] { display: flex; }
  .account-sidebar { display: none; }
  .account-nav:has(.account-nav-item[data-group="profile"].active) ~ .account-shell .account-sidebar {
    display: flex;
  }
  .account-nav:has(.account-nav-item[data-group="profile"].active) ~ .account-shell .account-content {
    display: none;
  }
  #accountMoreBtn { display: flex; }

  /* --- Footer ----------------------------------------------------------- */
  /* Never part of the normal page flow on mobile (not even on Account) —
     tapping the ••• "More" tab opens this same element as a full-screen
     overlay instead (see the accountMoreBtn handler in app.js), so the
     brand blurb/social/support links are still reachable without eating
     permanent scroll space on every screen. */

  /* A sheet, not a takeover: there are three links, three icons and a
     blurb here, which never filled a phone screen — so it sits in the
     space between the header and the tab bar, everything centred, rather
     than stretching that little content over the whole viewport. */
  .app-footer {
    display: none;
    position: fixed;
    left: 16px;
    right: 16px;
    top: calc(var(--topbar-h) + 12px);
    bottom: calc(var(--bottom-nav-h) + 12px + env(safe-area-inset-bottom));
    z-index: 200;
    background: var(--surface-1);
    border: none;
    border-radius: var(--r-xl);
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.6);
    /* Height comes from the content, and the auto block margins centre it
       in that band — a card sized to the band would be two-thirds empty. */
    height: max-content;
    margin: auto 0;
    overflow-y: auto;
    max-width: 100%;
    padding: 24px 20px;
  }
  /* Centres the block vertically when it's shorter than the sheet, which
     it always is; the sheet still scrolls if a small screen makes it
     taller. */
  .app-footer.mobile-visible {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 24px;
  }
  /* Dims the page behind the sheet. A shadow spread past the viewport
     rather than a z-index:-1 pseudo-element: inside the sheet's own
     stacking context that pseudo painted over the sheet's background,
     which washed the whole sheet grey in light mode. */
  .app-footer.mobile-visible {
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.6), 0 0 0 100vmax rgba(0, 0, 0, 0.6);
  }

  /* Bottom centre and in flow at the end of the sheet, not the top-right
     corner: the corner is the one place a thumb can't reach without
     shifting grip. */
  .app-footer-close-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    order: 2;
    position: static;
    align-self: center;
    width: auto;
    height: auto;
    padding: 12px 32px;
    border-radius: 999px;
    background: var(--surface-2);
    border: none;
    color: var(--text);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
  }

  /* Everything centres on itself here — the desktop row of a brand block
     and two link columns pushed apart by space-between reads as lopsided
     once it's this narrow. */
  .app-footer-main {
    order: 1;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 0;
    gap: 24px;
    border-top: none;
  }
  .app-footer-brand { flex: 0 0 auto; max-width: 100%; }
  .app-footer-logo { justify-content: center; margin-bottom: 12px; }
  .app-footer-tagline { font-size: 0.72rem; }
  .app-footer-columns {
    width: 100%;
    justify-content: center;
    gap: 32px;
  }
  .app-footer-col { align-items: center; min-width: 0; }
  .app-footer-link { align-self: center; text-align: center; }
}

/* --- The slab reveal, inside this app ------------------------------------
   slab.css owns the case, the price and the stills. These are the few
   places the host app has to meet it.

   The reveal is a dark spotlight in both themes — a black scrim with a lit
   object on it — so everything inside it is lit for dark, whatever the page
   is set to. Redefining the tokens here does that in one place: the exit
   buttons, the badges and the sub-labels all read from these, and in light
   mode the Keep button would otherwise be a near-black fill sitting on a
   near-black scrim. Same reasoning as .reveal-rarity-banner above. */
.slab-reveal {
  --text: #f5f5f5;
  --text-dim: rgba(245, 245, 245, 0.55);
  --text-faint: rgba(245, 245, 245, 0.32);
  --text-inverse: #000;
  --text-inverse-dim: rgba(0, 0, 0, 0.55);
  --hairline: rgba(255, 255, 255, 0.06);
  --line: rgba(255, 255, 255, 0.14);
  --line-strong: rgba(255, 255, 255, 0.4);
  --surface-1: #131318;
  --surface-2: #1a1a20;
  --accent: #e6e6eb;
  --accent-dim: rgba(230, 230, 235, 0.16);
}

/* The badges sit between the facts line and the buttons; they were laid out
   for a card and need their own spacing now that there isn't one. */
.slab-reveal .multiplier-badge,
.slab-reveal .streak-badge {
  margin-bottom: 12px;
}
.slab-reveal .exits-grid { margin-top: 4px; }

/* A crate that's been opened shows what was in it: one card holding the
   product's photo, its price, then its name, on the same slow lean the
   reveal uses. It sits above the open box (see #screen-game .price-card),
   never over it. */
.price-card-body {
  padding: 8px 8px 10px;
  border-radius: var(--r-md);
  background: var(--surface-1);
  box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.28);
  will-change: transform;
  /* Staggered per slot so the three drift out of phase instead of marching
     in step. attachTiltRow takes over on hover and restores this after. */
  animation: slabLean 11s ease-in-out infinite alternate;
}
.box-slot:nth-child(2) .price-card-body { animation-duration: 13.5s; animation-delay: -4s; }
.box-slot:nth-child(3) .price-card-body { animation-duration: 9.5s; animation-delay: -7s; }
:root[data-theme="light"] .price-card-body { background: #fff; }
.price-card-img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
  border-radius: var(--r-sm);
  background: #fff;
}
.price-card-price {
  display: block;
  margin-top: 6px;
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.price-card-name {
  display: block;
  overflow: hidden;
  padding: 0 4px;
  font-size: 0.72rem;
  color: var(--text-dim);
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* A certificate is flat paper: a touch smaller in its card. */

@media (prefers-reduced-motion: reduce) {
  .price-card-body { animation: none; }
}

/* The reveal: the photo on a square stage, then its price, then its name. */
.slab-reveal .slab-stage { width: min(320px, 70vw); height: min(320px, 40vh); margin-bottom: 12px; }
.reveal-name {
  margin: -6px auto 6px;
  max-width: 34ch;
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
}

/* --- Light-theme colour corrections --------------------------------------
   Hues picked to carry on near-black don't all carry on beige. These are
   the same colours, darkened only where they had to be, and only here —
   dark mode keeps them exactly as they were.

   The crate hues measured 2.3-3.3:1 on a light card, worst on the small
   uppercase badges. Kept recognisably terracotta / denim / amber. */
:root[data-theme="light"] .category-tier-name.tier-name-sneakers,
:root[data-theme="light"] .tier-badge-sneakers { color: #a8511f; }
:root[data-theme="light"] .category-tier-name.tier-name-streetwear,
:root[data-theme="light"] .tier-badge-streetwear { color: #2c5fa8; }
:root[data-theme="light"] .category-tier-name.tier-name-collectibles,
:root[data-theme="light"] .tier-badge-collectibles { color: #8a6410; }
:root[data-theme="light"] .category-tier-name.tier-name-cards,
:root[data-theme="light"] .tier-badge-pokémon { color: #b02e2e; }

/* The Credits claim button carries both .exit-btn-primary and .deposit-btn.
   Primary's white-ink sub-label won on source order and put near-white text
   on the green gradient; the green button has its own dark ink for this. */
.exit-btn-primary.deposit-btn .exit-btn-sub { color: rgba(17, 42, 20, 0.62); }

/* --- Recent pulls: a watch face in the corner -----------------------------
   One prize at a time, floating over every screen. This replaced a
   scrolling list of the same feed: a list in a corner is something you
   read, and this is something you glance at.

   Desktop only — a phone already has the tab bar and the account dock in
   its bottom corners, and a third floating panel would fight both. */

.pull-dock { display: none; }

@media (min-width: 641px) {
  .pull-dock {
    /* The base rule hides it; this is the opt-in. column-reverse puts the
       header at the bottom, so the panel opens upward off it — anchored in
       the bottom corner, a panel that dropped downward would have nowhere
       to go. */
    display: flex;
    flex-direction: column-reverse;
    position: fixed;
    left: 16px;
    bottom: 16px;
    z-index: 60;
    width: 188px;
    background: var(--panel-blur);
    backdrop-filter: blur(10px);
    border-radius: var(--r-md);
    box-shadow: 0 12px 32px var(--shadow-card);
    overflow: hidden;
    touch-action: none; /* the header is a drag handle */
  }

  .pull-dock-head {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 8px 8px 8px 11px;
    color: var(--text-dim);
    font-size: 0.58rem;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    cursor: grab;
    user-select: none;
  }
  .pull-dock.is-dragging { transition: none; }
  .pull-dock.is-dragging .pull-dock-head { cursor: grabbing; }
  .pull-dock-title { flex: 1; }

  /* The one thing that says this is live rather than a stored list. */
  .pull-dock-pip {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--positive);
    animation: pullDockPip 2s ease-in-out infinite;
  }
  @keyframes pullDockPip {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.25; }
  }

  .pull-dock-min {
    display: flex;
    padding: 2px;
    background: none;
    border: none;
    color: var(--text-faint);
    cursor: pointer;
  }
  .pull-dock-min:hover { color: var(--text); }
  .pull-dock-min svg { transition: transform 0.22s ease; }

  .pull-dock-body {
    padding: 10px 10px 0;
    display: flex;
    flex-direction: column;
    gap: 7px;
  }

  /* Collapsed: the header is the whole widget. */
  .pull-dock.collapsed .pull-dock-body { display: none; }
  .pull-dock.collapsed .pull-dock-min svg { transform: rotate(-180deg); }

  /* The crate this prize came out of — a full-width action under the case
     rather than a label tucked into a corner of it, because going to the
     crate is the one thing you'd actually want to do from here. */
  .pull-dock-crate {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 8px;
    border: none;
    border-radius: var(--r-sm);
    background: var(--control-fill);
    text-align: left;
    cursor: pointer;
  }
  .pull-dock-crate:hover { background: var(--control-fill-hover); }

  /* The crate's own box, rendered by the same viewer that draws it on the
     Drops page — so the thumbnail is the actual crate, wearing its own
     product collage, not a generic icon. */
  .pull-dock-crate-box {
    width: 32px;
    height: 32px;
    flex: 0 0 auto;
    object-fit: contain;
  }

  /* One line, so it can be read rather than scanned — the crate name is
     the whole label now that the pulled-by line is gone. */
  .pull-dock-crate-name {
    flex: 1;
    min-width: 0;
    font-size: 0.84rem;
    font-weight: 700;
    letter-spacing: 0.2px;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .pull-dock-crate-arrow { flex: 0 0 auto; color: var(--text-faint); }
  .pull-dock-crate:hover .pull-dock-crate-arrow { color: var(--text); }
}

/* No bezel and no display any more: the prize is a rounded tile on the
   dock's own surface. The gold ring was doing the work of a frame around
   something that already reads as an object, and the dark screen behind a
   cut-out product shot was mostly empty. */
.pull-face { display: block; }

.pull-face-screen {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--well);
}

/* Absolutely placed so the outgoing and incoming prizes cross in the same
   space. */
.pull-face-card {
  position: absolute;
  inset: 0;
  display: block;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
}

.pull-face-card img {
  position: absolute;
  inset: 8px;
  width: calc(100% - 16px);
  height: calc(100% - 16px);
  object-fit: contain;
  /* Rounded like the frame around it (12px, less the 8px inset, plus a
     little so the curve reads at this size). */
  border-radius: var(--r-xs);
}

/* The name, not the price. A number is what you'd compare listings by;
   this is a feed of what just came out of a crate, and the thing that says
   that is what it is. */
.pull-face-name {
  display: block;
  padding: 8px 2px 0;
  font-size: 0.74rem;
  font-weight: 700;
  line-height: 1.25;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A swipe: the new prize in from the right, the last one out to the left,
   both in the same 0.5s so they cross rather than queue. No fill-mode on
   the entering card on purpose — with `both` it holds the 0-opacity `from`
   state whenever the animation hasn't run, which is what a backgrounded tab
   does, and the face would sit blank until you came back. */
.pull-face-card.is-entering { animation: pullFaceIn 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
.pull-face-card.is-leaving { animation: pullFaceOut 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards; }

@keyframes pullFaceIn {
  from { opacity: 0; transform: translateX(46%) scale(0.92); }
  to { opacity: 1; transform: none; }
}
@keyframes pullFaceOut {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateX(-46%) scale(0.92); }
}

@media (prefers-reduced-motion: reduce) {
  .pull-face-card.is-entering,
  .pull-face-card.is-leaving { animation-duration: 0.01s; }
}

/* A new tile in the carousel pops in where it lands; the rest of the row
   just shifts along. */
.recent-pull-item.is-new { animation: recentPullIn 0.32s var(--spring); }
@keyframes recentPullIn {
  from { opacity: 0; transform: scale(0.86); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .recent-pull-item.is-new { animation: none; }
}


/* ==========================================================================
   Home
   The front door: a billboard, then one band per thing the app does, each
   a way into the screen that owns it. Section titles are set in the
   wordmark's face so the page reads as one voice from the header down.
   ========================================================================== */

/* --- The billboard ------------------------------------------------------
   A light stage in both themes, on purpose: the product shots are white-
   ground photographs, and multiply against a pale tint is what lifts them
   off their rectangles into cut-outs. A dark stage would need real
   transparency the photos don't have. Its own ink for the same reason. */
.home-hero {
  --hero-tint: #eeeae2;
  --hero-accent: #16130f;
  --hero-accent2: #16130f;
  --hero-ink: #16130f;
  --hero-ink-dim: rgba(22, 19, 15, 0.68);
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  align-items: center;
  min-height: clamp(460px, 64vh, 640px);
  border-radius: var(--r-2xl);
  overflow: hidden;
  background-color: var(--hero-tint);
  transition: background-color 0.7s ease;
  isolation: isolate;
}
/* A pool of light behind the product — what makes it read as lit rather
   than pasted. */
.home-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(ellipse 48% 62% at 74% 54%, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0) 72%);
}

.home-hero-copy {
  position: relative;
  z-index: 2;
  padding: 56px 0 48px 64px;
  color: var(--hero-ink);
}
.home-hero-eyebrow {
  display: inline-block;
  margin-bottom: 14px;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.2px;
  background: linear-gradient(90deg, var(--hero-accent), var(--hero-accent2));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.home-hero-title {
  margin: 0 0 20px;
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-weight: 400;
  font-size: clamp(3.4rem, 6.6vw, 6.2rem);
  line-height: 0.94;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--hero-ink);
}
.home-hero-sub {
  max-width: 420px;
  margin: 0 0 28px;
  font-size: 1.02rem;
  line-height: 1.5;
  color: var(--hero-ink-dim);
}
.home-hero-sub b { color: var(--hero-ink); font-weight: 700; }
.home-hero-ctas { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }

/* The copy that turns over with the product fades out and back rather than
   cutting, so for a moment it says nothing instead of the wrong thing. */
.home-hero-eyebrow,
.home-hero-sub,
#homeHeroOpen {
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.home-hero.is-swapping .home-hero-eyebrow,
.home-hero.is-swapping .home-hero-sub,
.home-hero.is-swapping #homeHeroOpen {
  opacity: 0;
  transform: translateY(6px);
}

.home-hero-media {
  position: relative;
  align-self: stretch;
  min-height: inherit;
  cursor: pointer;
}
/* The crate's name, huge and faint behind the product. */
.home-hero-media::before {
  content: attr(data-word);
  position: absolute;
  right: -2%;
  bottom: -4%;
  z-index: 0;
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-size: clamp(6rem, 13vw, 12.5rem);
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--hero-accent);
  opacity: 0.07;
  transition: color 0.7s ease;
  pointer-events: none;
}
/* The show: a stage filling the media half, the crate low and centred,
   the prizes above it. Items are placed by their centre (left/top) and
   start at the crate's mouth via --from-x/--from-y (set in app.js). */
.home-hero-stage {
  position: absolute;
  inset: 4% 4% 2% 2%;
  z-index: 1;
}
.home-hero-box {
  position: absolute;
  left: 50%;
  bottom: 0;
  /* Framed for the box open (fitOpen), so it needs the wider canvas: 60%
     against the 48% it had shut keeps the flaps inside the frame and still
     draws the box itself a little bigger than before. Behind the burst
     layer: prizes come up out of the open box in front of it. */
  z-index: 1;
  width: 60%;
  /* Taller than wide: the crate sits in the bottom square, and the space
     above (HERO_BOX_HEADROOM in app.js) is where the lid swings up to. */
  aspect-ratio: 1 / 1.45;
  transform: translateX(-50%);
  transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.home-hero-box canvas { display: block; width: 100%; height: 100%; }
.home-hero-box.is-away { opacity: 0; transform: translateX(-50%) translateY(24px) scale(0.92); }
.home-hero-burst { position: absolute; inset: 0; z-index: 2; pointer-events: none; }

.hero-burst-item {
  position: absolute;
  aspect-ratio: 1;
  translate: -50% -50%;
  opacity: 0;
  transform: translate(var(--from-x), var(--from-y)) scale(0.12) rotate(0deg);
  will-change: transform, opacity;
}
.hero-burst-item img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 18px 22px rgba(22, 19, 15, 0.22));
}
/* Out: an arc up out of the box with a little overshoot, then a slow bob
   on the image so the group never sits dead still. */
.hero-burst-item.is-out {
  animation: heroBurstOut 1.15s var(--spring) var(--d) both;
}
.hero-burst-item.is-out img {
  animation: heroBob var(--bob) ease-in-out calc(var(--d) + 0.9s) infinite;
}
/* In: back down into the box, quicker than they came out. */
.hero-burst-item.is-in {
  opacity: 1;
  transform: none;
  rotate: var(--r);
  animation: heroBurstIn 0.45s cubic-bezier(0.5, 0, 0.75, 0) var(--d) forwards;
}
/* Up out of the box first — from its open mouth, fading in as it clears
   the flaps, straight up to just above the rim — then out to its place
   with a little overshoot. */
@keyframes heroBurstOut {
  0% { opacity: 0; transform: translate(var(--from-x), var(--from-y)) scale(0.3) rotate(0deg); }
  14% { opacity: 1; }
  38% { opacity: 1; transform: translate(var(--from-x), var(--rise-y)) scale(0.62) rotate(0deg); }
  100% { opacity: 1; transform: none; rotate: var(--r); }
}
@keyframes heroBurstIn {
  from { opacity: 1; transform: none; }
  60% { opacity: 1; transform: translate(var(--from-x), var(--rise-y)) scale(0.62); }
  to { opacity: 0; transform: translate(var(--from-x), var(--from-y)) scale(0.3); }
}
@keyframes heroBob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-9px) rotate(1.5deg); }
}
.home-hero-media:hover .home-hero-stage { transform: scale(1.02); }
.home-hero-stage { transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1); }
@media (prefers-reduced-motion: reduce) {
  .hero-burst-item.is-out { animation: none; opacity: 1; transform: none; rotate: var(--r); }
  .hero-burst-item.is-out img { animation: none; }
}

/* Progress bars, not dots: each one fills while its slide is up, and the
   fill ending is what turns the page (see buildHomeHero). */
.home-hero-dots { display: flex; gap: 8px; margin-top: 40px; }
.home-hero-dot {
  position: relative;
  width: 44px;
  height: 20px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
}
.home-hero-dot::before,
.home-hero-dot-fill {
  position: absolute;
  left: 0;
  top: 8px;
  height: 4px;
  border-radius: var(--r-pill);
}
.home-hero-dot::before { content: ""; right: 0; background: rgba(22, 19, 15, 0.14); }
.home-hero-dot-fill { width: 0; background: var(--hero-ink); }
.home-hero-dot.is-active .home-hero-dot-fill { animation: homeHeroFill 9s linear forwards; } /* HERO_SLIDE_MS */
@keyframes homeHeroFill {
  from { width: 0; }
  to { width: 100%; }
}

/* --- Buttons ------------------------------------------------------------ */
.home-btn {
  padding: 14px 24px;
  border: none;
  border-radius: 999px;
  font: inherit;
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: 0.2px;
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease, opacity 0.15s ease;
}
.home-btn:hover { transform: translateY(-2px); }
.home-btn-solid { background: var(--text); color: var(--text-inverse); }
.home-btn-ghost { background: transparent; color: var(--text); }
.home-btn-ghost::after { content: " \203A"; }
/* On the billboard the ink is the stage's, not the theme's. */
.home-hero .home-btn-solid { background: var(--hero-ink); color: #fff; }
.home-hero .home-btn-ghost { color: var(--hero-ink); }
.home-btn-inverse { background: var(--text-inverse); color: var(--text); }

/* --- Section heads ------------------------------------------------------ */
.home-block { margin-top: 64px; }
.home-block-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}
.home-block-title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-weight: 400;
  font-size: 2rem;
  line-height: 1.05;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text);
}
.home-block-sub { margin: 6px 0 0; font-size: 0.88rem; color: var(--text-dim); }
.home-more {
  flex: 0 0 auto;
  padding: 9px 16px;
  border: none;
  border-radius: 999px;
  background: var(--control-fill);
  color: var(--text);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.15s ease;
}
.home-more:hover { background: var(--control-fill-hover); }
.home-more::after { content: " \2192"; }

.home-live-pip {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #22c55e;
  animation: homeLive 1.8s ease-out infinite;
}
@keyframes homeLive {
  0% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.5); }
  100% { box-shadow: 0 0 0 10px rgba(34, 197, 94, 0); }
}

/* White wells for the product shots in both themes: the photos are shot on
   white, so a white tile is the one ground they sit on without an edge. */
.home-crate-thumbs img,
.home-grail-media,
.home-market-thumb,
.home-step-choices #homeStepItem { background: #fff; }

/* --- Crates ------------------------------------------------------------- */
.home-crates {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}
.home-crate {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px;
  border-radius: var(--r-lg);
  background: var(--surface-1);
  cursor: pointer;
  transition: transform 0.2s ease;
}
.home-crate:hover { transform: translateY(-4px); }
.home-crate-stage {
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-md);
}
.home-crate-box {
  display: block;
  width: 100%;
  height: 100%;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
.home-crate:hover .home-crate-box { transform: scale(1.05); }
.home-crate-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.home-crate .category-tier-name { font-size: 1.2rem; }
.home-crate-price { font-size: 1.1rem; font-weight: 800; color: var(--text); }
.home-crate-top { font-size: 0.78rem; color: var(--text-dim); }
.home-crate-top b { color: var(--text); }
.home-crate-thumbs { display: flex; gap: 6px; }
.home-crate-thumbs img {
  width: 44px;
  height: 44px;
  padding: 3px;
  border-radius: var(--r-sm);
  object-fit: contain;
}
.home-crate-open { width: 100%; margin-top: auto; }

/* --- Grails: two bentos, the big tile swapping sides ----------------------- */
.home-grails {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: minmax(250px, auto);
  grid-auto-flow: dense;
  gap: 16px;
}
.home-grail:nth-child(1) { grid-column: 1 / span 2; grid-row: span 2; }
.home-grail:nth-child(6) { grid-column: 3 / span 2; grid-row: span 2; }
.home-grail {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 12px;
  border: none;
  border-radius: var(--r-lg);
  background: var(--surface-1);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 0.2s ease;
}
.home-grail:hover { transform: translateY(-4px); }
.home-grail-media {
  flex: 1;
  display: grid;
  place-items: center;
  min-height: 150px;
  border-radius: var(--r-md);
  overflow: hidden;
}
.home-grail-media img {
  width: 84%;
  height: 84%;
  max-height: 100%;
  object-fit: contain;
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.home-grail:hover .home-grail-media img { transform: scale(1.07); }
.home-grail-info { display: flex; flex-direction: column; gap: 6px; padding: 12px 4px 4px; }
.home-grail-info .tier-badge { align-self: flex-start; margin: 0; }
.home-grail-name {
  overflow: hidden;
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  text-overflow: ellipsis;
}
.home-grail-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.home-grail-foot b { font-size: 1.05rem; color: var(--text); }
.home-grail-foot span { font-size: 0.7rem; color: var(--text-dim); text-align: right; }
/* The two big tiles get the big number. */
.home-grail:nth-child(1) .home-grail-name,
.home-grail:nth-child(6) .home-grail-name { font-size: 1.1rem; white-space: normal; }
.home-grail:nth-child(1) .home-grail-foot b,
.home-grail:nth-child(6) .home-grail-foot b {
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-weight: 400;
  font-size: 2rem;
  letter-spacing: 0.5px;
}

/* --- Live pulls ---------------------------------------------------------- */
.home-pulls .recent-pull-item { width: 184px; border-radius: var(--r-md); }
.home-pulls .recent-pull-price { color: var(--positive); }
.home-pulls .recent-pull-item img { width: 128px; height: 128px; background: #fff; border-radius: var(--r-sm); }

/* --- How it works --------------------------------------------------------- */
.home-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.home-step { padding: 16px 16px 26px; border-radius: var(--r-xl); background: var(--surface-1); }
.home-step-visual {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  margin-bottom: 20px;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--surface-2);
}
.home-step-visual img { max-width: 72%; max-height: 84%; object-fit: contain; }
#homeStepSlab { max-height: 94%; filter: drop-shadow(0 14px 20px rgba(0, 0, 0, 0.22)); }
.home-step-num {
  display: block;
  padding: 0 8px;
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-size: 2.4rem;
  line-height: 1;
  color: var(--text-faint);
}
.home-step h3 { margin: 6px 8px 8px; font-size: 1.15rem; font-weight: 800; color: var(--text); }
.home-step p { margin: 0 8px; font-size: 0.86rem; line-height: 1.55; color: var(--text-dim); }

.home-step-choices #homeStepItem { width: 50%; padding: 8px; border-radius: var(--r-md); }
.home-choice {
  position: absolute;
  padding: 7px 12px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 800;
  color: #fff;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.16);
}
.home-choice-keep { left: 7%; top: 16%; background: var(--text); color: var(--text-inverse); }
.home-choice-ship { right: 6%; top: 44%; background: #2c5fa8; }
.home-choice-sell { left: 10%; bottom: 13%; background: #15803d; }

/* --- Leaderboard + market ----------------------------------------------- */
.home-duo {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-top: 64px;
}
.home-panel { min-width: 0; padding: 24px; border-radius: var(--r-xl); background: var(--surface-1); }
.home-panel .home-block-head { margin-bottom: 14px; }
.home-panel .home-block-title { font-size: 1.5rem; }

.home-board, .home-market { display: flex; flex-direction: column; gap: 4px; }
.home-board-row,
.home-market-row {
  border: none;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s ease;
}
.home-board-row:hover, .home-market-row:hover { background: var(--hover-bg); }

.home-board-row {
  display: grid;
  grid-template-columns: 30px 32px minmax(0, 1fr) 84px 84px;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
}
.home-board-row.you { background: var(--accent-dim); }
.home-board-row.gap { margin-top: 12px; }
.home-board-rank {
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-size: 1.25rem;
  text-align: center;
  color: var(--text-faint);
}
.home-board-rank.rank-1 { color: var(--gold); }
.home-board-rank.rank-2 { color: #8e959e; }
.home-board-rank.rank-3 { color: #b0683a; }
.home-board-avatar { width: 32px; height: 32px; font-size: 0.8rem; }
.home-board-name {
  overflow: hidden;
  font-size: 0.9rem;
  font-weight: 700;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.home-board-bar { height: 6px; border-radius: var(--r-pill); background: var(--control-fill); overflow: hidden; }
.home-board-bar i { display: block; height: 100%; border-radius: inherit; background: var(--text); opacity: 0.75; }
.home-board-xp {
  font-size: 0.78rem;
  color: var(--text-dim);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.home-market-row { display: flex; align-items: center; gap: 12px; padding: 8px; }
.home-market-thumb {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 52px;
  height: 52px;
  border-radius: var(--r-sm);
  overflow: hidden;
}
.home-market-thumb img { width: 88%; height: 88%; object-fit: contain; }
.home-market-text { display: flex; flex-direction: column; gap: 5px; flex: 1; min-width: 0; }
.home-market-name {
  overflow: hidden;
  font-size: 0.86rem;
  font-weight: 700;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.home-market-meta { display: flex; align-items: center; gap: 6px; min-width: 0; }
.home-market-meta .market-item-fmv,
.home-market-meta .market-item-size { margin: 0; }
.home-market-seller {
  overflow: hidden;
  font-size: 0.7rem;
  color: var(--text-dim);
  white-space: nowrap;
  text-overflow: ellipsis;
}
.home-market-price { font-size: 0.98rem; font-weight: 800; font-variant-numeric: tabular-nums; }

/* --- Closing band ---------------------------------------------------------
   The theme's ink as the ground: dark on the light theme, light on the
   dark one, so the last thing on the page always inverts what came before
   it. */
.home-cta {
  margin-top: 64px;
  padding: 64px 32px;
  border-radius: var(--r-2xl);
  background: var(--text);
  color: var(--text-inverse);
  text-align: center;
}
.home-cta-title {
  margin: 0 0 12px;
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-weight: 400;
  font-size: clamp(2.2rem, 4.6vw, 3.8rem);
  line-height: 1;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.home-cta-sub { margin: 0 0 28px; font-size: 1rem; color: var(--text-inverse-dim); }

@media (prefers-reduced-motion: reduce) {
  .home-hero-dot.is-active .home-hero-dot-fill { animation: none; width: 100%; }
  .home-live-pip { animation: none; }
}

/* Between desktop and phone the four-across rows get cramped first. */
@media (max-width: 1000px) and (min-width: 641px) {
  .home-hero-copy { padding: 44px 0 40px 40px; }
  .home-crates { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .home-board-row { grid-template-columns: 26px 30px minmax(0, 1fr) 80px; }
  .home-board-bar { display: none; }
}

@media (max-width: 640px) {
  .home-hero { grid-template-columns: 1fr; min-height: 0; border-radius: var(--r-2xl); }
  .home-hero::before { background: radial-gradient(ellipse 70% 40% at 50% 26%, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0) 72%); }
  .home-hero-media { order: -1; height: 290px; min-height: 0; }
  .home-hero-media::before { font-size: 6.5rem; right: 50%; transform: translateX(50%); bottom: 0; }
  .home-hero-media { height: 340px; }
  .home-hero-stage { inset: 2% 3% 0; }
  .home-hero-box { width: 58%; }
  .home-hero-copy { padding: 4px 22px 26px; }
  .home-hero-eyebrow { font-size: 0.92rem; margin-bottom: 10px; }
  .home-hero-title { font-size: 3.1rem; margin-bottom: 14px; }
  .home-hero-sub { font-size: 0.9rem; margin-bottom: 20px; }
  .home-hero-dots { margin-top: 22px; }
  .home-btn { padding: 12px 20px; font-size: 0.8rem; }
  /* It wraps under the solid button here; flush left so the two line up. */
  .home-btn-ghost { padding-left: 2px; }


  .home-block { margin-top: 44px; }
  .home-block-head { margin-bottom: 14px; }
  .home-block-title { font-size: 1.5rem; }
  .home-block-sub { font-size: 0.8rem; }
  .home-more { padding: 8px 12px; font-size: 0.72rem; }

  .home-crates { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .home-crate { padding: 12px; border-radius: var(--r-lg); gap: 8px; }
  .home-crate .category-tier-name { font-size: 1rem; }
  .home-crate-price { font-size: 0.95rem; }
  .home-crate-thumbs img { width: 34px; height: 34px; }

  .home-grails { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: auto; gap: 10px; }
  .home-grail:nth-child(1),
  .home-grail:nth-child(6) { grid-column: 1 / -1; grid-row: auto; }
  .home-grail { padding: 10px; border-radius: var(--r-lg); }
  .home-grail-media { aspect-ratio: 1; min-height: 0; flex: 0 0 auto; }
  .home-grail:nth-child(1) .home-grail-media,
  .home-grail:nth-child(6) .home-grail-media { aspect-ratio: 4 / 3; }
  .home-grail-foot { flex-direction: column; align-items: flex-start; gap: 2px; }
  .home-grail-foot span { text-align: left; }

  .home-pulls .recent-pull-item { width: 150px; }
  .home-pulls .recent-pull-item img { width: 104px; height: 104px; }

  .home-steps { grid-template-columns: 1fr; gap: 10px; }

  .home-duo { grid-template-columns: 1fr; gap: 10px; margin-top: 44px; }
  .home-panel { padding: 16px; border-radius: var(--r-xl); }
  .home-board-row { grid-template-columns: 24px 30px minmax(0, 1fr) 74px; gap: 10px; padding: 8px 6px; }
  .home-board-bar { display: none; }

  .home-cta { margin-top: 44px; padding: 44px 20px; border-radius: var(--r-2xl); }
}

/* --- Ship: checkout form + order tracker ---------------------------------- */
.ship-modal-card {
  max-width: 520px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  padding: 28px;
  text-align: left;
  border-color: var(--hairline);
}
.ship-close-btn { position: absolute; top: 18px; right: 22px; margin: 0; }

.ship-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-right: 56px;
  margin-bottom: 20px;
}
.ship-item img {
  width: 64px;
  height: 64px;
  flex: 0 0 auto;
  object-fit: contain;
  padding: 4px;
  border-radius: var(--r-xs);
  background: #fff;
}
.ship-item-name { display: block; font-size: 0.9rem; font-weight: 700; color: var(--text); line-height: 1.3; }
.ship-item-meta { display: block; margin-top: 4px; font-size: 0.72rem; color: var(--text-dim); }

.ship-title { margin: 0 0 14px; font-size: 1rem; font-weight: 700; color: var(--text); }
.ship-title span { color: var(--text-dim); font-weight: 600; }

.ship-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
.ship-span-2 { grid-column: 1 / -1; }
.ship-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.4px;
  color: var(--text-dim);
}
.ship-optional { font-weight: 400; color: var(--text-faint); }
.ship-field input,
.ship-field select {
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-sm);
  background: var(--control-fill);
  color: var(--text);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0;
}
.ship-field input:focus,
.ship-field select:focus { outline: none; border-color: var(--text-dim); }
.ship-field .invalid { border-color: var(--negative); }

.ship-save {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  font-size: 0.74rem;
  color: var(--text-dim);
  cursor: pointer;
}
.ship-error { margin: 12px 0 0; font-size: 0.74rem; color: var(--negative); }

/* Tracker: a vertical timeline, the line filling up to the current step. */
.ship-status-line { margin: -6px 0 18px; font-size: 0.8rem; color: var(--text-dim); }
.ship-steps { list-style: none; margin: 0 0 20px; padding: 0; }
.ship-step {
  position: relative;
  display: grid;
  grid-template-columns: 22px 1fr;
  column-gap: 12px;
  padding-bottom: 18px;
}
.ship-step:last-child { padding-bottom: 0; }
.ship-step::before {
  content: "";
  position: absolute;
  left: 10px;
  top: 20px;
  bottom: -2px;
  width: 2px;
  background: var(--hairline);
}
.ship-step:last-child::before { display: none; }
.ship-step.done::before { background: var(--positive); }
.ship-step-dot {
  grid-row: span 2;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--hairline);
  background: var(--surface-1);
  box-sizing: border-box;
}
.ship-step.done .ship-step-dot { background: var(--positive); border-color: var(--positive); }
.ship-step.current .ship-step-dot {
  border-color: var(--positive);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--positive) 22%, transparent);
  animation: ship-pulse 1.6s ease-in-out infinite;
}
@keyframes ship-pulse {
  50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--positive) 8%, transparent); }
}
.ship-step-label { font-size: 0.86rem; font-weight: 700; color: var(--text); line-height: 22px; }
.ship-step.todo .ship-step-label { color: var(--text-faint); font-weight: 600; }
.ship-step-time { font-size: 0.7rem; color: var(--text-dim); }
.ship-step.todo .ship-step-time { color: var(--text-faint); }

.ship-address {
  padding: 14px 16px;
  border-radius: var(--r-sm);
  background: var(--control-fill);
  margin-bottom: 20px;
}
.ship-address-label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}
.ship-address p { margin: 0; font-size: 0.8rem; line-height: 1.5; color: var(--text); }
.ship-done-btn { width: 100%; flex: none; }
.activity-row[data-shipment] { cursor: pointer; }

@media (max-width: 640px) {
  .ship-modal-card { padding: 22px 18px; }
  /* 16px or iOS zooms the page in on focus. */
  .ship-field input,
  .ship-field select { font-size: 16px; }
  .ship-grid { grid-template-columns: 1fr; }
  .ship-item img { width: 52px; height: 52px; }
}
@media (prefers-reduced-motion: reduce) {
  .ship-step.current .ship-step-dot { animation: none; }
}

/* --- Picking screen scale -------------------------------------------------
   The reel and the three crates are sized from one number, --slot, that
   grows with the viewport (it was a fixed 190px, which left the crates
   small in a lot of empty screen). Everything that has to line up with a
   crate (the reel's height and width, the gaps, the slab that pops out of
   an opened crate and how far it rises) is a fraction of it, so the reel
   still hands off to the crates at the same height and size. */
#screen-game {
  --slot: clamp(190px, min(24vw, 36vh), 320px);
}
#screen-game .reel {
  height: var(--slot);
  max-width: calc(var(--slot) * 3 + var(--slot) * 0.26);
  margin-top: calc(var(--slot) * 0.42);
}
#screen-game .box-row {
  column-gap: calc(var(--slot) * 0.13);
  padding-top: calc(var(--slot) * 0.42);
}
#screen-game .box-slot { width: var(--slot); }
#screen-game .box-canvas { width: var(--slot); height: var(--slot); }
/* The card stands on the open box rather than over it: its bottom edge is
   pinned just above the flaps' tips (about 30% down the box's canvas). */
#screen-game .price-card {
  top: auto;
  bottom: calc(100% - var(--slot) * 0.28 + 10px);
  width: calc(var(--slot) * 0.58);
  filter: none;
  transform: translate(-50%, 16px) scale(0.82);
  transform-origin: 50% 100%;
}
#screen-game .box-slot.open .price-card { transform: translate(-50%, 0) scale(1); }
@media (max-width: 640px) {
  /* Three across, filling the width between the 16px gutters. */
  #screen-game { --slot: min(150px, calc((100vw - 48px) / 3)); }
  #screen-game .box-row { column-gap: 8px; padding-top: calc(var(--slot) * 0.54); }
  #screen-game .reel { max-width: calc(var(--slot) * 3 + 16px); margin-top: calc(var(--slot) * 0.54); }
  #screen-game .price-card { width: calc(var(--slot) * 0.86); }
  #screen-game .price-card-body { padding: 5px 5px 7px; }
  #screen-game .price-card-price { font-size: 0.82rem; margin-top: 4px; }
  #screen-game .price-card-name { font-size: 0.6rem; }
}

/* --- Pinned page headers (desktop) ---------------------------------------
   Market: the title row stays under the top bar and the filters pin below
   it; only the grid scrolls. Account: the tab bar and the profile sidebar
   stay, the My Items/Portfolio switch pins under the tab bar, and only
   the section content scrolls. Each pinned strip carries a band of page
   colour over the gap above it, so cards scrolling up disappear behind it
   instead of showing through. --market-head-h and --acct-nav-h are
   measured in app.js. */
@media (min-width: 641px) {
  /* Where main's content starts (top bar + main's 32px top padding), so
     the pinned strips stick exactly where they already sit and never
     shift at all. */
  :root { --pin-top: calc(var(--topbar-h) + 32px); }
  .market-title-row {
    position: sticky;
    top: var(--pin-top);
    z-index: 12;
    display: flex;
    align-items: center;
    margin: 0 0 4px;
    padding: 0 0 12px;
    background: var(--bg);
  }
  .market-title-row .screen-title { margin-bottom: 0; }
  .market-title-row::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: 34px;
    background: var(--bg);
  }
  .market-filters {
    top: calc(var(--pin-top) + var(--market-head-h, 52px) + 4px);
    max-height: calc(100vh - var(--pin-top) - var(--market-head-h, 52px) - 24px);
    overflow-y: auto;
  }

  /* The strip's own fill moves to ::after so ::before can sit under it
     as a square band of page colour: from the top bar down to the next
     pinned piece. Its rounded corners then have page behind them, not
     whatever is scrolling past. Both pseudo-elements sit at z-index -1
     inside the strip's own stacking context: behind its buttons, in
     front of the page. */
  .account-nav {
    top: var(--pin-top);
    margin-bottom: 10px;
    background: none;
    backdrop-filter: none;
  }
  .account-nav::before,
  .account-nav::after,
  .account-toggle.toggle-group-active::before,
  .account-toggle.toggle-group-active::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    z-index: -1;
    pointer-events: none;
  }
  .account-nav::before { top: -34px; bottom: -10px; background: var(--bg); }
  .account-nav::after { inset: 0; border-radius: var(--r-pill); background: var(--surface-1); }
  .account-sidebar {
    top: var(--pin-top);
    max-height: calc(100vh - var(--pin-top) - 16px);
    overflow-y: auto;
    scrollbar-width: none;
  }
  .account-sidebar::-webkit-scrollbar { display: none; }

  .account-toggle.toggle-group-active {
    position: sticky;
    top: calc(var(--pin-top) + var(--acct-nav-h, 50px) + 10px);
    z-index: 9;
    margin-bottom: 16px;
    background: none;
  }
  .account-toggle.toggle-group-active::before { top: -10px; bottom: -16px; background: var(--bg); }
  .account-toggle.toggle-group-active::after { inset: 0; border-radius: 999px; background: var(--surface-2); }
}

/* --- Recent pulls dock: special pulls ------------------------------------
   Rare and up: the frame is outlined in its rarity colour, and the whole
   face shakes briefly once the new card has swiped in (0.5s). Legendary
   shakes harder. */
.pull-face { position: relative; border-radius: var(--r-sm); transition: box-shadow 0.4s ease; }
.pull-face.is-special { box-shadow: 0 0 0 2px var(--rarity-color); }
/* Over the photo, not under it: the product shots are on solid white, so a
   glow behind them only showed in the margin. An inset shadow laid over
   the edges tints the shot's own border instead. */
.pull-face-card.is-special::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: var(--r-sm);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--rarity-color) 60%, transparent),
              inset 0 0 26px 2px color-mix(in srgb, var(--rarity-color) 50%, transparent);
  pointer-events: none;
}
.pull-face.is-shaking { animation: pullShake 0.62s cubic-bezier(0.36, 0.07, 0.19, 0.97) 0.45s both; }
.pull-face.is-legendary.is-shaking { animation: pullShakeBig 0.8s cubic-bezier(0.36, 0.07, 0.19, 0.97) 0.45s both; }
@keyframes pullShake {
  10%, 90% { transform: translateX(-1px) rotate(-0.6deg); }
  20%, 80% { transform: translateX(2px) rotate(0.8deg); }
  30%, 50%, 70% { transform: translateX(-3px) rotate(-1.2deg); }
  40%, 60% { transform: translateX(3px) rotate(1.2deg); }
}
@keyframes pullShakeBig {
  10%, 90% { transform: translateX(-2px) rotate(-1deg) scale(1.02); }
  20%, 80% { transform: translateX(3px) rotate(1.4deg) scale(1.03); }
  30%, 50%, 70% { transform: translateX(-4px) rotate(-2deg) scale(1.04); }
  40%, 60% { transform: translateX(4px) rotate(2deg) scale(1.04); }
}
@media (prefers-reduced-motion: reduce) {
  .pull-face.is-shaking,
  .pull-face.is-legendary.is-shaking { animation: none; }
}

/* Try Again sat flush under the "Your Box/Stock" caption on desktop;
   give it room so it reads as the next step, not part of the caption.
   (Phones already have their own 32px, set in the mobile block.) */
@media (min-width: 641px) {
  #playAgainBtn { margin-top: 44px; }
}

/* Phones: Market's title row pins under the header too, as on desktop.
   (Account already keeps its section bar fixed at the bottom on phones.) */
@media (max-width: 640px) {
  .market-title-row {
    position: sticky;
    top: calc(var(--topbar-h) + 16px);
    z-index: 12;
    padding-bottom: 12px;
    margin-bottom: 4px;
    background: var(--bg);
  }
  .market-title-row::before {
    content: "";
    position: absolute;
    left: -16px;
    right: -16px;
    bottom: 100%;
    height: 18px;
    background: var(--bg);
  }
  .market-title-row::after {
    content: "";
    position: absolute;
    left: -16px;
    right: -16px;
    top: 0;
    bottom: 0;
    z-index: -1;
    background: var(--bg);
  }
}

/* Recent / Live pulls strips: Rare and up get a clean outline in their
   rarity's colour (no glow), and a special one arriving pops in with a
   short shake. Inset, so the strip's scrolling viewport never clips it. */
.recent-pull-item.is-special { box-shadow: inset 0 0 0 2px var(--rarity-color); }
.recent-pull-item.is-special.is-new {
  animation: recentPullIn 0.32s var(--spring),
             pullShake 0.6s cubic-bezier(0.36, 0.07, 0.19, 0.97) 0.35s;
}
@media (prefers-reduced-motion: reduce) {
  .recent-pull-item.is-special.is-new { animation: none; }
}

/* Grails wall: a tile turns edge-on, swaps to another grail at the
   midpoint (app.js), and turns back, with a slight lift so it reads as a
   card being flipped rather than a fade. */
.home-grails { perspective: 1400px; }
.home-grail.is-flipping {
  animation: grailFlip 0.66s cubic-bezier(0.45, 0, 0.2, 1);
  pointer-events: none;
}
@keyframes grailFlip {
  0% { transform: rotateY(0deg) scale(1); }
  50% { transform: rotateY(90deg) scale(0.96); }
  50.01% { transform: rotateY(-90deg) scale(0.96); }
  100% { transform: rotateY(0deg) scale(1); }
}
/* The incoming image (inserted at the swap) settles in with a small pop. */
.home-grail.is-flipping .home-grail-media img { animation: grailPop 0.45s var(--spring); }
@keyframes grailPop {
  0% { transform: scale(0.88); opacity: 0.4; }
  100% { transform: scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .home-grail.is-flipping, .home-grail.is-flipping .home-grail-media img { animation: none; }
}

/* --- Drops: title + line filter ------------------------------------------ */
.drops-head { display: flex; }
.drops-head .screen-title { margin-bottom: 0; }
.drop-lines { display: flex; flex-wrap: wrap; gap: 6px; }
.drop-line {
  padding: 7px 14px;
  border: none;
  border-radius: 999px;
  background: var(--control-fill);
  color: var(--text-dim);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.drop-line span { margin-left: 4px; opacity: 0.55; font-weight: 700; }
.drop-line:hover { color: var(--text); background: var(--control-fill-hover); }
.drop-line.active { background: var(--text); color: var(--text-inverse); }
.drop-line.active span { opacity: 0.7; }
/* A single crate's page has its own back button; the filter would just
   be noise there. */
body.drop-detail-open .drop-lines { display: none; }
@media (max-width: 640px) {
  .drops-head { gap: 10px; margin-bottom: 16px; }
  /* align-self: stretch — the head is a column that sizes children to
     their content, so without it this row took its full 484px and pushed
     the whole page sideways instead of scrolling inside itself. */
  .drop-lines { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin: 0 -16px; padding: 0 16px; align-self: stretch; min-width: 0; }
  .drop-lines::-webkit-scrollbar { display: none; }
  .drop-line { flex: 0 0 auto; }
}

/* --- Drops: page header, tabs, and a titled section per line ------------
   Header: title and a line under it, then the tab row (All Packs + one
   per line) on its own row. On All Packs each line gets a heading that
   spans the grid: its name in its colour, a line about it, the pack count,
   and View all. */
.drops-head { flex-direction: column; align-items: flex-start; gap: 16px; margin-bottom: 28px; }
.drop-line { padding: 9px 16px; font-size: 0.78rem; }
.drop-section-head {
  grid-column: 1 / -1;
  display: flex;
  align-items: flex-end;
  gap: 12px;
  padding: 4px 2px 0;
}
.drop-section-head:not(:first-child) { margin-top: 24px; }
.drop-section-head > div { flex: 1; min-width: 0; }
.drop-section-title { margin: 0; font-size: 1.35rem; font-weight: 800; letter-spacing: 0.2px; }
.drop-section-sub { margin: 4px 0 0; font-size: 0.8rem; color: var(--text-dim); }
.drop-section-count {
  flex: 0 0 auto;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--control-fill);
  color: var(--text-dim);
  font-size: 0.68rem;
  font-weight: 700;
}
.drop-section-more {
  flex: 0 0 auto;
  border: none;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  padding: 4px 0;
}
.drop-section-more:hover { text-decoration: underline; }
body.drop-detail-open .drop-section-head { display: none; }
@media (max-width: 640px) {
  .drops-head { gap: 12px; margin-bottom: 18px; }
  .drop-section-head { flex-wrap: wrap; gap: 6px 10px; }
  .drop-section-head:not(:first-child) { margin-top: 16px; }
  .drop-section-title { font-size: 1.1rem; }
  .drop-section-sub { font-size: 0.72rem; }
}

/* All Drops: ten crates, one run by price. Five across (two full rows) on
   a desktop, two across below that, so no row is left half empty. */
.category-list.is-all { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 14px; }
.category-list.is-all .category-card { padding-left: 14px; padding-right: 14px; }
.category-list.is-all .category-box-canvas { width: 140px; height: 140px; }
@media (max-width: 1100px) {
  .category-list.is-all { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .category-list.is-all .category-box-canvas { width: 165px; height: 165px; }
}
@media (max-width: 640px) {
  .category-list.is-all { gap: 8px; }
  .category-list.is-all .category-box-canvas { width: 92px; height: 92px; }
  .category-list.is-all .category-card { padding: 16px 8px; }
}
body.drop-detail-open .category-list.is-all { grid-template-columns: minmax(0, 1fr); }

/* --- Drops: the same soft shapes as Home ---------------------------------
   Home's cards are 20px-round and its buttons are pills; Drops was still
   on 4px corners. Same card radius, pill buttons, rounder inner panels. */
.category-card { border-radius: var(--r-lg); }
.category-open-btn {
  border-radius: 999px;
  padding: 13px 0;
  font-size: 0.84rem;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: none;
}
.prize-dropdown { border-radius: var(--r-lg); }
.odds-bucket { border-radius: var(--r-sm); }
.pity-bar-track, .pity-bar-fill { border-radius: 999px; }
@media (max-width: 640px) {
  .category-card { border-radius: var(--r-lg); }
  .prize-dropdown { border-radius: var(--r-lg); }
}

/* --- Recent pulls on phones: an app-icon tile ----------------------------
   Desktop's dock is a panel; a phone has no room for one, so here it's
   just the prize tile, app-icon sized, parked bottom-left over the tab
   bar. The newest pull swipes through it (and a Rare+ one still glows and
   shakes); tapping it opens that pull. It ducks out of the way while the
   page is scrolling and comes back a moment after you stop, and isn't
   shown at all while a drop is being opened. */
@media (max-width: 640px) {
  .pull-dock {
    display: block;
    position: fixed;
    left: 14px !important;
    right: auto;
    bottom: calc(var(--bottom-nav-h) + 14px + env(safe-area-inset-bottom)) !important;
    z-index: 60;
    width: 64px;
    padding: 0;
    background: none;
    transition: opacity 0.25s ease 0.5s, transform 0.3s cubic-bezier(0.22, 1, 0.36, 1) 0.5s;
  }
  .pull-dock-head,
  .pull-face-name,
  .pull-dock-crate { display: none; }
  .pull-dock-body,
  .pull-dock.collapsed .pull-dock-body { display: block; padding: 0; }
  .pull-face {
    border-radius: var(--r-md);
    background: var(--surface-1);
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.18), 0 0 0 1px var(--hairline);
  }
  .pull-face.is-special {
    box-shadow: 0 0 0 2px var(--rarity-color), 0 8px 22px rgba(0, 0, 0, 0.18);
  }
  .pull-face-screen { border-radius: var(--r-md); }
  .pull-face-card img { inset: 5px; width: calc(100% - 10px); height: calc(100% - 10px); border-radius: var(--r-xs); }
  /* A live dot, so it reads as a feed and not a stray thumbnail. */
  .pull-face::after {
    content: "";
    position: absolute;
    top: -3px;
    right: -3px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #22c55e;
    box-shadow: 0 0 0 2px var(--bg);
    animation: pullDockLive 1.8s ease-in-out infinite;
  }
  @keyframes pullDockLive { 50% { transform: scale(0.75); opacity: 0.6; } }

  /* Out of the way: while scrolling (quick), back after a pause (above). */
  body.is-scrolling .pull-dock {
    opacity: 0;
    transform: translateY(12px) scale(0.85);
    pointer-events: none;
    transition: opacity 0.15s ease, transform 0.2s ease;
  }
  /* Not while a drop is being opened. */
  body:has(#screen-game.active) .pull-dock { display: none; }
  /* Account has its own floating bars along the bottom: sit above them. */
  body:has(#screen-account.active) .pull-dock {
    bottom: calc(var(--bottom-nav-h) + 86px + env(safe-area-inset-bottom)) !important;
  }
}
@media (max-width: 640px) and (prefers-reduced-motion: reduce) {
  .pull-face::after { animation: none; }
}

/* --- Pop-ups: the same soft shapes as Home and Drops ---------------------
   Every pop-up card (market listing, recent pull, vault item, payment,
   amount, ship, withdraw...) takes a 24px corner, its buttons are pills,
   and the pieces inside are rounded to match. */
.prize-modal-card { border-radius: var(--r-xl); }
.detail-modal-card { border-radius: var(--r-xl); }
.modal-btn { border-radius: 999px; }
.payment-option { border-radius: var(--r-md); }
.offer-row { border-radius: var(--r-sm); }
.amount-input { border-radius: var(--r-sm); }
.exit-btn { border-radius: var(--r-md); }
@media (max-width: 640px) {
  .prize-modal-card, .detail-modal-card { border-radius: var(--r-xl); }
}

/* --- Credits explainer ---------------------------------------------------- */
.credits-info-card { max-width: 400px; text-align: left; padding: 28px; }
.credits-info-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: 0 auto 12px;
  border-radius: var(--r-sm);
  background: linear-gradient(135deg, #5eead4, #16a34a);
  color: #04160c;
  box-shadow: 0 6px 16px -6px rgba(22, 163, 74, 0.6);
}
.credits-info-card .payment-modal-title { text-align: center; margin-bottom: 6px; font-size: 1.15rem; font-weight: 800; }
.credits-info-lede { margin: 0 auto 16px; max-width: 300px; text-align: center; font-size: 0.82rem; line-height: 1.45; color: var(--text-dim); }
.credits-info-balance {
  margin-bottom: 18px;
  padding: 10px 14px;
  border-radius: var(--r-sm);
  background: var(--control-fill);
  text-align: center;
  font-size: 0.78rem;
  color: var(--text-dim);
}
.credits-info-balance b { color: var(--text); font-size: 0.95rem; font-variant-numeric: tabular-nums; }
.credits-info-list { list-style: none; margin: 0 0 22px; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.credits-info-list li { display: flex; gap: 12px; align-items: flex-start; }
.credits-info-icon {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--r-sm);
  background: var(--control-fill);
  color: var(--text);
}
.credits-info-list b { display: block; font-size: 0.86rem; color: var(--text); margin-bottom: 2px; }
.credits-info-list span:not(.credits-info-icon) { display: block; font-size: 0.76rem; line-height: 1.45; color: var(--text-dim); }
@media (max-width: 640px) { .credits-info-card { padding: 22px 18px; } }


/* --- Motion ---------------------------------------------------------------
   Two springs, sampled from a closed-form damped spring's step response
   (see js/motion.js, which uses the same model for the tab pills):
   --spring overshoots by ~1.5% and settles, --spring-soft is critically
   damped (no overshoot). They replace the bouncy back-out curves that used
   to be scattered through this file. */
:root {
  --spring: linear(0.0, 0.0129, 0.047, 0.0965, 0.1567, 0.2234, 0.2935, 0.3645, 0.4345, 0.5019, 0.5657, 0.6251, 0.6798, 0.7296, 0.7742, 0.8139, 0.8489, 0.8793, 0.9056, 0.9279, 0.9468, 0.9626, 0.9756, 0.9861, 0.9945, 1.001, 1.006, 1.0097, 1.0122, 1.0139, 1.0148, 1.0152, 1.015, 1.0146, 1.0139, 1.013, 1.012, 1.011, 1.0099, 1.0088, 1.0078, 1.0068, 1.0059, 1.005, 1.0043, 1.0036, 1.0029, 1.0024, 1);
  --spring-soft: linear(0.0, 0.0139, 0.0497, 0.0998, 0.1587, 0.2222, 0.2872, 0.3516, 0.4139, 0.473, 0.5284, 0.5797, 0.6268, 0.6696, 0.7084, 0.7433, 0.7745, 0.8024, 0.8272, 0.8491, 0.8685, 0.8855, 0.9005, 0.9136, 0.9251, 0.9352, 0.9439, 0.9515, 0.9581, 0.9639, 0.9689, 0.9732, 0.9769, 0.9802, 0.983, 0.9854, 0.9874, 0.9892, 0.9908, 0.9921, 0.9932, 0.9942, 0.995, 0.9958, 0.9964, 0.9969, 0.9973, 0.9977, 1);
}

/* Press: buttons dip a touch while held and spring back on release. Only
   transform, so nothing reflows and no text re-rasterises mid-press. */
.modal-btn, .category-open-btn, .home-btn, .drop-line, .qty-btn, .qty-max-btn,
.market-chip, .offer-btn, .exit-btn, .wallet-item, .stat-pill, .avatar-btn,
.account-nav-item, .account-toggle-label, .add-funds-tab, .mute-btn,
.detail-media-btn, .item-action-btn, .payment-option, .home-more {
  transition-property: transform, background-color, color, box-shadow, opacity, border-color;
  transition-duration: 0.45s, 0.18s, 0.18s, 0.25s, 0.18s, 0.18s;
  transition-timing-function: var(--spring), ease, ease, ease, ease, ease;
}
:is(.modal-btn, .category-open-btn, .home-btn, .drop-line, .qty-btn, .qty-max-btn,
.market-chip, .offer-btn, .exit-btn, .wallet-item, .stat-pill,
.account-nav-item, .account-toggle-label, .add-funds-tab, .mute-btn,
.detail-media-btn, .item-action-btn, .payment-option, .home-more):active:not(:disabled) {
  transform: scale(0.96);
  transition-duration: 0.12s, 0.18s, 0.18s, 0.25s, 0.18s, 0.18s;
  transition-timing-function: ease-out, ease, ease, ease, ease, ease;
}
/* The lift-on-hover a few of these had is kept, and eased by the spring. */
.modal-btn:hover:not(:active), .category-open-btn:hover:not(:active) { transform: translateY(-2px); }

/* --- Liquid tab pill ------------------------------------------------------
   One pill behind the active tab, moved by js/motion.js (liquidTabs): its
   leading edge springs ahead of the trailing one, so it stretches as it
   travels. The tabs' own active background steps aside for it. */
.has-liquid { isolation: isolate; }
.has-liquid > .liquid-pill {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
  pointer-events: none;
  background: var(--pill-bg, var(--text));
  transition: opacity 0.2s ease, background-color 0.3s ease;
}
.has-liquid > :not(.liquid-pill) { position: relative; z-index: 1; }
.drop-lines { --pill-bg: var(--text); }
.account-nav, .account-toggle { --pill-bg: var(--accent-dim); }
.add-funds-tabs { --pill-bg: var(--surface-1); }
.drop-lines.has-liquid .drop-line.active,
.account-nav.has-liquid .account-nav-item.active,
.account-toggle.has-liquid .account-toggle-label.active,
.add-funds-tabs.has-liquid .add-funds-tab.active { background: transparent; }
/* The label colours still change, just after a beat, so they cross over
   as the pill arrives rather than before it. */
.drop-line, .account-nav-item, .account-toggle-label, .add-funds-tab { transition-delay: 0s, 0.06s, 0.06s, 0s, 0s, 0s; }

@media (prefers-reduced-motion: reduce) {
  :is(.modal-btn, .category-open-btn, .home-btn, .drop-line, .qty-btn, .market-chip, .exit-btn):active { transform: none; }
}

/* Rewards: both columns run to the same bottom edge. The columns stretch
   to the taller one and each column's last card (Leaderboard, How to earn
   more) takes up the slack, so their bottoms line up. Two columns only
   exist above 900px; below that the cards stack. */
@media (min-width: 901px) {
  .rewards-grid { align-items: stretch; }
  .rewards-col > .rewards-card:last-child { flex: 1 1 auto; }
  /* Any extra height goes above the pager, which stays on the bottom edge. */
  .rewards-leaderboard .leaderboard-pager { margin-top: auto; }
}

/* Referral Rewards, tightened: the share row and the claim block sat in
   24px-padded panels the same colour as the card, which read as empty
   space. Padding comes off, the gaps close up, and "Available to claim"
   becomes one line (label, then the figure) since the buttons below
   already show both amounts. */
.rewards-referral { gap: 12px; }
.referral-current { padding: 0; margin-bottom: 10px; }
.referral-current .share { font-size: 1.4rem; line-height: 1.1; }
.referral-progress-track { margin-bottom: 14px; }
.referral-claim { padding: 0; gap: 10px; margin-bottom: 12px; }
.referral-claim-info { flex-direction: row; align-items: baseline; justify-content: space-between; width: 100%; gap: 8px; }
.referral-claim-amount { font-size: 1.1rem; }
.claim-btn { padding: 11px 16px; }
.claim-btn-amount { font-size: 1.1rem; }

/* Measuring pass for the leaderboard fit (app.js fitLeaderboard): the
   columns at their natural heights, for one synchronous read. */
.rewards-grid.is-measuring { align-items: flex-start !important; }
.rewards-grid.is-measuring .rewards-col > .rewards-card:last-child { flex: none !important; }

/* Referral link: the link itself, and a Copy button that answers. */
.referral-link-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 5px 5px 14px;
  border-radius: 999px;
  background: var(--control-fill);
}
.referral-link-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.74rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.referral-copy-btn,
.referral-link-btn {
  transition: transform 0.45s var(--spring), background-color 0.18s ease, color 0.18s ease;
}
.referral-copy-btn {
  flex: 0 0 auto;
  padding: 8px 14px;
  border: none;
  border-radius: 999px;
  background: var(--text);
  color: var(--text-inverse);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  cursor: pointer;
}
.referral-copy-btn:hover { background: color-mix(in srgb, var(--text) 82%, var(--bg)); }
.referral-copy-btn:active, .referral-link-btn:active { transform: scale(0.96); transition-duration: 0.12s; }
/* Copied: the site's green, for as long as the label says so. */
.referral-copy-btn.is-copied,
.referral-link-btn.is-copied {
  background: var(--open-green);
  color: var(--open-ink);
  box-shadow: inset 0 0 0 1.5px #000;
}
.referral-copy-label, .referral-link-btn-label { display: inline-block; }
.referral-invite-note {
  margin: 2px 0 8px;
  font-size: 0.74rem;
  line-height: 1.45;
  color: var(--text-dim);
}
.referral-invite-note b { color: var(--text); }


/* ==========================================================================
   Motion: screens, reveals, the round guard, the theme wipe
   Additions to the springs and liquid tabs in motion.js. Each one animates
   toward a state the element already has, so none of it is load-bearing.
   Opacity and the standalone `translate` property only: `transform` is what
   the cards' own hover lifts use, and the two would fight over it.
   ========================================================================== */

/* Screens fade in rather than cut. Opacity only — Market and Account pin
   parts of their chrome, and a moving ancestor would drag pinned children
   along for the length of the animation. */
.screen.active { animation: screenFade 0.32s ease-out; }
@keyframes screenFade {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Scroll reveal (initReveal in motion.js). The hidden state exists only
   under .motion-armed, which is only ever set while the tab is drawing. */
.motion-armed [data-reveal]:not([data-reveal="stagger"]):not(.in),
.motion-armed [data-reveal="stagger"]:not(.in) > * {
  opacity: 0;
}
.motion-armed [data-reveal]:not([data-reveal="stagger"]).in { animation: revealRise 0.7s cubic-bezier(0.22, 1, 0.36, 1) both; }
.motion-armed [data-reveal="stagger"].in > * { animation: revealRise 0.6s cubic-bezier(0.22, 1, 0.36, 1) both; }
.motion-armed [data-reveal="stagger"].in > :nth-child(2) { animation-delay: 45ms; }
.motion-armed [data-reveal="stagger"].in > :nth-child(3) { animation-delay: 90ms; }
.motion-armed [data-reveal="stagger"].in > :nth-child(4) { animation-delay: 135ms; }
.motion-armed [data-reveal="stagger"].in > :nth-child(5) { animation-delay: 180ms; }
.motion-armed [data-reveal="stagger"].in > :nth-child(6) { animation-delay: 225ms; }
.motion-armed [data-reveal="stagger"].in > :nth-child(7) { animation-delay: 270ms; }
.motion-armed [data-reveal="stagger"].in > :nth-child(8) { animation-delay: 315ms; }
.motion-armed [data-reveal="stagger"].in > :nth-child(n + 9) { animation-delay: 360ms; }
/* Liquid pills sit inside some of these rows as a first child; they place
   themselves and must not fade with the content. */
.motion-armed [data-reveal="stagger"] > .liquid-pill { opacity: 1; animation: none; }
@keyframes revealRise {
  from { opacity: 0; translate: 0 24px; }
  to { opacity: 1; translate: none; }
}

/* "Pick a box first" — the row shakes its head. */
#boxRow.nudge { animation: nudge 0.42s cubic-bezier(0.22, 1, 0.36, 1); }
@keyframes nudge {
  20% { translate: -8px 0; }
  45% { translate: 7px 0; }
  70% { translate: -4px 0; }
  100% { translate: none; }
}

/* The theme wipe draws its own circle (themeWipe in motion.js), so the
   browser's default cross-fade is switched off and the new picture is laid
   straight over the old one. */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

@media (prefers-reduced-motion: reduce) {
  .screen.active,
  #boxRow.nudge { animation: none; }
}

@media (max-width: 640px) {
  /* Seven fixed 40px days plus their gaps come to 328px, wider than a phone
     card's inside: the week shares the width instead. */
  .rewards-week-strip { width: 100%; gap: 6px; }
  .rewards-day { flex: 1; min-width: 0; }
  .rewards-day-box { width: 100%; height: auto; aspect-ratio: 1; max-width: 40px; }
}

/* ==========================================================================
   Live pulls bar (desktop)
   The whole bottom edge. At rest one 52px row; on hover it grows upward
   into big tiles. The same tile element serves both — the row is the tile
   with its picture shrunk and its details laid out on one line — so
   opening the bar reflows what's there instead of swapping in a second
   list. No outline on the bar: it lifts off the page on a shadow.
   ========================================================================== */

.live-bar,
.live-bar-pill { display: none; }

@media (min-width: 641px) {
  :root { --live-bar-h: 52px; }

  .live-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 45;
    display: flex;
    align-items: stretch;
    height: var(--live-bar-h);
    background: var(--panel-blur);
    backdrop-filter: blur(14px);
    box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.08);
    transition: height 0.42s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .live-bar.is-open { height: 272px; }
  body.live-bar-min .live-bar { display: none; }

  /* Room at the bottom of every page for the bar, and the theme/sound
     buttons lift above it. */
  body:not(.live-bar-min) .shell-body { padding-bottom: var(--live-bar-h); }
  body:not(.live-bar-min) .rail-bottom { bottom: calc(var(--live-bar-h) + 14px); }

  .lb-label,
  .lb-all,
  .lb-min {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    align-self: flex-end;
    height: var(--live-bar-h);
    padding: 0 18px;
    border: none;
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 0.8rem;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
  }
  .lb-label { gap: 8px; padding-left: 20px; }
  .lb-all { color: var(--text-dim); }
  .lb-all:hover, .lb-min:hover { color: var(--text); }
  .lb-min { padding: 0 18px 0 8px; color: var(--text-faint); }

  .lb-dot {
    position: relative;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--positive);
  }
  .lb-dot::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: var(--positive);
    animation: lbPing 1.8s cubic-bezier(0, 0, 0.2, 1) infinite;
  }
  @keyframes lbPing {
    75%, 100% { transform: scale(2.6); opacity: 0; }
  }

  /* The row scrolls sideways under the wheel or a drag; its ends fade so a
     tile slides out of view rather than being cut. */
  .lb-view {
    flex: 1;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 24px, #000 calc(100% - 40px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 24px, #000 calc(100% - 40px), transparent);
  }
  .lb-view::-webkit-scrollbar { display: none; }
  .lb-track {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 100%;
    padding: 0 16px;
    width: max-content;
  }

  /* --- A tile, at rest: one line --------------------------------------- */
  .lb-pull {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 40px;
    padding: 0 12px 0 4px;
    border-radius: var(--r-sm);
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s ease;
  }
  .lb-pull:hover,
  .lb-pull:focus-visible { background: var(--hover-bg); outline: none; }
  .lb-media {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: var(--r-xs);
    background: #fff;
    overflow: hidden;
  }
  .lb-media img { width: 88%; height: 88%; object-fit: contain; }
  .lb-info { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
  .lb-name {
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--text);
  }
  .lb-price { font-size: 0.8rem; font-weight: 800; color: var(--positive); font-variant-numeric: tabular-nums; }
  /* Always green, whatever the rarity: the outline already says how rare,
     and a yellow or blue number read like a loss. */
  .lb-mult {
    margin-left: 6px;
    padding: 2px 6px;
    border-radius: var(--r-pill);
    background: color-mix(in srgb, var(--positive) 16%, transparent);
    color: var(--positive);
    font-size: 0.64rem;
    font-style: normal;
    font-weight: 800;
  }
  .lb-who { display: none; font-size: 0.7rem; color: var(--text-faint); }
  .lb-who b { color: var(--text); font-weight: 700; }
  .lb-crate {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 0;
    border: none;
    background: none;
    color: var(--text-faint);
    font: inherit;
    font-size: 0.72rem;
    cursor: pointer;
  }
  .lb-crate b { color: var(--text-dim); font-weight: 600; }
  .lb-crate i {
    padding: 2px 7px;
    border-radius: var(--r-pill);
    background: var(--control-fill);
    color: var(--text-dim);
    font-style: normal;
    font-weight: 700;
  }
  .lb-crate:hover b,
  .lb-crate:hover i { color: var(--text); }

  /* --- Open: big tiles --------------------------------------------------- */
  .live-bar.is-open .lb-track { align-items: flex-start; gap: 12px; padding: 16px 16px 0; }
  .live-bar.is-open .lb-pull {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 132px;
    height: auto;
    padding: 0;
    background: none;
    white-space: normal;
    animation: lbTileIn 0.34s cubic-bezier(0.22, 1, 0.36, 1) both;
  }
  .live-bar.is-open .lb-media {
    width: 100%;
    height: auto;
    aspect-ratio: 1;
    border-radius: var(--r-md);
    transition: box-shadow 0.2s ease, transform 0.2s ease;
  }
  .live-bar.is-open .lb-media img { width: 90%; height: 90%; transition: scale 0.35s cubic-bezier(0.22, 1, 0.36, 1); }
  .live-bar.is-open .lb-pull:hover .lb-media { transform: translateY(-3px); }
  .live-bar.is-open .lb-pull:hover .lb-media img { scale: 1.06; }
  .live-bar.is-open .lb-info { flex-direction: column; align-items: stretch; gap: 3px; padding: 0 2px; }
  .live-bar.is-open .lb-name { max-width: none; white-space: nowrap; font-size: 0.78rem; }
  .live-bar.is-open .lb-price { font-size: 0.84rem; }
  .live-bar.is-open .lb-who { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .live-bar.is-open .lb-crate { font-size: 0.68rem; white-space: nowrap; overflow: hidden; }
  .live-bar.is-open .lb-crate .lb-from { display: none; }
  @keyframes lbTileIn {
    from { opacity: 0; translate: 0 10px; }
    to { opacity: 1; translate: none; }
  }

  /* Rare and up: the picture is outlined in its rarity's colour, open or
     not — a line, not a glow, and nothing tinting the white behind the
     shot, so the photo never shows as a box inside a box. */
  /* Drawn as a layer over the photo, not an inset shadow under it: the
     shot's own square white corners painted over the shadow and cut the
     ring's rounded corners off. */
  .lb-media { position: relative; }
  .lb-pull.is-special .lb-media::after {
    content: "";
    position: absolute;
    inset: 0;
    border: 1.5px solid var(--rarity-color);
    border-radius: inherit;
    pointer-events: none;
  }
  .live-bar.is-open .lb-pull.is-special .lb-media::after { border-width: 2px; }

  /* A pull arriving pops in where it lands. A good one (Rare and up) then
     glares: a sheen in its rarity's colour sweeps across the tile over a
     soft tint, and fades — inside the tile's own edges, behind its text,
     so it never spills onto its neighbours. */
  .lb-pull.is-arriving { animation: lbArrive 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); }
  @keyframes lbArrive {
    from { opacity: 0; scale: 0.7; }
    to { opacity: 1; scale: 1; }
  }
  .lb-pull { position: relative; isolation: isolate; }
  .lb-pull.is-glaring::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    background:
      linear-gradient(105deg, transparent 35%, color-mix(in srgb, var(--rarity-color) 55%, transparent) 50%, transparent 65%) no-repeat,
      color-mix(in srgb, var(--rarity-color) 20%, transparent);
    background-size: 260% 100%, 100% 100%;
    animation: lbGlare 1.4s cubic-bezier(0.3, 0.6, 0.3, 1) both;
  }
  .live-bar.is-open .lb-pull.is-glaring::before { inset: -6px; border-radius: var(--r-md); }
  @keyframes lbGlare {
    0% { opacity: 0; background-position: 120% 0, 0 0; }
    18% { opacity: 1; }
    65% { opacity: 1; }
    100% { opacity: 0; background-position: -20% 0, 0 0; }
  }

  /* Minimized: a pill in the corner that brings it back — the right-hand
     corner, under where the minimize button was. */
  body.live-bar-min .live-bar-pill {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 45;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border: none;
    border-radius: var(--r-pill);
    background: var(--surface-1);
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.12);
    color: var(--text);
    font: inherit;
    font-size: 0.78rem;
    font-weight: 700;
    cursor: pointer;
  }
  :root[data-theme="light"] body.live-bar-min .live-bar-pill { background: #fff; }
  /* A Grail, Epic or Rare pulled while minimized: the pill takes the same
     colour sweep a tile glares with in the open bar, with a ring and glow
     in the tier's colour so it reads from the corner of your eye. */
  body.live-bar-min .live-bar-pill { isolation: isolate; overflow: hidden; transition: box-shadow 0.4s ease; }
  body.live-bar-min .live-bar-pill.is-glaring {
    box-shadow: 0 0 0 2px var(--rarity-color), 0 8px 26px color-mix(in srgb, var(--rarity-color) 45%, transparent);
  }
  body.live-bar-min .live-bar-pill.is-glaring::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    background:
      linear-gradient(105deg, transparent 30%, color-mix(in srgb, var(--rarity-color) 60%, transparent) 50%, transparent 70%) no-repeat,
      color-mix(in srgb, var(--rarity-color) 22%, transparent);
    background-size: 260% 100%, 100% 100%;
    animation: lbGlare 1.6s cubic-bezier(0.3, 0.6, 0.3, 1) both;
  }

  /* The corner dock was desktop's live feed; the bar is now. It stays the
     phone's (see the mobile query). */
  .pull-dock { display: none !important; }
}

@media (max-width: 640px) {
  .live-bar, .live-bar-pill { display: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  .live-bar { transition: none; }
  .lb-dot::after, .lb-pull.is-arriving, .live-bar.is-open .lb-pull, .lb-pull.is-glaring::before { animation: none !important; }
}
@media (min-width: 641px) {
  /* Open, the tiles' own entrance would otherwise win over the arrival pop. */
  .live-bar.is-open .lb-pull.is-arriving { animation: lbArrive 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); }
}
@media (min-width: 641px) {
  /* The pinned side panels are sized to the viewport; with the bar showing
     their last 52px would sit under it. */
  body:not(.live-bar-min) .market-filters {
    max-height: calc(100vh - var(--pin-top) - var(--market-head-h, 52px) - 24px - var(--live-bar-h));
  }
  body:not(.live-bar-min) .account-sidebar {
    max-height: calc(100vh - var(--pin-top) - 16px - var(--live-bar-h));
  }
}
@media (min-width: 641px) {
  /* Open, the tiles take the full width and the controls drop into a strip
     beneath them — otherwise the label kept an empty column down the left
     of the row the whole height of the bar. */
  .live-bar {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "label view all min";
  }
  .lb-label { grid-area: label; }
  .lb-view { grid-area: view; }
  .lb-all { grid-area: all; }
  .lb-min { grid-area: min; }
  .live-bar.is-open {
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-rows: minmax(0, 1fr) 44px;
    grid-template-areas:
      "view view view view"
      "label . all min";
  }
  .live-bar.is-open .lb-label,
  .live-bar.is-open .lb-all,
  .live-bar.is-open .lb-min { height: 44px; align-self: center; }

  /* The theme and sound buttons ride up with the bar as it opens. */
  .rail-bottom { transition: bottom 0.42s cubic-bezier(0.22, 1, 0.36, 1); }
  body:not(.live-bar-min):has(.live-bar.is-open) .rail-bottom { bottom: calc(272px + 14px); }
}

/* The cardboard box in the round is framed for its open flaps, which
   shrinks it ~10% inside its canvas; the canvas grows by as much, outward
   into the slot's margin, so the box stays the size it was and the slot
   doesn't move. */
.box-slot.is-od .box-canvas { width: 212px; height: 212px; margin: -11px; }
@media (max-width: 640px) {
  .box-slot.is-od .box-canvas { width: 116px; height: 116px; margin: -6px; }
}

@media (min-width: 641px) {
  /* At rest the bar says three things per pull: the picture, the name, the
     price. Who pulled it, the multiple and the crate it came out of wait for
     the open bar, where there's room to read them — and the crate line
     there is the way into the crate. */
  .live-bar:not(.is-open) .lb-mult,
  .live-bar:not(.is-open) .lb-crate { display: none; }
  .live-bar:not(.is-open) .lb-track { gap: 4px; padding: 0 12px; }
  .live-bar:not(.is-open) .lb-pull { padding: 0 14px 0 4px; }
  .live-bar:not(.is-open) .lb-pull.is-alt { background: var(--control-fill); }
  .live-bar:not(.is-open) .lb-pull:hover { background: var(--control-fill-hover); }
}

/* ==========================================================================
   Home: crate cards, grails and How it works, in the layout of the team's
   other Chosen build — adapted to this site's scale and its no-outline
   rule (their cards are ruled in black; these lift on the page's own
   surface tones instead).
   ========================================================================== */

/* --- Crate cards ------------------------------------------------------- */
#homeCrates .home-crate {
  gap: 0;
  padding: 0;
  overflow: hidden;
  background: var(--surface-1);
}
.crate-panel {
  --crate-tint: #efe3d4;
  position: relative;
  padding: 14px 14px 12px;
  background: linear-gradient(var(--crate-tint), transparent);
}
.home-crate[data-line="sneakers"] .crate-panel { --crate-tint: #f3ddcb; }
.home-crate[data-line="streetwear"] .crate-panel { --crate-tint: #dfe6f1; }
.home-crate[data-line="collectibles"] .crate-panel { --crate-tint: #f5e7c6; }
:root:not([data-theme="light"]) .crate-panel { --crate-tint: rgba(255, 255, 255, 0.07); }
.crate-brand {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 1;
  padding: 4px 9px;
  border-radius: var(--r-pill);
  background: var(--surface-1);
  color: var(--text);
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.6px;
  text-transform: uppercase;
}
#homeCrates .home-crate-stage { aspect-ratio: 5 / 4; background: none; }
.crate-could {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.72rem;
  color: var(--text-dim);
}
.crate-could-thumbs { display: flex; gap: 4px; }
.crate-could-thumbs img {
  width: 32px;
  height: 32px;
  padding: 3px;
  border-radius: var(--r-xs);
  background: #fff;
  object-fit: contain;
}
.crate-body { display: flex; flex-direction: column; gap: 12px; padding: 12px 16px 16px; }
.crate-title { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.crate-title .category-tier-name { font-size: 1.1rem; }
.crate-price { font-size: 1.05rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.crate-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.crate-facts span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.crate-facts i { font-style: normal; font-size: 0.66rem; color: var(--text-dim); }
.crate-facts b { font-size: 0.82rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.crate-supply { height: 4px; border-radius: var(--r-pill); background: var(--control-fill); overflow: hidden; }
.crate-supply i { display: block; height: 100%; border-radius: inherit; background: var(--text); }
#homeCrates .home-crate-open { width: 100%; margin-top: 2px; }

/* --- Grails: the clean collectibles grid --------------------------------- */
#homeGrails {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  grid-auto-rows: auto;
  gap: 28px 14px;
}
#homeGrails .home-grail {
  grid-column: auto;
  grid-row: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 0;
  border-radius: 0;
  background: none;
  text-align: left;
}
#homeGrails .home-grail:hover { transform: none; }
#homeGrails .home-grail-media {
  position: relative;
  flex: none;
  aspect-ratio: 1;
  min-height: 0;
  margin-bottom: 8px;
  padding: 14px;
  border-radius: var(--r-md);
  background: #fff;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
#homeGrails .home-grail:hover .home-grail-media { transform: translateY(-3px); box-shadow: 0 12px 26px rgba(0, 0, 0, 0.1); }
#homeGrails .home-grail-media img { width: 100%; height: 100%; object-fit: contain; }
.home-grail-chip {
  position: absolute;
  top: 10px;
  left: 10px;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, currentColor 12%, #fff);
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.6px;
  text-transform: uppercase;
}
#homeGrails .home-grail-name,
#homeGrails .home-grail:nth-child(n) .home-grail-name {
  font-size: 0.86rem;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#homeGrails .home-grail-foot,
#homeGrails .home-grail:nth-child(n) .home-grail-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
#homeGrails .home-grail-foot b,
#homeGrails .home-grail:nth-child(n) .home-grail-foot b {
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 800;
  letter-spacing: 0;
  color: var(--text);
}
#homeGrails .home-grail-foot span { font-size: 0.68rem; color: var(--text-faint); }

/* --- How it works: three across, joined by dotted arrows ----------------- */
.how-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 40px 72px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.how-step { position: relative; }
/* The arrow into the next step, in the gap between the pictures. */
.how-step:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 96px;
  right: -58px;
  width: 44px;
  height: 12px;
  background:
    radial-gradient(circle, var(--text) 1.3px, transparent 1.6px) 0 50% / 7px 4px repeat-x;
  -webkit-mask: linear-gradient(90deg, #000 78%, transparent 78%);
  mask: linear-gradient(90deg, #000 78%, transparent 78%);
}
.how-step:not(:last-child)::before {
  content: "";
  position: absolute;
  top: 97px;
  right: -58px;
  width: 8px;
  height: 8px;
  border-top: 1.8px solid var(--text);
  border-right: 1.8px solid var(--text);
  transform: translateY(-2px) rotate(45deg);
}
.how-art {
  position: relative;
  height: 200px;
  margin-bottom: 26px;
}
/* 1 — three crates, stacked. */
.how-crate { position: absolute; width: 56%; object-fit: contain; filter: drop-shadow(0 14px 16px rgba(0, 0, 0, 0.14)); }
.how-crate-a { left: 2%; top: 4%; transform: rotate(-4deg); }
.how-crate-b { right: 2%; top: 0; transform: scaleX(-1) rotate(-3deg); }
.how-crate-c { left: 22%; top: 30%; width: 62%; z-index: 1; }
/* 2 — three grails cut out of their backgrounds, fanned, the middle one
   in front. */
.how-art-pick { display: flex; align-items: center; justify-content: center; }
.how-card {
  position: absolute;
  width: 46%;
  height: 72%;
  object-fit: contain;
  filter: drop-shadow(0 14px 14px rgba(0, 0, 0, 0.18));
}
.how-card-l { left: 8%; top: 2%; transform: rotate(-8deg); }
.how-card-r { right: 6%; top: 0; transform: rotate(8deg); }
.how-card-c { z-index: 1; left: 10%; top: 30%; width: 80%; height: 66%; transform: rotate(-5deg) scale(1.3); }
/* 3 — the three ways out. */
.how-exit {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-radius: var(--r-md);
  background: var(--surface-1);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.05);
  color: var(--text);
  font-size: 0.9rem;
  font-weight: 600;
}
:root[data-theme="light"] .how-exit { background: #fff; }
.how-exit svg { flex: 0 0 auto; color: var(--text-dim); }
.how-num {
  display: block;
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-size: 2.6rem;
  line-height: 1;
  color: var(--text);
}
.how-step h3 {
  margin: 4px 0 8px;
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-size: 1.5rem;
  font-weight: 400;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--text);
}
.how-step p { max-width: 34ch; margin: 0; font-size: 0.9rem; line-height: 1.55; color: var(--text-dim); }

@media (max-width: 1000px) and (min-width: 641px) {
  #homeGrails { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .how-steps { gap: 32px 40px; }
  .how-step:not(:last-child)::after,
  .how-step:not(:last-child)::before { display: none; }
}

@media (max-width: 640px) {
  #homeGrails { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 10px; }
  #homeGrails .home-grail:nth-child(1),
  #homeGrails .home-grail:nth-child(6) { grid-column: auto; }
  .how-steps { grid-template-columns: 1fr; gap: 36px; }
  .how-step:not(:last-child)::after,
  .how-step:not(:last-child)::before { display: none; }
  .how-art { height: 180px; margin-bottom: 18px; }
  .crate-facts b { font-size: 0.74rem; }
}

/* --- Grails as slot reels (spinGrail in app.js) -------------------------
   Each tile is a window onto a vertical strip of pieces. At rest the strip
   holds one; a spin fills it with a run of others and slides it up, blurred
   for the fast part, stopping hard on the new piece. Name, price and the
   Grail tag ease out for the spin and back in when it lands. */
#homeGrails .home-grail-media {
  position: relative;
  padding: 0;
  overflow: visible;
  transition: transform 0.2s ease, box-shadow 0.35s ease;
}
.grail-window {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  background: #fff;
}
/* The reel's top and bottom fade into the window, so pieces arrive and
   leave rather than being cut by its edge. */
.grail-window::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(#fff, transparent 14%, transparent 86%, #fff);
}
.grail-strip { display: block; will-change: transform, filter; }
.grail-strip.is-blurred { filter: blur(2.5px); }
/* Each piece is exactly one window tall, whatever the window's shape, so
   the reel's step (the window's height, in spinGrail) always lands flush. */
.grail-window { container-type: size; }
.grail-item { display: block; width: 100%; height: 100cqh; padding: 14px; }
.grail-item img { display: block; width: 100%; height: 100%; object-fit: contain; }

.grail-badge {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, #f7b733, #f56a3d);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.3px;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.35s ease-in-out, transform 0.35s ease-in-out;
}
.home-grail.is-grail .grail-badge { opacity: 1; transform: none; }

.home-grail-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
  transition: opacity 0.35s ease-in-out, transform 0.35s ease-in-out;
}
.home-grail-meta .home-grail-name { flex: 1; min-width: 0; }
.home-grail-price { font-size: 0.9rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }

/* During a spin: text and tag out. */
.home-grail.is-changing .home-grail-meta { opacity: 0; transform: translateY(4px); }
.home-grail.is-changing .grail-badge { opacity: 0; transform: translateY(-4px); }

/* One light sweep across a grail as it lands. */
.grail-shine {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
}
.grail-shine::before {
  content: "";
  position: absolute;
  top: -20%;
  bottom: -20%;
  width: 40%;
  left: -60%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.85), transparent);
  transform: skewX(-12deg);
}
.home-grail.is-shining .grail-shine::before { animation: grailSweep 0.9s cubic-bezier(0.22, 1, 0.36, 1); }
@keyframes grailSweep {
  from { left: -60%; }
  to { left: 130%; }
}

/* --- Grails as a bento: the first piece big on the left, four small in
   a square to its right. The big tile stretches to the two rows the small
   ones make, and its window takes whatever shape that leaves. */
#homeGrails { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px 16px; }
#homeGrails .home-grail:first-child { grid-column: 1 / span 2; grid-row: 1 / span 2; }
#homeGrails .home-grail:first-child .home-grail-media { flex: 1 1 auto; aspect-ratio: auto; }
#homeGrails .home-grail:first-child .grail-item { padding: 36px; }
#homeGrails .home-grail:first-child .home-grail-name,
#homeGrails .home-grail:first-child .home-grail-price { font-size: 1.05rem; }
#homeGrails .home-grail:first-child .grail-badge { top: 16px; right: 16px; font-size: 0.72rem; padding: 4px 11px; }
@media (max-width: 640px) {
  #homeGrails { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 10px; }
  #homeGrails .home-grail:first-child { grid-column: 1 / -1; grid-row: auto; }
  #homeGrails .home-grail:first-child .home-grail-media { flex: none; aspect-ratio: 4 / 3; }
  #homeGrails .home-grail:first-child .grail-item { padding: 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .grail-strip { transition: none !important; }
  .home-grail.is-shining .grail-shine::before { animation: none; }
}

/* --- Open buttons: green, everywhere -------------------------------------
   Every button that opens a crate is the same one, after the reference
   build: flat bright green, a thin black keyline, softly squared corners,
   dark green type. The price is already on the card above it; the button
   just says Open. */
.category-open-btn,
#homeCrates .home-crate-open,
.home-btn-open,
.home-hero .home-btn-open {
  background: var(--open-green);
  color: var(--open-ink);
  border: 1.5px solid #000;
  border-radius: 9px;
  font-weight: 600;
  letter-spacing: 0;
  box-shadow: none;
}
.category-open-btn:hover,
#homeCrates .home-crate-open:hover,
.home-btn-open:hover,
.home-hero .home-btn-open:hover { background: var(--open-green-hover); }

/* --- Partner logos: ODTO's wordmark on its white chip, Robinhood's feather */
.crate-brand { display: inline-flex; align-items: center; gap: 5px; }
.crate-brand:has(.brand-mark-odto) {
  padding: 7px 14px;
  border: 2px solid #deddd8;
  background: #fff;
  color: #0b0b0b;
}
.crate-brand .brand-mark-odto { display: block; height: 13px; width: auto; }
.crate-brand .brand-mark-robinhood { width: 14px; height: 14px; }
.category-powered-by { display: flex; align-items: center; justify-content: center; gap: 5px; height: 15px; }
.category-powered-by-spacer { height: 23px; } /* the line above, plus its margin */
.category-powered-by .brand-mark { flex: none; color: var(--text); }
.category-powered-by .brand-mark-odto { height: 9px; width: auto; }
.category-powered-by .brand-mark-robinhood { width: 12px; height: 12px; }

/* --- Drops: bigger boxes ----------------------------------------------------
   The prop is framed with room to spin (and, on the round screen, to open),
   so a canvas shows the box at well under half its width. Twice the canvas,
   pulled in top and bottom where that framing leaves only air. */
.category-list.is-all .category-box-canvas,
.category-box-canvas { width: min(100%, 230px); height: auto; aspect-ratio: 1; margin: -18px auto -22px; }
@media (min-width: 641px) {
  .drop-detail-active .category-card { flex: 0 0 420px; min-width: 0; }
  .category-list .drop-detail-active .category-box-canvas { width: 320px; max-width: 100%; height: auto; margin: -30px auto -36px; }
}
@media (max-width: 640px) {
  .category-list.is-all .category-box-canvas,
  .category-box-canvas { width: min(100%, 170px); margin: -10px auto -14px; }
  .category-list .drop-detail-active .category-box-canvas { width: min(100%, 260px); height: auto; margin: -20px auto -26px; }
}
/* Withdraw sits beside the green Deposit: same corners, so they read as a pair. */
.account-wallet-actions .modal-btn { border-radius: 9px; }
.account-wallet-actions .modal-btn:not(.deposit-btn) { border: 1.5px solid transparent; }

/* --- Home billboard, open to the page ------------------------------------
   No panel: the copy, the crate and the burst sit straight on the page's
   own background. Its ink follows the theme now it isn't on a fixed pale
   stage, and the slide accents lift toward white in dark mode so a dark
   accent (the $1,000 slide's) still reads. The crate floats over a soft
   shadow on the floor. */
.home-hero {
  --hero-ink: var(--text);
  --hero-ink-dim: var(--text-dim);
  background: none;
  border-radius: 0;
}
.home-hero::before { content: none; }
.home-hero-copy { padding-left: 0; }
.home-hero-dot::before { background: color-mix(in srgb, var(--hero-ink) 14%, transparent); }
:root:not([data-theme="light"]) .home-hero-eyebrow {
  background-image: linear-gradient(90deg,
    color-mix(in srgb, var(--hero-accent) 55%, #fff),
    color-mix(in srgb, var(--hero-accent2) 55%, #fff));
}
:root:not([data-theme="light"]) .home-hero-media::before {
  color: color-mix(in srgb, var(--hero-accent) 40%, #fff);
}

/* The float: the crate drifts up and back, and its shadow on the floor
   tightens and fades as it rises, so it reads as hovering over the page. */
.home-hero-box canvas { animation: heroFloat 4.2s ease-in-out infinite; }
.home-hero-box::after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 50%;
  bottom: 16.5%;
  width: 58%;
  height: 7%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0, 0, 0, 0.32), rgba(0, 0, 0, 0));
  transform: translateX(-50%);
  animation: heroFloatShadow 4.2s ease-in-out infinite;
  pointer-events: none;
}
:root:not([data-theme="light"]) .home-hero-box::after {
  background: radial-gradient(closest-side, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0));
}
@keyframes heroFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}
@keyframes heroFloatShadow {
  0%, 100% { transform: translateX(-50%) scale(1); opacity: 1; }
  50% { transform: translateX(-50%) scale(0.84); opacity: 0.7; }
}
@media (prefers-reduced-motion: reduce) {
  .home-hero-box canvas, .home-hero-box::after { animation: none; }
}
@media (max-width: 640px) {
  .home-hero-copy { padding-left: 0; padding-right: 0; }
}

/* No watermark word behind the crate. And the show itself bigger and a
   little lower, filling the half it sits in: the stage grows past the
   media box (the burst is placed as shares of the stage, so the crate, its
   mouth and every prize scale together), and nothing clips it now there's
   no panel edge to clip to. */
.home-hero-media::before { content: none; }
.home-hero { overflow: visible; }
@media (min-width: 641px) {
  /* Low enough that the crate's base sits just above "Pick your drop",
     bridging the two instead of leaving a gap under the billboard. */
  .home-hero-stage { inset: 6% -10% -28% -10%; }
  .home-hero-box { width: 70%; }
}
@media (max-width: 640px) {
  .home-hero-stage { inset: 0 -4% -8%; }
  .home-hero-box { width: 64%; }
}

/* ==========================================================================
   Crate supply and sealed crates
   ========================================================================== */

/* --- On a crate card: what's left of the drop --------------------------- */
.supply-block { margin-top: 14px; text-align: left; }
.supply-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 5px;
  font-size: 0.68rem;
  color: var(--text-dim);
}
.supply-count b { color: var(--text); font-weight: 800; font-variant-numeric: tabular-nums; }
.supply-grails { color: var(--gold); font-weight: 700; white-space: nowrap; }
.supply-track { height: 4px; border-radius: var(--r-pill); background: var(--track, var(--control-fill)); overflow: hidden; }
.supply-track i { display: block; height: 100%; border-radius: inherit; background: var(--text); transition: width 0.4s ease; }
.supply-whats-left {
  margin-top: 8px;
  padding: 0;
  border: none;
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.7rem;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.supply-whats-left:hover { color: var(--text); }

/* Prize rows on a crate's page: how many of each are left, gone ones faded. */

/* --- Buy dialog: open now, or keep it sealed --------------------------- */
.pay-mode[hidden] { display: none; }
.pay-mode {
  display: flex;
  gap: 4px;
  margin: 4px 0 8px;
  padding: 4px;
  border-radius: var(--r-pill);
  background: var(--control-fill);
}
.pay-mode-btn {
  flex: 1;
  padding: 9px 10px;
  border: none;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.pay-mode-btn.active { background: var(--surface-1); color: var(--text); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); }
:root[data-theme="light"] .pay-mode-btn.active { background: #fff; }
.pay-supply { margin: 0 0 14px; font-size: 0.72rem; color: var(--text-dim); }

/* --- What's left ------------------------------------------------------------ */
.crate-modal-card {
  max-width: 760px;
  max-height: calc(100vh - 48px);
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 24px;
  text-align: left;
}
.modal-close-x {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 50%;
  background: var(--control-fill);
  color: var(--text-dim);
  cursor: pointer;
}
.modal-close-x:hover { background: var(--control-fill-hover); color: var(--text); }
.crate-modal-head { display: flex; align-items: center; gap: 16px; padding-right: 40px; }
.crate-modal-box { width: 88px; height: 88px; object-fit: contain; flex: 0 0 auto; }
.crate-modal-eyebrow {
  display: block;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-faint);
}
.crate-modal-title {
  margin: 2px 0;
  font-family: Anton, "Arial Narrow", Impact, sans-serif;
  font-size: 1.7rem;
  font-weight: 400;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--text);
}
.crate-modal-sub { font-size: 0.78rem; color: var(--text-dim); }

.crate-modal-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.crate-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.crate-stat b { font-size: 1.15rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.crate-stat b small { font-size: 0.72rem; font-weight: 600; color: var(--text-faint); }
.crate-stat span { font-size: 0.68rem; color: var(--text-dim); }

/* The live odds: one cell per tier, what's left of it over what's left. */
.crate-modal-odds { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.crate-odds-cell {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--rarity-color) 12%, transparent);
}
.crate-odds-cell.is-gone { opacity: 0.45; }
.crate-odds-label { font-size: 0.62rem; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase; color: var(--rarity-color); }
:root[data-theme="light"] .crate-odds-label { filter: brightness(0.65) saturate(1.4); }
.crate-odds-cell b { font-size: 0.95rem; color: var(--text); font-variant-numeric: tabular-nums; }
.crate-odds-left { font-size: 0.62rem; color: var(--text-dim); }

.crate-modal-list { overflow-y: auto; min-height: 0; padding-right: 4px; margin-right: -4px; }
.crate-tier + .crate-tier { margin-top: 16px; }
.crate-tier-head {
  display: flex;
  justify-content: space-between;
  margin-bottom: 8px;
  font-size: 0.72rem;
  font-weight: 800;
  color: var(--text-dim);
}
.crate-tier-head span:first-child { color: var(--rarity-color); letter-spacing: 0.5px; text-transform: uppercase; }
:root[data-theme="light"] .crate-tier-head span:first-child { filter: brightness(0.65) saturate(1.4); }
.crate-tier-items { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 10px; }
.crate-prize { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.crate-prize-media {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  padding: 8px;
  border-radius: var(--r-sm);
  background: #fff;
}
.crate-prize-media img { width: 100%; height: 100%; object-fit: contain; }
.crate-prize-name { font-size: 0.72rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.crate-prize-foot { display: flex; justify-content: space-between; gap: 6px; font-size: 0.72rem; }
.crate-prize-foot b { color: var(--text); font-variant-numeric: tabular-nums; }
.crate-prize-foot span { color: var(--text-dim); font-weight: 700; }
.crate-prize.is-gone { opacity: 0.38; }
.crate-prize.is-gone img { filter: grayscale(1); }

.crate-modal-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; flex-wrap: wrap; }
.crate-modal-actions .modal-btn { width: auto; padding-left: 22px; padding-right: 22px; margin: 0; }
.crate-modal-note { display: inline-flex; align-items: center; gap: 8px; margin-right: auto; font-size: 0.78rem; color: var(--text-dim); }

/* --- Sealed crate cards (Account and the market) ---------------------------- */
/* On the same white tile as every other product, so a sealed box sits in
   a grid of items (My Items, the market) as one of them. The box fills
   more of its tile than a photo would: it's a cut-out with no margin. */
.market-item .sealed-media img { padding: 2px; background: #fff; border-radius: var(--r-sm); }
.sealed-sub { display: block; font-size: 0.7rem; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* The market narrowed to one crate's sealed boxes, and the way back out. */
.market-focus {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 8px;
  justify-self: start;
  padding: 6px 6px 6px 14px;
  border-radius: var(--r-pill);
  background: var(--control-fill);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text);
}
.market-focus-clear {
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 50%;
  background: var(--surface-1);
  color: var(--text-dim);
  font: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

@media (max-width: 640px) {
  .crate-modal-card { padding: 18px; gap: 12px; }
  .crate-modal-box { width: 64px; height: 64px; }
  .crate-modal-title { font-size: 1.3rem; }
  .crate-modal-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .crate-modal-odds { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4px; }
  .crate-odds-cell { padding: 6px; }
  .crate-odds-cell b { font-size: 0.78rem; }
  .crate-tier-items { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .crate-modal-actions .modal-btn { flex: 1; }
}

/* How many sealed crates you hold, on the Holdings "Crates" tab. */
.toggle-count {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  margin-left: 4px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--positive);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 800;
}
.toggle-count[hidden] { display: none; }
@media (max-width: 640px) {
  /* A list to browse, not a small confirm dialog: the phone width cap for
     pop-ups would squeeze three prizes a row into ~75px tiles. */
  .prize-modal-card.crate-modal-card { width: 100%; max-width: none; max-height: calc(100vh - 32px); }
  #crateModal { padding: 16px 12px; }
}

/* --- What's inside: the pieces still in a crate, stacked by tier --------
   One stack per tier (Grail, Epic, Rare — or the best three tiers still
   in stock), each piece on a white tile edged in its tier's colour, the
   best piece in front and the next ones peeking out square behind it.
   The stacks share the row's width between them and each fills its share
   edge to edge — tiles as big as the row allows (up to --wl-max), the
   pieces behind spread to the share's far edge — so there's no dead space
   at the end of the row. A button where it opens the crate's page; a plain
   row inside cards that already open something. */
.whats-left {
  --wl-max: 52px;
  --wl-gap: 6px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
  width: 100%;
  margin-top: 12px;
  padding: 9px 10px 10px;
  border: none;
  border-radius: var(--r-md);
  background: var(--control-fill);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s ease;
  container: wl / inline-size;
}
button.whats-left:hover { background: var(--control-fill-hover); }
.whats-left-label {
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-dim);
  line-height: 1;
}
/* 100cqi is the row's own inner width (it's the container), so each
   stack's share and the tile size follow the card, whatever its width. */
.whats-left-thumbs {
  /* --k tier stacks, each about 1.4 tiles wide, share the row evenly.
     The tile size comes first; then each stack takes its share. */
  --wl-size: min(var(--wl-max), calc((100cqi - (var(--k, 3) - 1) * var(--wl-gap)) / (var(--k, 3) * 1.4)));
  --wl-share: calc((100cqi - (var(--k, 3) - 1) * var(--wl-gap)) / var(--k, 3));
  display: flex;
  align-items: center;
  gap: var(--wl-gap);
  width: 100%;
}
.wl-stack {
  /* The step that lands the last tile's right edge on the share's edge. */
  --wl-step: calc((var(--wl-share) - var(--wl-size)) / max(var(--n) - 1, 1));
  display: flex;
  flex: 1 1 0;
  min-width: 0;
}
.wl-fan { position: relative; width: 100%; height: var(--wl-size); }
.wl-thumb {
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: var(--wl-size);
  height: var(--wl-size);
  padding: 3px;
  border: 1.5px solid var(--rarity-color);
  border-radius: var(--r-xs);
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  /* --i 0 is the front tile; each one behind sits a step to the right and
     a little smaller, its right edge showing like the next card in a deck. */
  transform: translateX(calc(var(--i) * var(--wl-step))) scale(calc(1 - var(--i) * 0.1));
  transform-origin: 100% 50%;
  z-index: calc(10 - var(--i));
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.wl-thumb img { width: 100%; height: 100%; object-fit: contain; }
/* The Grail in front gets a slow sheen across it: the one tier worth a shine. */
.wl-legendary .wl-thumb[style*="--i:0"]::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, 0.85) 50%, transparent 65%) no-repeat;
  background-size: 250% 100%;
  background-position: 130% 0;
  animation: wl-sheen 3.6s ease-in-out infinite;
  pointer-events: none;
}
@keyframes wl-sheen {
  0%, 55% { background-position: 130% 0; }
  85%, 100% { background-position: -30% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .wl-legendary .wl-thumb::after { animation: none; display: none; }
  .wl-thumb { transition: none; }
}
/* Home: sits in the crate panel where "Could contain" was, with room for
   bigger tiles. */
.whats-left-home { --wl-max: 60px; margin-top: 0; background: rgba(255, 255, 255, 0.55); }
:root:not([data-theme="light"]) .whats-left-home { background: rgba(255, 255, 255, 0.06); }
/* Inside sealed cards: no ground of its own, smaller stacks, no label. */
/* A sealed box on the market links to its crate's page in words: the
   card's own picture is the box, and stacks at that size were noise. */
.view-inside {
  align-self: flex-start;
  margin-top: 4px;
  padding: 0;
  border: none;
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line-strong);
  cursor: pointer;
}
.view-inside:hover { color: var(--text); text-decoration-color: currentColor; }
@media (max-width: 640px) {
  .whats-left { padding: 8px; }
}

/* --- Market: a sealed box's own page ---------------------------------------
   The crate page's layout (it reuses .drop-detail-active), with the box
   for sale on the left: price, seller, value, Buy and Make an offer. */
#screen-marketplace.is-crate-view > .market-title-row,
#screen-marketplace.is-crate-view > .market-shell { display: none; }
.market-crate-view { max-width: 1000px; margin: 0 auto; }
.market-crate-view .drop-detail-back { display: inline-flex; }
.mcv-card { align-items: center; justify-content: center; gap: 6px; cursor: default; }
.mcv-box { display: block; width: min(100%, 240px); aspect-ratio: 1; object-fit: contain; margin: -8px auto 0; }
.mcv-tags { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.mcv-name { margin: 6px 0 0; font-size: 1.2rem; font-weight: 800; color: var(--text); }
.mcv-seller { font-size: 0.74rem; color: var(--text-dim); }
.mcv-seller b { color: var(--text); }
.mcv-price { margin-top: 10px; font-size: 2rem; font-weight: 900; line-height: 1; color: var(--text); }
.mcv-ev { font-size: 0.72rem; color: var(--text-faint); }
.mcv-actions { display: flex; flex-direction: column; gap: 8px; width: 100%; margin-top: 16px; }
.mcv-actions .mcv-buy { margin-top: 0; width: 100%; }
.mcv-btn {
  width: 100%;
  padding: 12px 0;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 0.84rem;
  font-weight: 700;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.mcv-btn:hover { border-color: var(--text); }
.mcv-offers { width: 100%; margin-top: 14px; text-align: left; }
.mcv-offers-label { display: block; margin-bottom: 6px; font-size: 0.62rem; font-weight: 800; letter-spacing: 1px; text-transform: uppercase; color: var(--text-dim); }
.mcv-offer { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--hairline); font-size: 0.76rem; }
.mcv-offer b { color: var(--text); }
.mcv-offer-status { margin-left: auto; color: var(--text-dim); }
.mcv-offer-status.is-yes { color: var(--green, #2f9e5b); }
.mcv-offer-status.is-no { color: var(--text-faint); }
.mcv-offer-accept {
  padding: 4px 10px;
  border: none;
  border-radius: var(--r-pill);
  background: var(--text);
  color: var(--text-inverse);
  font: inherit;
  font-size: 0.7rem;
  font-weight: 700;
  cursor: pointer;
}
.mcv-more { margin-top: 40px; }
.mcv-more-title { margin: 0 0 14px; font-size: 0.68rem; letter-spacing: 2px; text-transform: uppercase; color: var(--text-dim); text-align: center; }
@media (min-width: 641px) {
  .market-crate-view .drop-detail-active .category-card { flex: 0 0 360px; }
}

/* --- Account: display and sound ------------------------------------------
   The theme and sound switches, as labelled rows under the wallet in the
   account column instead of floating over every page. The label names
   what a click switches to (theme) or what's on now (sound). */
.account-prefs { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; }
.account-prefs .account-pref {
  width: 100%;
  height: auto;
  justify-content: flex-start;
  gap: 10px;
  padding: 10px 14px;
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--text-dim);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 700;
}
.account-prefs .account-pref:hover { color: var(--text); background: var(--control-fill-hover); }

/* --- My Items: wider, shorter cards --------------------------------------
   Three across rather than five or six: each card gets a wide picture
   (4:3, so it's bigger without the card getting taller) and its actions on
   one line along the bottom, lined up from card to card. Phones keep
   their two-up grid and two-by-two buttons. */
@media (min-width: 641px) {
  #inventoryGrid { grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); }
  #inventoryGrid .market-item { display: flex; flex-direction: column; }
  #inventoryGrid .market-item-media { aspect-ratio: 4 / 3; }
  #inventoryGrid .market-item-media img { padding: 10px 14px; }
  #inventoryGrid .market-item-body { display: flex; flex-direction: column; flex: 1 1 auto; }
  #inventoryGrid .item-actions {
    display: flex;
    gap: 6px;
    margin-top: auto;
  }
  #inventoryGrid .item-action-btn { flex: 1 1 0; min-width: 0; padding: 9px 4px; font-size: 0.62rem; white-space: nowrap; }
  #inventoryGrid .item-action-btn.item-action-icon { flex: 0 0 34px; }
  /* Sealed crates: the same bottom-aligned row, two buttons. */
  #inventoryGrid .sealed-item .sealed-sub { margin-bottom: 10px; }
}

/* --- Market: Items / Crates ---------------------------------------------
   Sealed boxes are their own tab, so they don't crowd the items. The pill
   behind the active tab is the liquid one (motion.js). */
.market-kind {
  --pill-bg: var(--text);
  display: inline-flex;
  gap: 4px;
  margin-bottom: 14px;
  padding: 4px;
  border-radius: var(--r-pill);
  background: var(--control-fill);
}
.market-kind-btn {
  padding: 8px 18px;
  border: none;
  border-radius: var(--r-pill);
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  transition: color 0.2s ease;
}
.market-kind-btn span { margin-left: 4px; opacity: 0.6; }
.market-kind-btn.active { color: var(--text-inverse); }
.market-kind:not(.has-liquid) .market-kind-btn.active { background: var(--text); }
/* Crates have no brand, size or category, and are always priced. */
.market-shell.is-crates .market-listed-toggle,
.market-shell.is-crates .market-filter-group:has(#marketCategoryFilter),
.market-shell.is-crates .market-filter-group:has(#marketBrandFilter),
.market-shell.is-crates .market-filter-group:has(#marketShoeSizeFilter),
.market-shell.is-crates .market-filter-group:has(#marketClothingSizeFilter) { display: none; }

/* One card per crate: how many are listed, and the cheapest. */
.crate-group { cursor: pointer; }
.crate-group-count {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 1;
  padding: 4px 9px;
  border-radius: var(--r-pill);
  background: var(--text);
  color: var(--text-inverse);
  font-size: 0.72rem;
  font-weight: 800;
}
.crate-group-sub { display: block; font-size: 0.68rem; color: var(--text-dim); }
.crate-group-from { font-size: 0.66rem; font-weight: 600; color: var(--text-dim); }

/* The crate's page: box and buying on the left; Listings / What's inside. */
.mcv-box-wrap { position: relative; width: min(100%, 240px); margin: 0 auto; }
.mcv-box-wrap .mcv-box { width: 100%; margin: 0; }
.mcv-box-wrap .crate-group-count { top: 10px; left: 0; }
.mcv-qty { display: flex; align-items: center; justify-content: center; gap: 10px; }
.mcv-qty .qty-btn:disabled { opacity: 0.35; cursor: default; }
.mcv-qty .qty-btn:disabled:hover { background: var(--control-fill); color: var(--text); }
.mcv-qty-of { font-size: 0.72rem; color: var(--text-faint); }
.mcv-offer-qty { color: var(--text-dim); }
.mcv-panel { display: flex; flex-direction: column; min-height: 0; }
.mcv-tabs { display: flex; gap: 6px; padding: 14px 16px 10px; border-bottom: 1px solid var(--hairline); }
.mcv-tab {
  padding: 7px 14px;
  border: none;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text-dim);
  font: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
}
.mcv-tab span { margin-left: 4px; opacity: 0.6; }
.mcv-tab.active { background: var(--text); color: var(--text-inverse); }
.mcv-listings { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.mcv-listing {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--hairline);
}
.mcv-listing.is-mine { background: color-mix(in srgb, var(--text) 4%, transparent); }
.mcv-listing-who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.mcv-listing-who b { font-size: 0.8rem; color: var(--text); }
.mcv-listing-who > span { display: flex; align-items: center; gap: 6px; font-size: 0.68rem; color: var(--text-dim); }
.mcv-listing-price { font-size: 0.95rem; font-weight: 800; color: var(--text); }
.mcv-row-btn {
  padding: 7px 16px;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  cursor: pointer;
}
.mcv-row-btn.is-buy { border-color: transparent; background: var(--text); color: var(--text-inverse); }
.mcv-row-btn:hover { opacity: 0.85; }
.mcv-panel .prize-browser { padding-top: 12px; }

/* --- Profile pictures ------------------------------------------------------
   Every username shows with its picture (avatarHTML / renderAvatarInto). */
.avatar-gen { background: none; }
.avatar-gen svg { display: block; width: 100%; height: 100%; }
.avatar-xs { width: 16px; height: 16px; }
.avatar-sm { width: 24px; height: 24px; }
.avatar-md { width: 34px; height: 34px; }
.market-item-seller { display: inline-flex; align-items: center; gap: 5px; min-width: 0; }
.listing-seller { display: flex; align-items: center; gap: 6px; }
.offer-row-info .avatar-circle { vertical-align: -3px; }
.leaderboard-row .avatar-circle { margin-right: -6px; }

/* --- A drop's listings: tick the boxes to buy together ------------------- */
button.mcv-listing {
  width: 100%;
  border: none;
  border-bottom: 1px solid var(--hairline);
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s ease;
}
button.mcv-listing:hover { background: color-mix(in srgb, var(--text) 3%, transparent); }
button.mcv-listing.is-sel { background: color-mix(in srgb, var(--accent, #2f9e5b) 10%, transparent); }
.mcv-check {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border: 1.5px solid var(--line-strong);
  border-radius: 6px;
  background: var(--panel);
  display: grid;
  place-items: center;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.mcv-check.is-blank { visibility: hidden; }
.is-sel > .mcv-check { background: var(--text); border-color: var(--text); }
.is-sel > .mcv-check::after {
  content: "";
  width: 9px;
  height: 5px;
  margin-top: -2px;
  border-left: 2px solid var(--text-inverse);
  border-bottom: 2px solid var(--text-inverse);
  transform: rotate(-45deg);
}
.mcv-tabs { align-items: center; }
.mcv-selall {
  margin-left: auto;
  padding: 6px 4px;
  border: none;
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.mcv-selall:hover { color: var(--text); }
.mcv-buy:disabled { opacity: 0.45; cursor: default; transform: none; }

/* Keep every card's quantity and Open on the same line as its
   neighbours', whatever sits above them. */
.category-list .category-card .category-qty { margin-top: auto; padding-top: 12px; }

/* --- Home: scroll-linked motion ------------------------------------------------
   Where the browser can tie an animation to scroll position (view
   timelines), Home's sections move with the scroll instead of fading in
   once: headings rise into place, cards come up and settle in a stagger,
   the grails tip forward out of a slight tilt, and the hero drifts up and
   away as you leave it.
   Scrolling back plays it backwards. Elsewhere (and with reduced motion)
   the one-shot reveal stays. app.js sets .scroll-anim and takes Home's
   data-reveal markers off, so the two never stack. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .scroll-anim #screen-home .home-block-head,
    .scroll-anim #screen-home .home-cta {
      animation: saRise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 90%;
    }
    .scroll-anim #screen-home .home-crate,
    .scroll-anim #screen-home .how-step,
    .scroll-anim #screen-home .home-panel {
      animation: saCard linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 32%;
    }
    .scroll-anim #screen-home :is(.home-crate, .how-step, .home-panel):nth-child(2) { animation-range: entry 12% cover 36%; }
    .scroll-anim #screen-home :is(.home-crate, .how-step, .home-panel):nth-child(3) { animation-range: entry 19% cover 40%; }
    .scroll-anim #screen-home :is(.home-crate, .how-step, .home-panel):nth-child(4) { animation-range: entry 26% cover 44%; }
    .scroll-anim #screen-home .home-grail:not(.is-flipping) {
      animation: saTilt linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 35%;
    }
    /* Its block clips the slide, so the strip waiting 120px to the right
       never widens the page (on a phone that pushed the bottom bar off). */
    .scroll-anim #screen-home .home-block:has(> .home-pulls) { overflow-x: clip; }
    .scroll-anim #screen-home .home-pulls {
      animation: saSlide linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }
    .scroll-anim #screen-home .home-hero-copy,
    .scroll-anim #screen-home .home-hero-media {
      animation: saHeroOut linear both;
      animation-timeline: view();
      animation-range: exit 0% exit 100%;
    }
    .scroll-anim #screen-home .home-hero-media { animation-name: saHeroOutSlow; }
  }
}
@keyframes saRise { from { opacity: 0; translate: 0 36px; } to { opacity: 1; translate: none; } }
@keyframes saCard {
  from { opacity: 0; translate: 0 70px; scale: 0.9; }
  60% { opacity: 1; }
  to { opacity: 1; translate: none; scale: 1; }
}
@keyframes saTilt {
  from { opacity: 0; transform: perspective(1000px) rotateX(22deg) translateY(60px) scale(0.94); }
  to { opacity: 1; transform: none; }
}
@keyframes saSlide { from { opacity: 0; translate: 120px 0; } to { opacity: 1; translate: none; } }
@keyframes saHeroOut { to { opacity: 0; translate: 0 -80px; } }
@keyframes saHeroOutSlow { to { opacity: 0.2; translate: 0 -30px; scale: 0.94; } }

/* ===== Lulu: burn Lulus for Credits ===================================== */

.lulu-head { margin-bottom: 18px; }
.lulu-head .screen-title { margin-bottom: 4px; }
.lulu-lede { margin: 0; font-size: 0.86rem; color: var(--text-dim); }
.lulu-lede b { color: var(--text); font-variant-numeric: tabular-nums; }

/* Nothing connected yet: the art, the two rates, one button. */
.lulu-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 44px 24px 40px;
  border-radius: var(--r-2xl);
  background: var(--panel);
}
.lulu-empty-fan { display: flex; margin-bottom: 22px; }
.lulu-empty-fan img {
  width: 108px;
  height: 108px;
  border-radius: var(--r-lg);
  object-fit: cover;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
  border: 3px solid var(--panel);
}
.lulu-empty-fan img:nth-child(1) { transform: rotate(-8deg) translate(18px, 6px); }
.lulu-empty-fan img:nth-child(2) { position: relative; z-index: 1; transform: translateY(-4px); }
.lulu-empty-fan img:nth-child(3) { transform: rotate(8deg) translate(-18px, 6px); }
.lulu-empty-title { margin: 0 0 16px; font-size: 1.15rem; font-weight: 800; color: var(--text); }
.lulu-rates { display: flex; gap: 8px; margin-bottom: 22px; }
.lulu-rate {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 132px;
  padding: 12px 16px;
  border-radius: var(--r-md);
  background: var(--control-fill);
}
.lulu-rate-n { font-size: 0.72rem; font-weight: 700; color: var(--text-dim); }
.lulu-rate b { font-size: 1rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.lulu-rate-bonus {
  position: absolute;
  top: -8px;
  right: -6px;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  background: var(--open-green);
  color: var(--open-ink);
  font-size: 0.62rem;
  font-weight: 800;
}
.lulu-connect-btn { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px; padding: 13px 26px; }
.lulu-empty-note { margin: 12px 0 0; font-size: 0.74rem; color: var(--text-faint); }

/* The page: Lulus on the left, the burn on the right. */
.lulu-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 20px;
  align-items: start;
}
.lulu-main { min-width: 0; }

.lulu-wallets { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.lulu-wallet-chip,
.lulu-wallet-add {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 14px;
  border: none;
  border-radius: var(--r-pill);
  background: var(--control-fill);
  color: var(--text-dim);
  font: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.lulu-wallet-chip:hover,
.lulu-wallet-add:hover { background: var(--control-fill-hover); color: var(--text); }
.lulu-wallet-chip.active { background: var(--text); color: var(--text-inverse); }
.lulu-chip-n { opacity: 0.6; }
.lulu-chip-x {
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  margin-right: -6px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  font-size: 0.95rem;
  line-height: 1;
  opacity: 0.55;
  cursor: pointer;
}
.lulu-chip-x:hover { opacity: 1; background: var(--inverse-tint); }
.lulu-wallet-add { background: transparent; box-shadow: inset 0 0 0 1.5px var(--line); color: var(--text); }
.lulu-wallet-dot { display: inline-block; width: 12px; height: 12px; border-radius: 50%; flex: 0 0 auto; }

/* Picking: count, select all / clear, and the bar you drag. */
.lulu-selectbar {
  padding: 12px 16px 10px;
  margin-bottom: 12px;
  border-radius: var(--r-lg);
  background: var(--panel);
}
.lulu-selectbar-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.lulu-sel-count { font-size: 0.8rem; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.lulu-sel-count b { color: var(--text); font-size: 0.95rem; }
.lulu-sel-actions { display: flex; gap: 4px; }
.lulu-text-btn {
  padding: 5px 10px;
  border: none;
  border-radius: var(--r-pill);
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
}
.lulu-text-btn:hover { background: var(--control-fill); color: var(--text); }

/* The track is drawn under a bare range input, so it can be cut into sets
   of three: each notch is where another bonus lands. The thumb's centre
   runs from 11px in to 11px from the end, so the track does too. */
.lulu-range { --p: 0; position: relative; height: 30px; }
.lulu-range-track {
  position: absolute;
  left: 11px;
  right: 11px;
  top: 50%;
  height: 8px;
  margin-top: -4px;
  border-radius: var(--r-pill);
  background: var(--track);
}
.lulu-range-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: calc(var(--p) * 100%);
  border-radius: inherit;
  background: var(--text);
}
.lulu-range-tick {
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 3px;
  margin-left: -1.5px;
  background: var(--panel);
}
.lulu-range input {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 30px;
  margin: 0;
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
  cursor: grab;
}
.lulu-range input:active { cursor: grabbing; }
.lulu-range input::-webkit-slider-runnable-track { height: 30px; background: transparent; }
.lulu-range input::-moz-range-track { height: 30px; background: transparent; }
.lulu-range input::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  margin-top: 4px;
  border-radius: 50%;
  background: var(--panel);
  border: 2.5px solid var(--text);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
  transition: transform 0.15s ease;
}
.lulu-range input::-moz-range-thumb {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--panel);
  border: 2.5px solid var(--text);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.lulu-range input:active::-webkit-slider-thumb { transform: scale(1.12); }
.lulu-range input:focus-visible { outline: none; }
.lulu-range input:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px var(--accent-dim); }

/* The Lulus. */
.lulu-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
  user-select: none;
}
.lulu-grid-empty {
  grid-column: 1 / -1;
  margin: 0;
  padding: 36px 16px;
  border-radius: var(--r-lg);
  background: var(--panel);
  text-align: center;
  font-size: 0.84rem;
  color: var(--text-dim);
}
.lulu-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 7px 7px 10px;
  border: none;
  border-radius: var(--r-lg);
  background: var(--panel);
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  box-shadow: inset 0 0 0 2px transparent;
  transition: box-shadow 0.15s ease, transform 0.15s ease, opacity 0.3s ease;
}
.lulu-tile:hover { transform: translateY(-2px); }
.lulu-tile.selected { box-shadow: inset 0 0 0 2px var(--text); }
.lulu-tile-media { position: relative; display: block; aspect-ratio: 1; }
.lulu-tile-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--r-md);
  transition: transform 0.2s ease;
}
.lulu-tile.selected .lulu-tile-media img { transform: scale(0.94); }
.lulu-tile-meta { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 0 4px; }
.lulu-tile-name { font-size: 0.78rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.lulu-tile-meta .lulu-wallet-dot { width: 9px; height: 9px; }
.lulu-tile-check {
  position: absolute;
  top: 13px;
  right: 13px;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.28);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.85);
  color: transparent;
  backdrop-filter: blur(4px);
  transition: background 0.15s ease, color 0.15s ease, transform 0.2s var(--spring);
}
.lulu-tile.selected .lulu-tile-check { background: var(--text); box-shadow: none; color: var(--text-inverse); transform: scale(1.08); }

/* Burning: the picture goes over to a canvas that burns it away in
   pixels (js/lulu.js), with room above for the sparks. */
.lulu-burn-canvas { position: absolute; left: 0; width: 100%; z-index: 2; pointer-events: none; }
.lulu-tile.is-burning { box-shadow: inset 0 0 0 2px rgba(255, 130, 40, 0.9), 0 0 28px -4px rgba(255, 110, 30, 0.55); transform: none; }
.lulu-tile.is-burning .lulu-tile-check { opacity: 0; }
.lulu-tile.is-burnt { opacity: 0; transform: scale(0.92); }
.lulu.is-burning .lulu-main,
.lulu.is-burning .lulu-panel { pointer-events: none; }

/* The burn: what's picked, what it comes to, and the button. */
.lulu-panel {
  position: sticky;
  top: calc(var(--topbar-h) + 16px);
  display: flex;
  flex-direction: column;
  padding: 20px;
  border-radius: var(--r-xl);
  background: var(--panel);
}
.lulu-panel-title { margin: 0 0 12px; font-size: 1rem; font-weight: 800; color: var(--text); }
.lulu-picked {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 8px;
  padding: 8px 10px;
  margin-bottom: 14px;
  border-radius: var(--r-sm);
  background: var(--control-fill);
}
.lulu-picked img {
  display: block;
  width: 38px;
  height: 38px;
  border-radius: var(--r-xs);
  object-fit: cover;
}
/* Every row is exactly a stack's height (46px), whatever is in it, so
   the panel only grows a whole row at a time. */
.lulu-picked > * { flex: 0 0 auto; }
.lulu-picked-empty,
.lulu-picked-more { display: flex; align-items: center; height: 46px; }
@keyframes lulu-pop { from { transform: scale(0.6); opacity: 0; } }

/* A set of three: one card in front, the other two straight behind it,
   each nudged up and right so their edges show, like a squared-up deck. */
.lulu-stack { position: relative; width: 46px; height: 46px; }
.lulu-stack img,
.lulu-ghost {
  position: absolute;
  width: 38px;
  height: 38px;
  border-radius: var(--r-xs);
}
.lulu-stack img { box-shadow: 0 0 0 1.5px var(--panel), 0 2px 6px rgba(0, 0, 0, 0.18); }
/* Where a set's missing cards go. */
.lulu-ghost { box-sizing: border-box; border: 1.5px dashed var(--line-strong); opacity: 0.55; }
.lulu-stack .s0 { left: 0; bottom: 0; z-index: 3; }
.lulu-stack .s1 { left: 4px; bottom: 4px; z-index: 2; }
.lulu-stack .s2 { left: 8px; bottom: 8px; z-index: 1; }
.lulu-stack img.s1 { filter: brightness(0.82); }
.lulu-stack img.s2 { filter: brightness(0.66); }
.lulu-stack img.is-new { animation: lulu-pop 0.25s var(--spring); }
/* Stepping back one place as a newer card lands in front. */
.lulu-stack img.is-shifted { animation: lulu-step-back 0.3s var(--spring); }
@keyframes lulu-step-back { from { transform: translate(-4px, 4px); filter: none; } }
.lulu-picked-more { padding: 0 6px; font-size: 0.74rem; font-weight: 800; color: var(--text-dim); }
.lulu-picked-empty { padding: 0 6px; font-size: 0.74rem; color: var(--text-faint); }

.lulu-rows { display: flex; flex-direction: column; }
.lulu-row {
  display: grid;
  grid-template-columns: 1fr auto 64px;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--hairline);
  font-variant-numeric: tabular-nums;
}
.lulu-row-label { display: flex; flex-direction: column; font-size: 0.82rem; font-weight: 700; color: var(--text); }
.lulu-row-label small { font-size: 0.7rem; font-weight: 600; color: var(--text-faint); }
.lulu-row-calc { font-size: 0.78rem; color: var(--text-dim); }
.lulu-row-val { text-align: right; font-size: 0.9rem; color: var(--text); }
.lulu-set-meter {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  font-size: 0.74rem;
  color: var(--text-dim);
}
.lulu-set-meter b { color: var(--text); }
.lulu-pips { display: inline-flex; gap: 3px; }
.lulu-pips i { width: 14px; height: 6px; border-radius: var(--r-pill); background: var(--track); transition: background 0.2s ease; }
.lulu-pips i.on { background: var(--open-green); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18); }
.lulu-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 12px 14px;
  margin-top: 2px;
  border-radius: var(--r-md);
  background: var(--control-fill);
}
.lulu-total > span { font-size: 0.82rem; font-weight: 700; color: var(--text-dim); }
.lulu-total b { font-size: 1.6rem; font-weight: 800; letter-spacing: -0.5px; color: var(--text); font-variant-numeric: tabular-nums; }
.lulu-total small { font-size: 0.78rem; font-weight: 700; letter-spacing: 0; color: var(--text-dim); }

.lulu-warn {
  display: flex;
  gap: 8px;
  margin: 14px 0 12px;
  font-size: 0.74rem;
  line-height: 1.45;
  color: var(--text-dim);
}
.lulu-warn svg { flex: 0 0 auto; margin-top: 2px; color: #f06a1c; }
.lulu-burn-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  padding: 14px 12px;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 800;
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease;
}
.lulu-burn-btn:not(:disabled):hover { transform: translateY(-2px); }
.lulu-burn-btn:disabled { cursor: default; }

/* The Mercurius rule: one small line, the reason under the (i). */
.lulu-fine {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  margin: 10px 0 0;
  font-size: 0.66rem;
  color: var(--text-faint);
}
.lulu-tip { position: relative; display: inline-grid; place-items: center; cursor: help; color: var(--text-dim); }
.lulu-tip-text {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  z-index: 5;
  width: 220px;
  padding: 9px 11px;
  border-radius: var(--r-sm);
  background: var(--text);
  color: var(--text-inverse);
  font-size: 0.72rem;
  line-height: 1.4;
  text-align: left;
  box-shadow: 0 8px 24px var(--shadow-toast);
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 4px);
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.lulu-tip:hover .lulu-tip-text,
.lulu-tip:focus .lulu-tip-text { opacity: 1; transform: translate(-50%, 0); }

/* Connect a wallet. */
.lulu-connect-card { max-width: 360px; text-align: left; padding: 26px; }
.lulu-connect-card .payment-modal-title { text-align: center; font-size: 1.1rem; font-weight: 800; margin-bottom: 4px; }
.lulu-connect-sub { margin: 0 0 16px; text-align: center; font-size: 0.8rem; color: var(--text-dim); }
.lulu-connect-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.lulu-connect-opt {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: none;
  border-radius: var(--r-md);
  background: var(--control-fill);
  color: var(--text);
  font: inherit;
  font-size: 0.86rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s ease;
}
.lulu-connect-opt:hover { background: var(--control-fill-hover); }
.lulu-connect-icon { display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-sm); background: var(--panel); }
.lulu-connect-name { flex: 1; }
.lulu-connect-state { font-size: 0.72rem; font-weight: 600; color: var(--text-dim); }
.lulu-connect-opt.is-busy .lulu-connect-state::before {
  content: "";
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: 6px;
  vertical-align: -1px;
  border: 2px solid var(--line);
  border-top-color: var(--text);
  border-radius: 50%;
  animation: lulu-spin 0.7s linear infinite;
}
@keyframes lulu-spin { to { transform: rotate(360deg); } }
.lulu-connect-modal.connecting .lulu-connect-opt:not(.is-busy) { opacity: 0.4; }
.lulu-connect-note { margin: 0 0 14px; text-align: center; font-size: 0.68rem; color: var(--text-faint); }

.lulu-dock { display: none; }

@media (max-width: 900px) {
  .lulu-layout { grid-template-columns: 1fr; }
  .lulu-panel { position: static; }
  .lulu-grid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; }
  .lulu-tile { padding: 5px 5px 8px; border-radius: var(--r-md); }
  .lulu-tile-media img { border-radius: var(--r-sm); }
  .lulu-tile-check { top: 10px; right: 10px; width: 20px; height: 20px; }
  .lulu-tile-name { font-size: 0.72rem; }
  /* The running total rides along at the bottom while you pick. */
  .lulu-dock:not([hidden]) {
    position: sticky;
    bottom: calc(var(--bottom-nav-h, 0px) + 12px);
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    margin-top: -8px;
    padding: 10px 10px 10px 16px;
    border: none;
    border-radius: var(--r-pill);
    background: var(--text);
    color: var(--text-inverse);
    font: inherit;
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
    box-shadow: 0 10px 30px var(--shadow-toast);
    cursor: pointer;
  }
  .lulu-dock-total { flex: 1; font-weight: 800; }
  .lulu-dock-go {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 8px 14px;
    border-radius: var(--r-pill);
    background: var(--open-green);
    color: var(--open-ink);
    font-weight: 800;
  }
}
@media (max-width: 640px) {
  .lulu-empty { padding: 32px 16px; }
  .lulu-empty-fan img { width: 84px; height: 84px; }
  .lulu-rate { min-width: 0; flex: 1; }
  .lulu-panel { padding: 16px; }
}

/* Get Lulu: both collections on OpenSea, from the top of the page. */
.lulu-get { position: relative; flex: 0 0 auto; }
.lulu-wallets { align-items: center; }
.lulu-wallets-sep { width: 1px; height: 20px; margin: 0 4px; background: var(--line); }
.lulu-empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.lulu-empty-actions .lulu-get-btn { height: 100%; min-height: 42px; padding: 0 18px; }
.lulu-get-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 13px 0 12px;
  border-radius: var(--r-pill);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 800;
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease;
}
/* The green "the button you want" look (button.deposit-btn), in a pill. */
button.lulu-get-btn.deposit-btn { border-radius: var(--r-pill); }
.lulu-get-btn:hover { transform: translateY(-1px); }
.lulu-get-chev { opacity: 0.6; transition: transform 0.2s ease; }
.lulu-get.open .lulu-get-chev { transform: rotate(180deg); }
.lulu-get-menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 280px;
  padding: 8px;
  border-radius: var(--r-lg);
  background: var(--panel);
  text-align: left;
  box-shadow: 0 18px 50px var(--shadow-toast), 0 0 0 1px var(--hairline);
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px) scale(0.98);
  transform-origin: top left;
  transition: opacity 0.15s ease, transform 0.2s var(--spring);
}
.lulu-get.open .lulu-get-menu { opacity: 1; pointer-events: auto; transform: none; }
.lulu-get-label {
  padding: 4px 8px 2px;
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--text-faint);
}
.lulu-get-opt {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px;
  border-radius: var(--r-md);
  color: var(--text);
  text-decoration: none;
  transition: background 0.15s ease;
}
.lulu-get-opt:hover { background: var(--control-fill); }
.lulu-get-opt img { width: 44px; height: 44px; border-radius: var(--r-sm); object-fit: cover; }
.lulu-get-text { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.lulu-get-text b { font-size: 0.86rem; font-weight: 800; }
.lulu-get-text small { font-size: 0.7rem; color: var(--text-dim); }
.lulu-get-opt > svg { color: var(--text-faint); }
.lulu-get-opt:hover > svg { color: var(--text); }
@media (max-width: 640px) {
  .lulu-get-btn { padding: 0 12px; font-size: 0.74rem; }
  .lulu-get-menu { width: min(280px, calc(100vw - 32px)); }
}

/* ===== Videos: the store and the drops' deck on Home, the packing video,
   and the pop-up player ================================================== */

/* Side by side: the store's video (the main one, bigger) on the left, the
   drops' wheel on the right. The store sets the row's height and the wheel
   fills exactly that, so the two sides match. One above the other on a
   phone, the store first. */
@property --turn {
  syntax: "<angle>";
  inherits: true;
  initial-value: 0deg;
}
.home-videos {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: 20px;
  align-items: stretch;
}
.home-store-card,
.drum-face {
  position: relative;
  display: block;
  padding: 0;
  border: none;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: #0d0d10;
  color: #fff;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.home-store-card { width: 100%; aspect-ratio: 16 / 9; box-shadow: 0 22px 50px -24px rgba(0, 0, 0, 0.5); }
.home-store-card .drop-video,
.drum-face .drop-video { width: 100%; height: 100%; object-fit: cover; display: block; }
.home-store-mark { display: inline-flex; padding: 3px 7px; border-radius: 6px; background: #fff; color: #111; width: max-content; }
.home-store-mark .brand-mark { height: 11px; width: auto; }
.home-store-card .drop-video-ph { padding-bottom: 46px; }
.drum-face .drop-video-ph { padding-bottom: 34px; }
.drum-face .drop-video-ph-play { width: 40px; height: 40px; font-size: 15px; margin-bottom: 2px; }

/* The wheel: videos round the rim of a wheel turning on its side axis,
   seen face on, so the one in front is flat and the ones above and below
   tilt away (darker the further round). The frame fades out top and
   bottom. --turn is a registered angle so the faces' shading follows the
   roll. */
.drop-drum { position: relative; min-width: 0; }
.drum-frame {
  position: absolute;
  inset: 0;
  perspective: var(--persp, 1200px);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 13%, #000 87%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 13%, #000 87%, transparent);
  touch-action: none; /* up-and-down drags roll the wheel */
  user-select: none;
  cursor: grab;
}
.drop-drum.is-dragging .drum-frame { cursor: grabbing; }
.drum {
  --step: calc(360deg / var(--n, 9));
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--cw, 300px);
  height: var(--ch, 170px);
  margin: calc(var(--ch, 170px) / -2) 0 0 calc(var(--cw, 300px) / -2);
  transform-style: preserve-3d;
  transform: translateZ(calc(var(--r, 300px) * -1)) rotateX(var(--turn));
  transition: --turn 0.9s cubic-bezier(0.65, 0, 0.25, 1);
}
.drum.no-anim { transition: none; }
.drum-face {
  --a: calc(var(--i) * var(--step) - var(--turn)); /* round from the front */
  position: absolute;
  inset: 0;
  border-radius: var(--r-lg);
  transform: rotateX(calc(var(--i) * var(--step) * -1)) translateZ(var(--r, 300px));
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  filter: brightness(calc(0.3 + 0.7 * (cos(var(--a)) + 1) / 2));
}
.drum-face.is-front { box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.55); }
.drum-face img, .drum-face video { -webkit-user-drag: none; }
.drum-face:focus-visible { outline: 2px solid var(--text); outline-offset: 3px; }
.drum-face .reel-banner { padding: 26px 12px 12px; }
.drum-face .reel-banner-text b { font-size: 0.9rem; }


/* The banner along each video's foot: which drop it is, and the way in. */
.reel-banner {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 8px;
  padding: 34px 14px 16px;
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.72) 55%);
  color: #fff;
  text-align: left;
}
.reel-banner-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.reel-banner-line {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.75);
}
.reel-banner-line::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--tint);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.18);
}
.reel-banner-text b { font-size: 1.02rem; font-weight: 800; letter-spacing: -0.2px; white-space: nowrap; }
.reel-banner-go {
  flex: 0 0 auto;
  padding: 6px 11px;
  border: none;
  border-radius: var(--r-pill);
  background: #fff;
  color: #111;
  font: inherit;
  font-size: 0.7rem;
  font-weight: 800;
  cursor: pointer;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.3s ease, transform 0.3s ease;
  pointer-events: none;
}
.drum-face.is-front .reel-banner-go,
.reel-banner-go.is-shown { opacity: 1; transform: none; pointer-events: auto; }
.reel-banner-go svg { width: 9px; height: 9px; margin-right: 4px; vertical-align: -1px; }
.reel-banner-go:hover { background: var(--open-green); }

/* How long the front one has left: a thin bar along its very foot. */
.drop-reel-progress {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 8px;
  z-index: 2;
  height: 3px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.22);
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.3s ease;
}
.drum-face.is-front .drop-reel-progress { opacity: 1; }
.drop-reel-progress i {
  display: block;
  height: 100%;
  width: 100%;
  background: #fff;
  transform-origin: left;
  transform: scaleX(var(--p, 0));
}
.drum-face.is-running .drop-reel-progress i { animation: reel-hold var(--hold, 6s) linear forwards; }
@keyframes reel-hold { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* No video yet: a blank frame in the drop's colour, waiting for one. */
.drop-video-ph {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  color: #fff;
  background:
    radial-gradient(120% 90% at 50% 120%, color-mix(in srgb, var(--tint) 55%, transparent), transparent 60%),
    repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.025) 0 14px, transparent 14px 28px),
    #111114;
  text-align: center;
}
.drop-video-ph-play {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  margin-bottom: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.35);
  font-size: 20px;
  backdrop-filter: blur(6px);
}
.drop-video-ph-play svg { margin-left: 3px; }
.drop-video-ph-sub {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

/* Watch, first in a drop's tab row: the same pill as the tier tabs, filled,
   with a play mark, so it reads as the one that does something else. */
.prize-tab.is-watch {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--text);
  color: var(--text-inverse);
}
.prize-tab.is-watch:hover { color: var(--text-inverse); opacity: 0.88; }
.prize-tab.is-watch svg { width: 9px; height: 9px; }

/* The pop-up player. */
.drop-video-modal {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.82);
  backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity 0.25s ease;
}
.drop-video-modal.hidden { display: none; }
.drop-video-modal.visible { opacity: 1; }
.dvm-card {
  width: min(960px, 100%, calc((100vh - 150px) * 16 / 9));
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--panel);
  box-shadow: 0 30px 80px var(--shadow-modal);
  transform-origin: center;
}
.dvm-stage { position: relative; aspect-ratio: 16 / 9; background: #0d0d10; }
.dvm-stage .drop-video { width: 100%; height: 100%; display: block; background: #000; }
.dvm-stage .drop-video-ph-play { width: 72px; height: 72px; font-size: 26px; }
.dvm-bar { display: flex; align-items: center; gap: 12px; padding: 12px 14px 12px 12px; }
.dvm-box { width: 46px; height: 46px; object-fit: contain; flex: 0 0 auto; }
.dvm-box:not([src]) { visibility: hidden; }
.dvm-title { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; font-size: 0.95rem; font-weight: 800; color: var(--text); }
.dvm-title .category-tier-name { font-weight: 800; }
.dvm-title small { font-size: 0.72rem; font-weight: 600; color: var(--text-dim); }
.dvm-close {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 50%;
  background: var(--control-fill);
  color: var(--text);
  cursor: pointer;
}
.dvm-close:hover { background: var(--control-fill-hover); }
.dvm-bar .drop-reel-btn {
  height: 34px;
  padding: 0 14px;
  border: none;
  border-radius: var(--r-pill);
  background: var(--text);
  color: var(--text-inverse);
  font: inherit;
  font-size: 0.76rem;
  font-weight: 800;
  cursor: pointer;
}

@media (max-width: 760px) {
  .home-videos { grid-template-columns: 1fr; }
  .drop-drum { aspect-ratio: 4 / 3; }
}
@media (max-width: 640px) {
  .reel-banner { padding: 26px 10px 13px; }
  .reel-banner-line { font-size: 0.56rem; }
  .reel-banner-text b { font-size: 0.86rem; }
  .reel-banner-go { padding: 5px 10px; font-size: 0.66rem; }
  .drop-video-modal { padding: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .drum { transition: none; }
}

/* How it works, 2: Cash back and Keep, under the fanned pieces. */
.how-art-choices {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: 8px;
}
.how-art-choices .how-exit { padding: 8px 12px; font-size: 0.74rem; box-shadow: 0 8px 20px -10px rgba(0, 0, 0, 0.35); }
/* How it works, 3: the packing video fills the picture's place. */
.how-art-video { display: flex; align-items: center; }
.how-video {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 100%;
  padding: 0;
  border: none;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #0d0d10;
  cursor: pointer;
  box-shadow: 0 18px 40px -22px rgba(0, 0, 0, 0.5);
}
.how-video .drop-video { width: 100%; height: 100%; object-fit: cover; display: block; }
.how-video .drop-video-ph-play { width: 44px; height: 44px; font-size: 16px; }
.how-video-tag {
  position: absolute;
  left: 10px;
  bottom: 10px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px 5px 8px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.92);
  color: #111;
  font-size: 0.68rem;
  font-weight: 800;
}
.how-video-tag svg { width: 15px; height: 15px; }
/* The pop-up's picture when it isn't a drop's box: an icon, or the
   store's mark. */
.dvm-icon { display: grid; place-items: center; width: 46px; height: 46px; border-radius: var(--r-sm); background: var(--control-fill); color: var(--text); flex: 0 0 auto; }
.dvm-brand { display: inline-flex; }
.dvm-brand .brand-mark { height: 16px; width: auto; }

/* ===== Demo: one crate's page, as the team's other build lays it out ===== */

.dm {
  --dm-display: "Archivo Black", "Anton", system-ui, sans-serif; /* their Druk Wide falls back to this */
  --dm-grail: linear-gradient(100deg, oklch(0.879 0.162 90.9) 0%, oklch(0.783 0.168 66.2) 50%, oklch(0.695 0.223 355.3) 100%);
  --dm-epic: oklch(0.606 0.219 292.7);
  --dm-rare: oklch(0.623 0.188 259.8);
  --dm-uncommon: oklch(0.6989 0.1391 168.39);
  --dm-common: oklch(0.661 0.009 106.6);
  --dm-grail-solid: oklch(0.783 0.168 66.2);
  --dm-card: var(--panel);
  --dm-hair: color-mix(in srgb, var(--text) 12%, transparent);
  --dm-rail-w: 240px;
}
.dm .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.dm-t-grail { --tc: var(--dm-grail-solid); }
.dm-t-epic { --tc: var(--dm-epic); }
.dm-t-rare { --tc: var(--dm-rare); }
.dm-t-uncommon { --tc: var(--dm-uncommon); }
.dm-t-common { --tc: var(--dm-common); }

/* The page and its rail: the rail holds to the right edge while the page
   scrolls past it. */
.dm-layout { display: grid; grid-template-columns: minmax(0, 1fr) var(--dm-rail-w); gap: 32px; align-items: start; }
.dm-layout.rail-closed { grid-template-columns: minmax(0, 1fr); }
.dm-main { min-width: 0; }
.dm-rail {
  position: sticky;
  top: calc(var(--topbar-h) + 12px);
  max-height: calc(100vh - var(--topbar-h) - 24px);
  overflow-y: auto;
  scrollbar-width: none;
  padding-bottom: 12px;
}
.dm-rail::-webkit-scrollbar { display: none; }
.dm-layout.rail-closed .dm-rail { display: none; }
.dm-rail-reopen {
  display: none;
  position: fixed;
  right: 20px;
  top: calc(var(--topbar-h) + 16px);
  z-index: 5;
  align-items: center;
  gap: 7px;
  padding: 8px 14px;
  border: 1px solid var(--dm-hair);
  border-radius: var(--r-pill);
  background: var(--dm-card);
  color: var(--text);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
}
.dm-layout.rail-closed .dm-rail-reopen { display: inline-flex; }

/* ---- Hero: the crate on the left; its name, price, open and odds on the right. */
.dm-hero { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); gap: 24px; align-items: center; min-height: 600px; }
.dm-hero-media { position: relative; align-self: stretch; min-height: 420px; }
.dm-back {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px;
  border: none;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.dm-back:hover { opacity: 0.7; }
.dm-box { position: absolute; inset: 40px 0 0; width: 100%; height: calc(100% - 40px); display: block; }
.dm-hero-copy { min-width: 0; }
.dm-pill {
  display: inline-block;
  padding: 4px 10px;
  border: 1px solid var(--dm-hair);
  border-radius: var(--r-pill);
  background: var(--dm-card);
  font-size: 0.74rem;
  font-weight: 600;
}
.dm-title {
  margin: 14px 0 10px;
  font-family: var(--dm-display);
  font-size: clamp(2rem, 3.6vw, 3.24rem);
  line-height: 0.95;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  color: var(--text);
  overflow-wrap: anywhere;
}
.dm-blurb { margin: 0 0 18px; max-width: 480px; font-size: 0.98rem; line-height: 1.5; color: var(--text-dim); }
.dm-buyline { display: flex; align-items: flex-end; gap: 22px; margin-bottom: 12px; }
.dm-price { display: flex; align-items: baseline; gap: 8px; }
.dm-price b { font-family: var(--dm-display); font-size: 1.88rem; font-weight: 400; line-height: 1; color: var(--text); }
.dm-price span { font-size: 0.74rem; color: var(--text-dim); }
.dm-open-row { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px; }
.dm-qty {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 52px;
  padding: 0 7px 0 10px;
  border: 1.5px solid var(--text);
  border-radius: var(--r-pill);
  background: var(--dm-card);
}
.dm-qty button {
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 1.2rem;
  cursor: pointer;
}
.dm-qty button:hover { background: var(--control-fill); }
.dm-qty b { min-width: 26px; text-align: center; font-size: 1.05rem; font-variant-numeric: tabular-nums; }
.dm-qty .dm-max {
  width: auto;
  height: 32px;
  margin-left: 6px;
  padding: 0 12px;
  border: 1.5px solid var(--dm-hair);
  border-radius: var(--r-pill);
  font-size: 0.8rem;
  font-weight: 600;
}
.dm-qty .dm-max.active { background: var(--text); color: var(--text-inverse); border-color: var(--text); }
.dm-open {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: 52px;
  padding: 0 22px;
  border: 1px solid #000;
  border-radius: var(--r-pill);
  background: oklch(0.8751 0.2471 147.45);
  color: oklch(0.256 0.062 150.2);
  font: inherit;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.15s ease, filter 0.15s ease;
}
.dm-open:hover { transform: translateY(-1px); filter: brightness(0.97); }
.dm-open-price { display: inline-flex; align-items: center; gap: 10px; }
.dm-paid { margin: 8px 0 18px; font-size: 0.74rem; color: var(--text-dim); }

/* The five tiers: range, share of opens, and a bar of that share. */
.dm-tiers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; max-width: 500px; }
.dm-tier {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 12px;
  border: 1px solid var(--tc);
  border-radius: 16px;
  background: var(--dm-card);
}
.dm-tier.dm-t-grail { border: 1px solid transparent; background: linear-gradient(var(--dm-card), var(--dm-card)) padding-box, var(--dm-grail) border-box; }
.dm-tier-name { display: inline-flex; align-items: center; gap: 6px; font-size: 0.86rem; font-weight: 700; color: var(--tc); }
.dm-tier-range { font-size: 0.72rem; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.dm-tier-pct { font-family: var(--dm-display); font-size: 1.5rem; font-weight: 400; line-height: 1.1; color: var(--tc); }
.dm-t-grail .dm-tier-pct { background: var(--dm-grail); -webkit-background-clip: text; background-clip: text; color: transparent; }
.dm-tier-bar { height: 4px; margin-top: 4px; border-radius: var(--r-pill); background: var(--dm-hair); overflow: hidden; }
.dm-tier-bar i { display: block; height: 100%; border-radius: inherit; background: var(--tc); }
.dm-t-grail .dm-tier-bar i { background: var(--dm-grail); }

/* ---- Sections */
.dm-sec { margin-top: 48px; }
.dm-sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 18px; }
.dm-sec-head .dm-sub { margin-bottom: 0; }
.dm-h2 { margin: 0 0 8px; font-family: var(--dm-display); font-size: 1.25rem; font-weight: 400; line-height: 1; text-transform: uppercase; color: var(--text); }
.dm-sub { margin: 0 0 18px; font-size: 0.92rem; color: var(--text-dim); }

/* A tier chip: outlined in the tier's colour; the top grail's is filled
   with its gradient. */
.dm-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 24px;
  padding: 0 9px 0 6px;
  border: 1px solid currentColor;
  border-radius: var(--r-pill);
  background: var(--dm-card);
  color: var(--tc);
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
}
.dm-chip.is-top,
.dm-t-grail > .dm-card-top .dm-chip { border: none; background: var(--dm-grail); color: #fff; padding: 0 11px 0 10px; }
.dm-card-top { position: absolute; left: 12px; right: 12px; top: 12px; z-index: 2; display: flex; align-items: center; gap: 6px; }
.dm-ago { margin-left: auto; font-size: 0.76rem; color: var(--text-dim); }
.dm-img { display: grid; place-items: center; aspect-ratio: 1; overflow: hidden; border-radius: 12px; }
.dm-img img { width: 100%; height: 100%; object-fit: contain; padding: 8%; mix-blend-mode: multiply; }
/* Dark: the product shots keep their white tiles rather than blending. */
:root:not([data-theme="light"]) .dm-img { background: #fff; }
:root:not([data-theme="light"]) .dm-img img { mix-blend-mode: normal; }
.dm-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.86rem; font-weight: 500; color: var(--text); }
.dm-money { font-family: var(--dm-display); font-size: 1.35rem; font-weight: 400; line-height: 1; color: var(--text); font-variant-numeric: tabular-nums; }

/* Pulled from this crate: a strip of cards you can drag. */
.dm-strip {
  display: flex;
  gap: 12px;
  margin: 0 -4px;
  padding: 4px 4px 10px;
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  cursor: grab;
  user-select: none;
}
.dm-strip::-webkit-scrollbar { display: none; }
.dm-strip.is-dragging { cursor: grabbing; scroll-snap-type: none; }
.dm-pull {
  position: relative;
  flex: 0 0 200px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 44px 12px 12px;
  border: 1.5px solid var(--text);
  border-radius: 20px;
  background: var(--dm-card);
  scroll-snap-align: start;
}
/* Every card the same width (a long name truncates instead of widening its
   card) and every photo on the same square tile. */
.dm-pull { width: 200px; min-width: 0; }
.dm-pull .dm-img { width: 100%; aspect-ratio: 1; height: auto; background: var(--surface-2); }
.dm-pull .dm-img img { padding: 10%; }
.dm-pull .dm-money { font-size: 1.25rem; }
.dm-pull.is-new { animation: dm-in 0.5s cubic-bezier(0.2, 0.8, 0.2, 1); }
@keyframes dm-in { from { opacity: 0; transform: translateX(-24px) scale(0.96); } }

/* What could be inside: filters, and the grid. */
.dm-filters { display: flex; flex-wrap: wrap; gap: 6px; }
.dm-filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 13px;
  border: 1px solid var(--tc, var(--dm-hair));
  border-radius: var(--r-pill);
  background: var(--dm-card);
  color: var(--tc, var(--text));
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}
.dm-filter.active { background: var(--tc, var(--text)); border-color: var(--tc, var(--text)); color: #fff; }
.dm-filter:not(.dm-t-common):not(.dm-t-grail):not(.dm-t-epic):not(.dm-t-rare):not(.dm-t-uncommon).active { color: var(--text-inverse); }
.dm-filter.dm-t-grail.active { background: var(--dm-grail); border-color: transparent; }
.dm-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; margin: 0; padding: 0; list-style: none; }
.dm-piece {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--tc);
  border-radius: 20px;
  background: var(--dm-card);
  animation: dm-up 0.4s ease both;
}
@keyframes dm-up { from { opacity: 0; transform: translateY(8px); } }
.dm-piece-text { display: grid; gap: 4px; min-width: 0; }
.dm-piece.dm-t-grail { border-color: transparent; background: linear-gradient(var(--dm-card), var(--dm-card)) padding-box, var(--dm-grail) border-box; }
/* The top grail: across two columns, its picture beside its name and a
   bigger price, a warm glow behind it and a sheen that passes over. */
.dm-piece.is-top { grid-column: span 2; flex-direction: row; align-items: center; gap: 20px; padding: 20px; overflow: hidden; box-shadow: 0 18px 50px -18px color-mix(in srgb, oklch(0.783 0.168 66.2) 55%, transparent); }
.dm-piece.is-top .dm-card-top { left: 20px; right: 20px; top: 20px; }
.dm-piece.is-top .dm-img { flex: 0 0 52%; }
.dm-piece.is-top .dm-piece-text { flex: 1; gap: 8px; }
.dm-piece.is-top .dm-name { white-space: normal; font-size: 1.12rem; }
.dm-piece.is-top .dm-money { font-size: 2.12rem; background: var(--dm-grail); -webkit-background-clip: text; background-clip: text; color: transparent; }
.dm-sheen {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, 0.55) 48%, transparent 60%);
  transform: translateX(-100%);
  animation: dm-sheen 4.5s ease-in-out infinite 1s;
}
@keyframes dm-sheen { 0%, 70% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }

/* The rail: today's top pull, then live pulls. */
.dm-rail-head { display: flex; align-items: center; justify-content: space-between; margin: 4px 0 8px; }
.dm-rail-head.is-live { margin-top: 18px; }
.dm-rail-title { display: inline-flex; align-items: center; gap: 6px; font-size: 0.86rem; font-weight: 700; color: var(--text); }
.dm-rail-title svg { color: var(--dm-grail-solid); }
.dm-rail-title small { font-size: 0.74rem; font-weight: 500; color: var(--text-dim); }
.dm-rail-btns { display: inline-flex; gap: 2px; }
.dm-rail-btns button { display: grid; place-items: center; width: 26px; height: 26px; border: none; border-radius: 50%; background: none; color: var(--text-dim); cursor: pointer; }
.dm-rail-btns button:hover { background: var(--control-fill); color: var(--text); }
.dm-live-dot { width: 7px; height: 7px; border-radius: 50%; background: oklch(0.72 0.19 147); box-shadow: 0 0 0 3px color-mix(in srgb, oklch(0.72 0.19 147) 25%, transparent); animation: dm-pulse 1.8s ease-in-out infinite; }
@keyframes dm-pulse { 50% { box-shadow: 0 0 0 6px transparent; } }
.dm-top {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 12px;
  border: 1.5px solid var(--text);
  border-radius: 18px;
  background: var(--dm-card);
  text-align: center;
}
.dm-top-rank { position: absolute; top: 8px; left: 12px; font-family: var(--dm-display); font-size: 0.9rem; color: var(--text); }
.dm-top .dm-img { width: 100%; aspect-ratio: auto; height: 120px; }
.dm-top .dm-name { max-width: 100%; font-weight: 600; }
.dm-top .dm-money { font-size: 1.5rem; }
.dm-top small { font-size: 0.72rem; color: var(--text-dim); }
.dm-live { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.dm-live-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px 7px 7px;
  border: 1.5px solid var(--text);
  border-radius: 14px;
  background: var(--dm-card);
}
.dm-live-row .dm-img { flex: 0 0 44px; width: 44px; height: 44px; border-radius: 9px; }
.dm-live-row .dm-img img { padding: 4%; }
.dm-live-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 0.72rem; color: var(--text-dim); }
.dm-live-text .dm-name { font-size: 0.78rem; font-weight: 600; }
.dm-live-text b { color: var(--text); }
.dm-live-row.is-new { animation: dm-drop 0.5s cubic-bezier(0.2, 0.8, 0.2, 1); }
@keyframes dm-drop { from { opacity: 0; transform: translateY(-14px); } }

/* What came out of an open. */
.dm-reveal {
  position: fixed;
  inset: 0;
  z-index: 110;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 0.22s ease;
}
.dm-reveal.hidden { display: none; }
.dm-reveal.visible { opacity: 1; }
.dm-reveal-card {
  width: min(880px, 100%);
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  padding: 26px;
  border-radius: var(--r-xl);
  background: var(--bg);
  text-align: center;
  transform: scale(0.94);
  transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.dm-reveal.visible .dm-reveal-card { transform: none; }
.dm-reveal-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; margin: 18px 0 0; padding: 0; list-style: none; text-align: left; }
.dm-reveal-list.is-one { grid-template-columns: minmax(0, 300px); justify-content: center; }
.dm-reveal-list .dm-piece { padding-top: 44px; animation: dm-pop 0.45s cubic-bezier(0.2, 0.8, 0.2, 1) both; animation-delay: calc(var(--i) * 70ms); }
@keyframes dm-pop { from { opacity: 0; transform: scale(0.8) translateY(10px); } }
.dm-reveal-total { margin: 16px 0 0; font-weight: 700; color: var(--text); }
.dm-reveal-note { margin: 8px 0 0; font-size: 0.76rem; color: var(--text-dim); }
.dm-reveal-actions { display: flex; justify-content: center; gap: 10px; margin-top: 18px; }
.dm-reveal-actions .dm-open { min-width: 260px; }
.dm-ghost { height: 52px; padding: 0 24px; border: 1.5px solid var(--text); border-radius: var(--r-pill); background: none; color: var(--text); font: inherit; font-weight: 700; cursor: pointer; }

@media (max-width: 1180px) {
  .dm-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1000px) {
  .dm-layout { grid-template-columns: minmax(0, 1fr); }
  .dm-rail { position: static; max-height: none; overflow: visible; }
  .dm-rail-btns, .dm-rail-reopen { display: none !important; }
  .dm-layout.rail-closed .dm-rail { display: block; }
  .dm-live { flex-direction: row; overflow-x: auto; scrollbar-width: none; }
  .dm-live-row { flex: 0 0 230px; }
  .dm-top { max-width: 260px; }
}
@media (max-width: 760px) {
  .dm-hero { grid-template-columns: minmax(0, 1fr); min-height: 0; }
  .dm-hero-media { min-height: 300px; }
  .dm-buyline { flex-wrap: wrap; }
  .dm-open-row { grid-template-columns: minmax(0, 1fr); }
  .dm-qty { justify-content: space-between; }
  .dm-tiers { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: none; }
  .dm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .dm-piece.is-top { flex-direction: column; align-items: stretch; padding: 12px; }
  .dm-piece.is-top .dm-card-top { left: 12px; right: 12px; top: 12px; }
  .dm-piece.is-top .dm-money { font-size: 1.6rem; }
  .dm-sec { margin-top: 36px; }
  .dm-pull { flex-basis: 170px; width: 170px; }
  .dm-reveal-actions { flex-direction: column; }
  .dm-reveal-actions .dm-open { min-width: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .dm-sheen, .dm-live-dot, .fl-tilt { animation: none; }
}

/* ===== Odds: boxes built from collectors' vaulted pieces ================= */

/* The three boxes, as tabs: price, and how much of its run is left. */
.od-boxes { display: flex; gap: 8px; margin-bottom: 18px; flex-wrap: wrap; }
.od-box-tab {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 10px 18px;
  border: 1.5px solid var(--dm-hair);
  border-radius: var(--r-lg);
  background: var(--dm-card);
  color: var(--text);
  font: inherit;
  font-size: 0.82rem;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.od-box-tab b { font-family: var(--dm-display); font-size: 1.2rem; font-weight: 400; line-height: 1; }
.od-box-tab span { font-size: 0.72rem; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.od-box-tab:hover { border-color: var(--text); }
.od-box-tab.active { border-color: var(--text); background: var(--text); color: var(--text-inverse); }
.od-box-tab.active span { color: color-mix(in srgb, var(--text-inverse) 70%, transparent); }

.od-hero { min-height: 560px; }

/* The run: ten cells, filled as boxes are taken (yours in green). */
.od-meter { display: flex; align-items: center; gap: 4px; margin: 4px 0 8px; }
.od-meter i { flex: 1; max-width: 46px; height: 10px; border-radius: var(--r-pill); background: var(--dm-hair); transition: background 0.3s ease; }
.od-meter i.is-taken { background: var(--text); }
.od-meter i.is-mine { background: oklch(0.72 0.19 147); }
.od-run-line { margin: 0 0 6px; font-size: 0.82rem; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.od-run-line b { color: var(--text); }
.od-clock { font-weight: 700; color: var(--text); }
.od-fallback { margin: 0; max-width: 500px; font-size: 0.74rem; line-height: 1.45; color: var(--text-dim); }

/* A piece in the run: who put it in, its odds, and once pulled, who by. */
.od-grid .dm-piece { gap: 8px; }
.od-creator { display: inline-flex; align-items: center; gap: 6px; min-width: 0; font-size: 0.74rem; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.od-creator .avatar-circle { width: 18px; height: 18px; flex: 0 0 auto; }
.od-you { padding: 1px 8px; border-radius: var(--r-pill); background: oklch(0.8751 0.2471 147.45); color: oklch(0.256 0.062 150.2); font-weight: 800; }
.dm-piece.is-mine { box-shadow: 0 0 0 2px oklch(0.72 0.19 147); }
.od-to { font-size: 0.72rem; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dm-pull.is-yours { box-shadow: 0 0 0 2px oklch(0.72 0.19 147); }
.od-reveal-sub { margin: 0; font-size: 0.86rem; color: var(--text-dim); }
.od-mine-badge { display: grid; place-items: center; flex: 0 0 52px; width: 52px; height: 52px; border-radius: 10px; background: var(--text); color: var(--text-inverse); font-family: var(--dm-display); font-size: 1.1rem; }
.od-mine-row.is-up, .od-mine-row.is-sold { border-color: oklch(0.72 0.19 147); }
.od-mine-row.is-sold .dm-money { color: oklch(0.5 0.15 147); }
.od-empty { padding: 28px 16px; color: var(--text-dim); font-size: 0.86rem; list-style: none; }

/* Put an item in: your pieces in the boxes, then your vault. */
.od-sell .dm-sub b { color: var(--text); }
.od-mine { display: flex; flex-direction: column; gap: 8px; margin: 0 0 16px; padding: 0; list-style: none; }
.od-mine-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 14px 8px 8px;
  border: 1.5px solid var(--dm-hair);
  border-radius: 16px;
  background: var(--dm-card);
}
.od-mine-row .dm-img { flex: 0 0 52px; width: 52px; height: 52px; border-radius: 10px; }
.od-mine-text { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 0.78rem; color: var(--text-dim); }
.od-mine-text b { color: var(--text); }
.od-mine-row .dm-money { font-size: 1.1rem; }
.od-vaults { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; margin: 0; padding: 0; list-style: none; }
.od-vault {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  border: 1px solid var(--dm-hair);
  border-radius: 18px;
  background: var(--dm-card);
}
.od-vault .dm-img { height: 120px; aspect-ratio: auto; }
.od-vault-row { display: flex; justify-content: space-between; gap: 8px; font-size: 0.76rem; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.od-vault-row b { color: var(--text); }
.od-vault-row.is-pay b { color: oklch(0.5 0.15 147); }
.od-vault-row.is-cash { opacity: 0.75; }
.od-put {
  margin-top: 4px;
  height: 36px;
  border: 1px solid #000;
  border-radius: var(--r-pill);
  background: oklch(0.8751 0.2471 147.45);
  color: oklch(0.256 0.062 150.2);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
}
.od-put:hover { filter: brightness(0.96); }
.od-vault.is-off .dm-img, .od-vault.is-off .dm-name { opacity: 0.5; }
.od-off { margin-top: 4px; padding: 8px 0; text-align: center; font-size: 0.74rem; color: var(--text-dim); }
.od-link { padding: 0; border: none; background: none; color: var(--text); font: inherit; font-weight: 700; text-decoration: underline; cursor: pointer; }

/* No rail on Odds: the page has the full width. */
.od-layout { grid-template-columns: minmax(0, 1fr); }

@media (max-width: 760px) {
  .od-hero { min-height: 0; }
  .od-box-tab { flex: 1; padding: 8px 12px; }
  .od-vaults { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ===== Odds in My Items, and the box chooser ============================== */

/* A box from a completed run, waiting to be opened. */
.odds-ready .market-item-media { display: grid; place-items: center; background: color-mix(in srgb, oklch(0.8751 0.2471 147.45) 18%, var(--panel)); }
.odds-ready-box { width: 72%; height: 72%; object-fit: contain; }
.item-ready-flag,
.item-box-flag {
  position: absolute;
  top: 10px;
  left: 10px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  font-size: 0.68rem;
  font-weight: 800;
}
.item-ready-flag { background: oklch(0.8751 0.2471 147.45); color: oklch(0.256 0.062 150.2); border: 1px solid #000; animation: ready-pulse 2s ease-in-out infinite; }
@keyframes ready-pulse { 50% { box-shadow: 0 0 0 5px color-mix(in srgb, oklch(0.8751 0.2471 147.45) 35%, transparent); } }
.odds-open-btn { flex: 1; background: var(--open-green) !important; color: var(--open-ink) !important; border: 1px solid #000 !important; font-weight: 800; }
/* An item held in a box: locked, its trading actions gone. */
.item-box-flag { background: var(--text); color: var(--text-inverse); }
.item-box-flag svg { width: 11px; height: 11px; }
.market-item.is-boxed .market-item-media img { opacity: 0.55; filter: grayscale(0.3); }
.item-box-note { display: inline-flex; align-items: center; gap: 6px; font-size: 0.72rem; color: var(--text-dim); }
.item-box-note svg { width: 12px; height: 12px; flex: 0 0 auto; }
/* The avatar's dot while a box is ready. */
.avatar-btn { position: relative; }
.avatar-btn.has-ready::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: oklch(0.72 0.19 147);
  box-shadow: 0 0 0 2px var(--bg);
}

/* Odds: ready boxes and take-backs in Your boxes / Put an item in. */
.od-ready { color: oklch(0.5 0.15 147); }
.od-mine-row.is-ready { border-color: oklch(0.72 0.19 147); }
.od-mine-badge svg { color: inherit; }
.od-go-open { height: 38px; padding: 0 16px; font-size: 0.8rem; flex: 0 0 auto; }
.od-takeback { height: 34px; padding: 0 14px; font-size: 0.76rem; flex: 0 0 auto; }

/* Put it in a box: the chooser, from My Items. */
.od-chooser { width: min(520px, 100%); text-align: left; }
.od-chooser .dm-h2 { text-align: center; }
.od-chooser-item { display: flex; align-items: center; gap: 12px; margin: 14px 0; padding: 10px; border: 1px solid var(--dm-hair); border-radius: 16px; background: var(--dm-card); }
.od-chooser-item .dm-img { flex: 0 0 60px; width: 60px; height: 60px; border-radius: 10px; }
.od-chooser-item > span:last-child { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.od-chooser-worth { font-size: 0.76rem; color: var(--text-dim); }
.od-chooser-opts { display: grid; gap: 8px; }
.od-chooser-opt {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1.5px solid var(--text);
  border-radius: 16px;
  background: var(--dm-card);
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s ease;
}
.od-chooser-opt b { font-family: var(--dm-display); font-size: 1.1rem; font-weight: 400; }
.od-chooser-opt span { font-size: 0.8rem; color: var(--text-dim); }
.od-chooser-opt strong { color: oklch(0.5 0.15 147); }
.od-chooser-opt:hover:not(:disabled) { background: color-mix(in srgb, oklch(0.8751 0.2471 147.45) 18%, var(--dm-card)); }
.od-chooser-opt:disabled { opacity: 0.45; border-color: var(--dm-hair); cursor: not-allowed; }

/* Odds: what you could pull, by tier. */
.od-tiers { margin: 16px 0 12px; max-width: 520px; }
.od-tiers-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; font-size: 0.86rem; color: var(--text-dim); }
.od-tiers-toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 6px;
  border: none;
  border-radius: 8px;
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.86rem;
  cursor: pointer;
}
.od-tiers-toggle:hover { color: var(--text); background: var(--control-fill); }
.od-tier-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.od-tier {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1.5px solid var(--tc);
  border-radius: 16px;
  background: var(--dm-card);
  animation: dm-up 0.3s ease both;
}
.od-tier-top { display: flex; align-items: center; justify-content: space-between; }
.od-tier-name { display: inline-flex; align-items: center; gap: 7px; font-size: 0.92rem; font-weight: 700; color: var(--tc); }
.od-tier-pct { font-size: 0.84rem; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.od-tier-range { font-size: 1.05rem; font-variant-numeric: tabular-nums; color: var(--text); }
.od-tier-range b { font-weight: 800; }
.od-tier-range i { font-style: normal; font-size: 0.82rem; color: var(--text-dim); margin: 0 2px; }
/* The lower tiers sit back a little. */
.od-tier.dm-t-uncommon .od-tier-range b,
.od-tier.dm-t-common .od-tier-range b { font-weight: 600; color: var(--text-dim); }

/* ---- Notification bell -------------------------------------------------- */
.bell-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: 0 0 auto;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-dim);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.bell-btn:hover, .bell-btn.active { background: var(--control-fill-hover); color: var(--text); }
.bell-btn .icon { vertical-align: 0; }
.bell-count {
  position: absolute;
  top: -3px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: oklch(0.63 0.22 27);
  color: #fff;
  font-size: 0.58rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--bg);
}
.bell-count.hidden { display: none; }

.bell-panel {
  position: fixed;
  z-index: 210;
  display: flex;
  flex-direction: column;
  width: min(360px, calc(100vw - 24px));
  max-height: min(480px, calc(100vh - var(--topbar-h) - 40px));
  border-radius: var(--r-lg);
  background: var(--panel);
  box-shadow: 0 18px 50px var(--shadow-toast), 0 0 0 1px var(--hairline);
  overflow: hidden;
  animation: bell-in 0.18s var(--spring);
  transform-origin: top right;
}
.bell-panel[hidden] { display: none; }
@keyframes bell-in { from { opacity: 0; transform: translateY(-4px) scale(0.98); } }
.bell-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px 10px;
  font-size: 0.85rem;
  border-bottom: 1px solid var(--hairline);
}
.bell-clear {
  border: none;
  background: none;
  padding: 2px 0;
  font: inherit;
  font-size: 0.72rem;
  color: var(--text-dim);
  cursor: pointer;
}
.bell-clear:hover { color: var(--text); }
.bell-clear[hidden] { display: none; }
.bell-list {
  list-style: none;
  margin: 0;
  padding: 6px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.bell-item {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  gap: 10px;
  align-items: start;
  padding: 10px;
  border-radius: 10px;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--text);
}
.bell-item.is-new { background: var(--surface-2); }
.bell-item-icon {
  position: relative;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-dim);
}
.bell-item.is-new .bell-item-icon { background: var(--panel); color: var(--text); }
.bell-item.is-new .bell-item-icon::after {
  content: "";
  position: absolute;
  top: -1px;
  right: -1px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: oklch(0.63 0.22 27);
  box-shadow: 0 0 0 2px var(--surface-2);
}
.bell-item-icon svg { width: 14px; height: 14px; }
.bell-item-time { font-size: 0.66rem; color: var(--text-dim); white-space: nowrap; padding-top: 2px; }
.bell-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 32px 24px;
  text-align: center;
  font-size: 0.78rem;
  color: var(--text-dim);
}
.bell-empty svg { width: 22px; height: 22px; opacity: 0.6; }
@media (max-width: 640px) {
  .bell-btn { width: 28px; height: 28px; }
  .bell-panel { right: 12px !important; }
}

/* Odds: the waitlist that gates putting an item in. */
.od-put { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.od-put.is-waiting { background: var(--surface-2); border-color: var(--line-strong, var(--hairline)); color: var(--text); }
.od-wait { text-align: left; }
.od-wait .dm-h2 { margin-top: 10px; }
.od-wait-live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: oklch(0.72 0.19 147 / 0.14);
  color: oklch(0.45 0.15 147);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.od-wait-live i { width: 7px; height: 7px; border-radius: 50%; background: oklch(0.65 0.2 147); animation: od-live 1.6s ease-in-out infinite; }
@keyframes od-live { 50% { opacity: 0.35; } }
.od-wait-lead { margin: 8px 0 14px; font-size: 0.86rem; line-height: 1.5; color: var(--text-dim); }
.od-wait .od-chooser-worth b { color: oklch(0.5 0.15 147); }
.od-wait .dm-reveal-actions { display: flex; gap: 8px; }
.od-wait .dm-reveal-actions > * { flex: 1; }
.od-wait .dm-reveal-actions .dm-open { min-width: 0; justify-content: center; }

/* Odds: dev-mode math, an info button beside the run number. */
.od-hero-tags { display: flex; align-items: center; gap: 8px; position: relative; z-index: 5; }
.od-math { position: relative; }
.od-math-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px 4px 8px;
  border: 1px dashed var(--dm-hair);
  border-radius: var(--r-pill);
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  cursor: pointer;
}
.od-math-btn:hover, .od-math.open .od-math-btn { color: var(--text); border-style: solid; border-color: var(--text); }
.od-math-pop {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: min(380px, calc(100vw - 32px));
  max-height: calc(100vh - var(--topbar-h) - 120px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 14px 16px 16px;
  border-radius: 16px;
  background: var(--panel);
  box-shadow: 0 18px 50px var(--shadow-toast), 0 0 0 1px var(--hairline);
  font-size: 0.76rem;
  text-align: left;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
}
.od-math.open .od-math-pop { opacity: 1; visibility: visible; transform: none; }
@media (hover: hover) {
  .od-math:hover .od-math-pop { opacity: 1; visibility: visible; transform: none; }
}
.od-math-title { display: flex; flex-direction: column; font-weight: 700; font-size: 0.86rem; color: var(--text); }
.od-math-title em { font-style: normal; font-weight: 400; font-size: 0.7rem; color: var(--text-dim); }
.od-math-sec { margin: 8px 0 2px; padding-top: 8px; border-top: 1px solid var(--hairline); font-size: 0.64rem; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-dim); }
.od-math-row { display: grid; grid-template-columns: 1fr auto; column-gap: 10px; padding: 2px 0; color: var(--text-dim); }
.od-math-row b { color: var(--text); font-variant-numeric: tabular-nums; text-align: right; }
.od-math-row i { font-style: normal; font-size: 0.68rem; opacity: 0.7; }
.od-math-note { color: var(--text-dim); line-height: 1.45; }
.od-math-formula { margin-top: 10px; padding: 8px 10px; border-radius: 10px; background: var(--surface-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.68rem; color: var(--text); }
/* On a phone the panel hangs from the row's left edge, not the button's,
   so it never runs (even hidden) past the screen. */
@media (max-width: 760px) {
  .od-math { position: static; }
  .od-math-pop { width: 100%; }
}

/* ===== Flip: heads or tails for a piece ================================== */

.fl-hero { min-height: 560px; align-items: stretch; }
.fl-media {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  min-height: 500px;
}
.fl-hero .dm-hero-copy { align-self: center; }

/* The coin: silver, thin, with a reeded edge. Two struck faces and a ring
   of edge slices, turned end over end on X inside a gently rocking tilt.
   js/flip.js lights it each frame: --dark shades a face turned from the
   light, --gy/--go place the shine, --l lights each edge slice. */
.fl-stage { position: relative; display: grid; place-items: center; width: 100%; height: 330px; perspective: 1100px; }
.fl-toss { --coin: 220px; --thick: 5px; position: relative; width: var(--coin); height: var(--coin); transform-style: preserve-3d; }
.fl-tilt { position: absolute; inset: 0; transform-style: preserve-3d; animation: fl-rock 7s ease-in-out infinite; }
@keyframes fl-rock {
  0%, 100% { transform: rotateX(9deg) rotateY(-11deg); }
  50% { transform: rotateX(-7deg) rotateY(10deg); }
}
.fl-coin { position: absolute; inset: 0; transform-style: preserve-3d; will-change: transform; }
.fl-edge {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--coin) * 3.1416 / 48 + 1px);
  height: var(--thick);
  margin: calc(var(--thick) / -2) 0 0 calc((var(--coin) * 3.1416 / 48 + 1px) / -2);
  background: repeating-linear-gradient(90deg, #7d848d 0 0.8px, #d7dbe0 0.8px 2.2px);
  filter: brightness(var(--l, 1));
  transform: rotateZ(var(--a)) translateY(calc(var(--coin) / -2 + 0.4px)) rotateX(90deg);
}
.fl-face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 24%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0) 42%),
    radial-gradient(circle at 70% 82%, rgba(90, 98, 110, 0.28), rgba(90, 98, 110, 0) 50%),
    conic-gradient(from 210deg, #c3c9d0, #f2f4f6, #a9b0b9, #e4e8ec, #9ba3ad, #dde1e6, #c3c9d0);
  box-shadow:
    inset 0 0 0 7px #d4d9de,
    inset 0 0 0 8px #8f97a1,
    inset 1px 2px 0 9px #f6f8fa,
    inset 0 0 22px rgba(40, 46, 56, 0.22);
  color: #7f8892;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.fl-heads { transform: translateZ(calc(var(--thick) / 2)); }
.fl-tails { transform: rotateX(180deg) translateZ(calc(var(--thick) / 2)); }
/* Struck in relief: lit on top, shadowed beneath. */
.fl-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: currentColor;
  font-family: var(--dm-display);
  filter: drop-shadow(0 -0.6px 0 rgba(255, 255, 255, 0.95)) drop-shadow(0 1px 0.4px rgba(38, 44, 54, 0.55));
}
.fl-art .fl-laurel { opacity: 0.9; }
/* Turned from the light, a face greys; at the angle that catches it, a
   band of shine runs across. */
.fl-face::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: rgb(22, 26, 32);
  opacity: var(--dark, 0.02);
  pointer-events: none;
}
.fl-glint {
  position: absolute;
  inset: -60% -10%;
  background: linear-gradient(172deg, transparent 38%, rgba(255, 255, 255, 0.85) 50%, transparent 62%);
  opacity: calc(0.15 + var(--go, 0) * 0.85);
  transform: translateY(var(--gy, 80%));
  mix-blend-mode: screen;
  pointer-events: none;
}
.fl-shadow {
  position: absolute;
  bottom: 6px;
  left: 50%;
  width: 190px;
  height: 26px;
  margin-left: -95px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(20, 26, 36, 0.34), transparent);
}

.fl-result {
  margin: 0;
  min-height: 1.4em;
  font-family: var(--dm-display);
  font-size: 1.15rem;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--text-dim);
  text-align: center;
}
.fl-result.is-won { color: oklch(0.62 0.19 147); animation: fl-pop 0.4s cubic-bezier(0.2, 0.8, 0.2, 1); }
.fl-result.is-lost { color: var(--text); animation: fl-pop 0.4s cubic-bezier(0.2, 0.8, 0.2, 1); }
@keyframes fl-pop { from { opacity: 0; transform: scale(0.85); } }

.fl-mini {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 26%, #fbfcfd, #c4cad1 55%, #959da7);
  box-shadow: inset 0 0 0 1.5px #a4abb4;
  color: #5f6872;
}
.fl-sides { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; width: min(380px, 100%); }
.fl-side {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 56px;
  border: 1.5px solid var(--dm-hair);
  border-radius: var(--r-pill);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.fl-side:hover { border-color: var(--text); }
.fl-side.active { border-color: var(--text); background: var(--text); color: var(--text-inverse); }
.fl-side:disabled, .fl-mode:disabled, .fl-pick:disabled { cursor: default; }
.fl-side:disabled:not(.active) { opacity: 0.5; }

/* The two pieces on the coin: what your call wins, and the other side. */
.fl-match { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; max-width: 520px; margin: 0 0 16px; }
.fl-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  padding: 12px;
  border: 1px solid var(--dm-hair);
  border-radius: 20px;
  background: var(--dm-card);
  transition: opacity 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
}
.fl-card.is-win { border-color: oklch(0.72 0.19 147); }
.fl-card-tag { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px; }
.fl-side-chip { padding-left: 3px; border-color: var(--dm-hair); color: var(--text); }
.fl-side-chip .fl-mini { width: 18px; height: 18px; }
.fl-card.is-win .fl-side-chip { border-color: oklch(0.72 0.19 147); color: oklch(0.5 0.15 147); }
.fl-card.is-hit { box-shadow: 0 0 0 3px oklch(0.72 0.19 147), 0 18px 40px -18px oklch(0.72 0.19 147); transform: translateY(-3px); }
.fl-card.is-miss { opacity: 0.4; }

.fl-modes { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 18px; }
.fl-modes > span { margin-right: 4px; font-size: 0.78rem; color: var(--text-dim); }
.fl-mode {
  height: 32px;
  padding: 0 14px;
  border: 1.5px solid var(--dm-hair);
  border-radius: var(--r-pill);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}
.fl-mode.active { border-color: var(--text); background: var(--text); color: var(--text-inverse); }
.fl-go { width: 100%; max-width: 520px; }
.fl-go-m { display: none; }
.fl-go:disabled { opacity: 0.6; cursor: default; transform: none; }
.fl-fairline { max-width: 520px; margin: -8px 0 0; font-size: 0.74rem; line-height: 1.5; color: var(--text-dim); }
.fl-fairline a, .fl .dm-sub a { color: var(--text); }
.fl code, .fl-steps code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.92em; color: var(--text); word-break: break-all; }

/* Picking a piece. */
.fl-search {
  width: min(260px, 100%);
  height: 38px;
  padding: 0 14px;
  border: 1.5px solid var(--dm-hair);
  border-radius: var(--r-pill);
  background: var(--dm-card);
  color: var(--text);
  font: inherit;
  font-size: 0.86rem;
}
.fl-search:focus { outline: none; border-color: var(--text); }
.fl-bands { margin-bottom: 16px; }
.fl-pick-li { display: flex; min-width: 0; }
.fl-pick { width: 100%; min-width: 0; color: inherit; font: inherit; text-align: left; cursor: pointer; transition: transform 0.15s ease, box-shadow 0.15s ease; }
.fl-pick:hover:not(:disabled) { transform: translateY(-2px); }
.fl-pick.is-picked { box-shadow: 0 0 0 2px var(--text); }
.fl-picked { margin-left: auto; padding: 3px 9px; border-radius: var(--r-pill); background: var(--text); color: var(--text-inverse); font-size: 0.7rem; font-weight: 700; }
.fl-empty { grid-column: 1 / -1; padding: 24px 0; color: var(--text-dim); }
.fl-more-wrap { grid-column: 1 / -1; display: flex; justify-content: center; padding-top: 8px; }

/* Your flips, on Odds' "Your boxes" rows; a proof opens beneath its row. */
.fl-mine-row { flex-wrap: wrap; }
.fl-mine-row .od-mine-text b { color: oklch(0.5 0.15 147); }
.fl-mine-row.is-up .dm-money { color: oklch(0.5 0.15 147); }
.fl-verify-btn {
  height: 30px;
  padding: 0 12px;
  border: 1.5px solid var(--dm-hair);
  border-radius: var(--r-pill);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
}
.fl-verify-btn:hover { border-color: var(--text); }
.fl-proof { flex: 1 0 100%; display: grid; gap: 6px; padding-top: 10px; border-top: 1px solid var(--hairline); font-size: 0.72rem; }
.fl-proof > span { display: grid; grid-template-columns: 130px minmax(0, 1fr); gap: 10px; }
.fl-proof em { font-style: normal; color: var(--text-dim); }
.fl-proof-check { display: block !important; font-weight: 700; color: var(--text-dim); }
.fl-proof-check.is-ok { color: oklch(0.62 0.19 147); }
.fl-proof-check.is-bad { color: var(--danger, #e5484d); }

.fl-steps { display: grid; gap: 12px; max-width: 720px; margin: 0; padding-left: 20px; font-size: 0.9rem; line-height: 1.5; color: var(--text-dim); }
.fl-steps b { color: var(--text); }
.fl-client { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.fl-client span { font-size: 0.76rem; font-weight: 700; color: var(--text); }
.fl-client input {
  width: min(280px, 100%);
  height: 34px;
  padding: 0 12px;
  border: 1.5px solid var(--dm-hair);
  border-radius: 10px;
  background: var(--dm-card);
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.8rem;
}
.fl-client input:focus { outline: none; border-color: var(--text); }

@media (max-width: 760px) {
  /* What you're flipping for first; then the coin, your call and the
     button together, so the toss happens right above your thumb. */
  .fl-hero { min-height: 0; gap: 20px; }
  .fl-copy { order: -1; }
  .fl-copy .fl-go, .fl-copy .dm-buyline, .fl-copy .dm-paid { display: none; }
  .fl-go-m { display: flex; width: min(380px, 100%); }
  .fl-match { margin-bottom: 12px; }
  .fl-modes { margin-bottom: 10px; }
  .fl-fairline { margin: 0; }
  .fl-media { min-height: 0; }
  .fl-stage { height: 250px; }
  .fl-toss { --coin: 176px; --thick: 4px; }
  .fl-shadow { width: 150px; margin-left: -75px; }
  .fl-match { gap: 8px; }
  /* The two pieces as compact rows: picture beside name and value. */
  .fl-card { display: grid; grid-template-columns: 52px minmax(0, 1fr); grid-template-rows: auto auto auto; column-gap: 10px; row-gap: 4px; padding: 10px; border-radius: 16px; }
  .fl-card-tag { grid-column: 1 / -1; margin-bottom: 4px; }
  .fl-card .dm-img { grid-row: 2 / 4; width: 52px; border-radius: 10px; }
  .fl-card .dm-name { align-self: end; font-size: 0.78rem; }
  .fl-card .dm-money { align-self: start; font-size: 1.1rem; }
  .fl-search { width: 100%; }
  /* Text gets the row; Verify drops to a line of its own under it. */
  .fl-mine-row .od-mine-text { min-width: calc(100% - 140px); }
  .fl-verify-btn { margin-left: 64px; }
  .fl-proof > span { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* ===== Wanted: bounties with escrowed offers ============================= */

.wn-media { display: flex; flex-direction: column; align-items: center; justify-content: center; }
.wn-feature { position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; width: min(460px, 100%); }
.wn-feature-top { display: flex; align-items: center; gap: 8px; width: 100%; }
.wn-feature-img { width: 100%; border: 1px solid var(--dm-hair); border-radius: 28px; }
.wn-feature-img img { padding: 10%; }
.wn-feature .wn-note { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px 10px; max-width: 380px; text-align: center; }
.wn-feature .wn-note .od-creator { font-style: normal; }
.wn-pill-match { border-color: oklch(0.72 0.19 147); background: oklch(0.8751 0.2471 147.45); color: oklch(0.256 0.062 150.2); }
.wn .dm-pill svg { vertical-align: -1px; margin-right: 3px; }
.wn .dm-sub a { color: var(--text); }
.wn-feat { margin: 0 0 10px; font-size: 0.86rem; color: var(--text-dim); }
.wn-feat b { color: var(--text); }
.wn-open-row.is-single { grid-template-columns: minmax(0, 1fr); }
.wn-open-row .dm-ghost { height: 52px; }

/* A bounty card: Odds' piece card, plus the offer and who's asking. */
.wn-card { gap: 8px; }
.wn-card.is-match { box-shadow: 0 0 0 2px oklch(0.72 0.19 147); }
.wn-match, .wn-yours { margin-left: auto; padding: 3px 9px; border-radius: var(--r-pill); font-size: 0.7rem; font-weight: 800; }
.wn-match { background: oklch(0.8751 0.2471 147.45); color: oklch(0.256 0.062 150.2); }
.wn-match { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.wn-yours { background: var(--text); color: var(--text-inverse); }
.wn-worth { font-size: 0.76rem; color: var(--text-dim); }
.wn-worth em { font-style: normal; font-weight: 700; }
.wn-worth em.is-up { color: oklch(0.55 0.17 147); }
.wn-offer-row { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; padding-top: 8px; border-top: 1px solid var(--dm-hair); }
.wn-escrow { display: inline-flex; align-items: center; gap: 4px; font-size: 0.66rem; font-weight: 700; letter-spacing: 0.4px; text-transform: uppercase; color: oklch(0.55 0.17 147); }
.wn-offer { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.wn-or { font-size: 0.74rem; font-weight: 600; color: var(--text-dim); }
.wn-items { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
.wn-thumb { display: grid; place-items: center; width: 30px; height: 30px; flex: 0 0 auto; overflow: hidden; border: 1px solid var(--dm-hair); border-radius: 8px; background: #fff; }
.wn-thumb img { width: 100%; height: 100%; object-fit: contain; padding: 8%; }
.wn-items-val { margin-left: 2px; font-size: 0.74rem; color: var(--text-dim); white-space: nowrap; }
.wn-note { margin: 0; font-size: 0.8rem; font-style: italic; line-height: 1.4; color: var(--text-dim); }
.wn-card .wn-note { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.wn-card .wn-fill { height: 44px; margin-top: auto; padding: 0 16px; font-size: 0.88rem; }
.wn-card.is-link { cursor: pointer; transition: transform 0.15s ease, box-shadow 0.15s ease; }
.wn-card.is-link:hover { transform: translateY(-2px); }
.wn-card.is-link:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
.wn-drop { display: inline-flex; align-items: center; gap: 6px; margin-top: auto; font-size: 0.78rem; font-weight: 700; color: var(--text); }
.wn-drop svg { width: 14px; height: 14px; }
.wn-none { margin-top: auto; font-size: 0.74rem; color: var(--text-dim); }
.wn-row-btn {
  height: 32px;
  padding: 0 14px;
  border: 1.5px solid var(--dm-hair);
  border-radius: var(--r-pill);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}
.wn-row-btn:hover { border-color: var(--text); }
.wn-card .wn-row-btn { margin-top: auto; align-self: flex-start; }
.dm-open:disabled { opacity: 0.45; cursor: default; transform: none; filter: none; }

/* Sheets: posting a bounty, filling one. */
.wn-sheet { width: min(640px, 100%); text-align: left; }
.wn-sheet .od-reveal-sub { margin: 0 0 6px; color: var(--text-dim); font-size: 0.9rem; }
.wn-step { display: flex; align-items: center; gap: 10px; margin: 20px 0 10px; font-weight: 700; color: var(--text); }
.wn-step span { display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; background: var(--text); color: var(--text-inverse); font-size: 0.76rem; }
.wn-search, .wn-note-in { width: 100%; }
.wn-results { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 8px; margin: 10px 0 0; padding: 0; list-style: none; }
.wn-result, .wn-vitem {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: 10px;
  align-items: center;
  width: 100%;
  padding: 7px;
  border: 1.5px solid var(--dm-hair);
  border-radius: 14px;
  background: var(--dm-card);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.wn-result:hover, .wn-vitem:hover { border-color: var(--text); }
.wn-result .dm-img, .wn-vitem .dm-img { grid-row: 1 / 3; width: 44px; border-radius: 9px; }
.wn-result .dm-name, .wn-vitem .dm-name { align-self: end; font-size: 0.8rem; }
.wn-result b, .wn-vitem b { align-self: start; font-size: 0.8rem; }
.wn-vitem.active { border-color: oklch(0.72 0.19 147); box-shadow: 0 0 0 1.5px oklch(0.72 0.19 147); }
.wn-empty { padding: 8px 0; font-size: 0.84rem; color: var(--text-dim); }
.wn-picked { display: flex; align-items: center; gap: 12px; padding: 8px 12px 8px 8px; border: 1.5px solid var(--text); border-radius: 16px; background: var(--dm-card); }
.wn-picked .dm-img { width: 56px; flex: 0 0 56px; border-radius: 10px; }
.wn-picked-text { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 0.78rem; color: var(--text-dim); }
.wn-cash { display: flex; align-items: center; gap: 6px; height: 56px; padding: 0 18px; border: 1.5px solid var(--text); border-radius: 16px; background: var(--dm-card); }
.wn-cash span { font-family: var(--dm-display); font-size: 1.6rem; color: var(--text-dim); }
.wn-cash input { flex: 1; min-width: 0; border: none; outline: none; background: none; color: var(--text); font-family: var(--dm-display); font-size: 1.6rem; font-variant-numeric: tabular-nums; }
.wn-quick { margin-top: 10px; }
.wn-hint { margin: 14px 0 8px; font-size: 0.82rem; color: var(--text-dim); }
.wn-vault { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 8px; max-height: 214px; margin: 0; padding: 2px; overflow-y: auto; list-style: none; }
.wn-days { margin-top: 10px; }
.wn-summary { margin-top: 18px; padding: 12px 14px; border-radius: 14px; background: var(--surface-2); font-size: 0.82rem; line-height: 1.5; color: var(--text-dim); }
.wn-summary:empty { display: none; }
.wn-summary p { margin: 0; }
.wn-summary b { color: var(--text); }
.wn-warn { color: var(--text) !important; font-weight: 600; }

.wn-swap { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 14px; margin: 18px 0 6px; }
.wn-swap-side { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.wn-swap-label { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-dim); }
.wn-swap-card { display: flex; flex-direction: column; gap: 6px; padding: 12px; border: 1.5px solid var(--dm-hair); border-radius: 18px; background: var(--dm-card); }
.wn-swap-note { font-size: 0.72rem; color: var(--text-dim); }
.wn-swap-icon { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; background: var(--text); color: var(--text-inverse); }
.wn-opts { display: flex; flex-direction: column; gap: 8px; }
.wn-opt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 12px;
  border: 1.5px solid var(--dm-hair);
  border-radius: 16px;
  background: var(--dm-card);
  color: inherit;
  font: inherit;
  font-size: 0.76rem;
  text-align: left;
  cursor: pointer;
}
.wn-opt span { color: var(--text-dim); line-height: 1.35; }
.wn-opt.active { border-color: oklch(0.72 0.19 147); box-shadow: 0 0 0 1.5px oklch(0.72 0.19 147); }
.wn-opt-items { display: flex; gap: 6px; }
.wn-opt-items .wn-thumb { width: 44px; height: 44px; }
.wn-checks { display: grid; gap: 6px; margin: 14px 0 0; padding: 12px 14px; border-radius: 14px; background: var(--surface-2); list-style: none; font-size: 0.82rem; color: var(--text); }
.wn-checks li { display: flex; align-items: center; gap: 8px; }
.wn-checks svg { flex: 0 0 auto; color: oklch(0.55 0.17 147); }
.wn-compare { margin: 12px 0 0; font-size: 0.82rem; color: var(--text-dim); }
.wn-compare b { color: oklch(0.5 0.15 147); }
.wn-done-mark { display: grid; place-items: center; width: 56px; height: 56px; margin: 4px 0 14px; border-radius: 50%; background: oklch(0.8751 0.2471 147.45); color: oklch(0.256 0.062 150.2); }
.wn-done-mark svg { width: 28px; height: 28px; }

@media (max-width: 760px) {
  .wn-feature { width: min(300px, 100%); }
  .wn-swap { grid-template-columns: minmax(0, 1fr); }
  .wn-swap-icon { justify-self: center; transform: rotate(90deg); }
  .wn-results, .wn-vault { grid-template-columns: minmax(0, 1fr); }
  /* Two cards a row: the tick alone says it's yours to fill. */
  .wn-card .wn-long { display: none; }
  .wn-match { padding: 3px 6px; }
  .wn-card .wn-fill { height: 40px; padding: 0 14px; }
  .wn-items-val { display: none; }
}

/* ===== Drops: the drop card, after the reference build =====================
   Partner logo in a white pill top left, the box, name and price on one
   line, the best pieces drifting past as tiles (price in their tier's
   colour, grails on the gold-to-pink edge), then quantity and Open with
   what it costs. Three across on a desktop, two on a tablet, one on a phone. */
.category-list.is-all { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
@media (max-width: 1100px) {
  .category-list, .category-list.is-all { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
}
@media (max-width: 640px) {
  .category-list, .category-list.is-all { grid-template-columns: minmax(0, 1fr); gap: 14px; }
}

.category-list .category-card.dc {
  display: flex;
  flex-direction: column;
  padding: 20px 22px 22px;
  border: 1.5px solid var(--text);
  border-radius: 28px;
  background: var(--panel);
  text-align: left;
}
.category-list .category-card.dc:hover { transform: translateY(-3px); box-shadow: 0 18px 40px -24px rgba(0, 0, 0, 0.35); }
.dc-top { display: flex; align-items: center; min-height: 34px; }
.dc-brand {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 14px;
  border: 1.5px solid #deddd8;
  border-radius: var(--r-pill);
  background: #fff;
  color: #0b0b0b;
}
.dc-brand .brand-mark { flex: none; color: #0b0b0b; }
.dc-brand .brand-mark-odto { height: 13px; width: auto; }
.dc-brand .brand-mark-cc { height: 22px; width: auto; }
.dc-brand:has(.brand-mark-cc) { padding: 0 13px; }
.dc-brand .brand-mark-robinhood { width: 14px; height: 14px; }
.dc-brand .brand-word, .dc-brand span { font-size: 0.8rem; font-weight: 800; letter-spacing: -0.01em; white-space: nowrap; }

/* The box is framed with room to spin, so its canvas is mostly air: drawn
   wide, and pulled in above and below. */
.category-list .dc .category-box-canvas { width: min(100%, 380px); height: auto; aspect-ratio: 1; margin: -15% auto -19%; }

.dc-title { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-top: 8px; }
.dc-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 1.4rem; font-weight: 600; letter-spacing: -0.01em; color: var(--text); }
.dc-price { flex: none; font-family: "Archivo Black", "Anton", system-ui, sans-serif; font-size: 1.8rem; font-weight: 400; line-height: 1; letter-spacing: -0.01em; color: var(--text); font-variant-numeric: tabular-nums; }

/* The strip: one button (it opens the odds and full list), its tiles
   drifting left; it holds still under the pointer. */
.dc-strip {
  position: relative;
  display: block;
  width: calc(100% + 20px);
  margin: 16px -10px 0;
  padding: 4px 0;
  overflow: hidden;
  border: none;
  background: none;
  cursor: pointer;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.dc-strip-track { display: flex; width: max-content; animation: dc-drift calc(var(--n, 8) * 3.4s) linear infinite; }
.dc-strip:hover .dc-strip-track, .dc-strip:focus-visible .dc-strip-track { animation-play-state: paused; }
@keyframes dc-drift { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .dc-strip-track { animation: none; } }
.dc-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  flex: none;
  width: 104px;
  height: 108px;
  margin-right: 10px;
  padding: 10px 6px 9px;
  border: 2px solid #e3e2dd;
  border-radius: 22px;
  background: var(--panel);
}
.dc-tile img { width: 100%; height: 58px; object-fit: contain; mix-blend-mode: multiply; }
:root:not([data-theme="light"]) .dc-tile img { mix-blend-mode: normal; }
.dc-tile b { font-size: 0.92rem; font-weight: 700; color: var(--rc); font-variant-numeric: tabular-nums; white-space: nowrap; }
.dc-tile.dc-t-legendary {
  border-color: transparent;
  background: linear-gradient(var(--panel), var(--panel)) padding-box, linear-gradient(135deg, #f7c948, #f39a3a 50%, #ee5f8c) border-box;
}
.dc-tile.dc-t-legendary b { background: linear-gradient(90deg, #e9a43a, #ec6a87); -webkit-background-clip: text; background-clip: text; color: transparent; }
.dc-tile.dc-t-epic, .dc-tile.dc-t-rare { border-color: color-mix(in srgb, var(--rc) 45%, #e3e2dd); }

.dc-actions { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px; margin-top: 18px; }
.category-list .dc .dc-qty {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2px;
  height: 56px;
  margin: 0;
  padding: 0 6px;
  border: 1.5px solid var(--text);
  border-radius: var(--r-pill);
  background: var(--panel);
}
.category-list .dc .dc-qty .qty-btn {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--text);
  font-size: 1.35rem;
  font-weight: 300;
}
.category-list .dc .dc-qty .qty-btn:hover { background: var(--control-fill); transform: none; }
.category-list .dc .dc-qty .qty-value { min-width: 28px; text-align: center; font-family: "Archivo Black", "Anton", system-ui, sans-serif; font-size: 1.15rem; color: var(--text); }
.category-list .dc .dc-open {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  height: 56px;
  margin: 0;
  padding: 0 18px 0 22px;
  border: 1.5px solid #000;
  border-radius: var(--r-pill);
  background: var(--open-green);
  color: var(--open-ink);
  font-size: 1rem;
  font-weight: 600;
  white-space: nowrap;
}
.dc-open-label { overflow: hidden; text-overflow: ellipsis; }
.dc-open-price { display: inline-flex; align-items: center; gap: 12px; }
.dc-open-price b { font-family: "Archivo Black", "Anton", system-ui, sans-serif; font-size: 1.15rem; font-weight: 400; }

/* A crate's own page keeps the card; its full list sits beside it. */
.drop-detail-active .dc-strip { display: none; }

@media (max-width: 640px) {
  .category-list .category-card.dc { padding: 16px 16px 18px; border-radius: 24px; }
  .category-list .dc .category-box-canvas { width: min(100%, 320px); margin: -14% auto -18%; }
  .dc-name { font-size: 1.2rem; }
  .dc-price { font-size: 1.5rem; }
  .category-list .dc .dc-qty, .category-list .dc .dc-open { height: 52px; }
  .category-list .dc .dc-open { padding: 0 14px 0 18px; font-size: 0.95rem; }
}
/* The card sizes its own controls to its width, not the screen's: three
   across a laptop is narrower than one across a phone. */
.category-list .category-card.dc { container-type: inline-size; }
@container (max-width: 400px) {
  .category-list .dc .dc-qty { padding: 0 3px; }
  .category-list .dc .dc-qty .qty-btn { width: 34px; height: 34px; }
  .category-list .dc .dc-qty .qty-value { min-width: 20px; }
  .category-list .dc .dc-open { gap: 8px; padding: 0 14px 0 16px; font-size: 0.92rem; }
  .dc-open-price { gap: 5px; }
  .dc-open-price b { font-size: 1.02rem; }
  .dc-open-price svg { width: 16px; height: 16px; }
  .dc-name { font-size: 1.22rem; }
  .dc-price { font-size: 1.55rem; }
}
@container (max-width: 330px) {
  .category-list .dc .dc-open { font-size: 0.86rem; }
  .dc-open-price svg { display: none; }
}

/* ===== Shipping several at once =============================================
   "Select to ship" turns My Items into a picker: a round tick on each piece,
   a bar along the bottom with the count and Ship. Pieces locked in an Odds
   box or a bounty fade out. */
.ship-select-btn {
  margin-left: auto;
  align-self: center;
  height: 34px;
  padding: 0 16px;
  border: 1.5px solid var(--text);
  border-radius: var(--r-pill);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
}
.ship-select-btn.active { background: var(--text); color: var(--text-inverse); }
.is-selecting .market-item[data-item] { position: relative; cursor: pointer; }
.is-selecting .market-item[data-item]::before {
  content: "";
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 4;
  width: 26px;
  height: 26px;
  border: 2px solid #fff;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.28) center / 15px no-repeat;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
.is-selecting .market-item.is-picked { box-shadow: 0 0 0 2.5px var(--text); }
.is-selecting .market-item.is-picked::before {
  border-color: var(--open-green);
  background-color: var(--open-green);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23123d17' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='5 12.5 10 17.5 19 7'/%3E%3C/svg%3E");
}
.is-selecting .market-item.not-shippable { opacity: 0.4; }
.is-selecting .market-item.not-shippable::before { display: none; }
.is-selecting .item-actions { pointer-events: none; opacity: 0.35; }

.ship-select-bar {
  position: fixed;
  left: 50%;
  bottom: 20px;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 10px;
  width: min(560px, calc(100vw - 24px));
  padding: 8px 8px 8px 18px;
  border-radius: var(--r-pill);
  background: var(--text);
  color: var(--text-inverse);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.3);
  transform: translateX(-50%);
}
.ship-select-bar.hidden { display: none; }
.ship-select-count { flex: 1; min-width: 0; font-size: 0.84rem; font-weight: 600; line-height: 1.3; }
.ship-select-cancel, .ship-select-go {
  flex: none;
  height: 42px;
  padding: 0 16px;
  border-radius: var(--r-pill);
  font: inherit;
  font-size: 0.86rem;
  font-weight: 700;
  cursor: pointer;
}
.ship-select-cancel { border: 1.5px solid color-mix(in srgb, var(--text-inverse) 35%, transparent); background: none; color: var(--text-inverse); }
.ship-select-go { border: 1.5px solid #000; background: var(--open-green); color: var(--open-ink); }
.ship-select-go:disabled { opacity: 0.45; cursor: default; }
@media (max-width: 640px) {
  .ship-select-bar { bottom: calc(var(--bottom-nav-h) + 10px); padding-left: 14px; }
  .ship-select-count { font-size: 0.76rem; }
  .ship-select-cancel { padding: 0 12px; }
}

/* The ship modal, several pieces: their pictures fanned in the header. */
.ship-thumbs { display: flex; flex: none; }
.ship-thumbs.hidden { display: none; }
.ship-thumbs img, .ship-thumbs span {
  width: 52px;
  height: 52px;
  margin-left: -16px;
  border: 2px solid var(--bg);
  border-radius: 12px;
  background: #fff;
  object-fit: contain;
}
.ship-thumbs img:first-child { margin-left: 0; }
.ship-thumbs span { display: grid; place-items: center; background: var(--surface-2); color: var(--text); font-size: 0.8rem; font-weight: 700; }
#shipItemImage.hidden { display: none; }

/* Two vaults: a parcel each, each with its quote. */
.ship-split.hidden { display: none; }
.ship-split-lead { margin: 0 0 14px; font-size: 0.9rem; line-height: 1.5; color: var(--text-dim); }
.ship-groups { display: grid; gap: 10px; }
.ship-group, .ship-order { display: grid; gap: 10px; padding: 14px; border: 1.5px solid var(--line, rgba(0,0,0,0.12)); border-radius: 18px; background: var(--panel); }
.ship-group-head { display: flex; align-items: center; gap: 10px; }
.ship-group-brand { height: 30px; padding: 0 11px; flex: none; }
.ship-group-label { flex: 1; display: flex; flex-direction: column; min-width: 0; font-weight: 700; font-size: 0.9rem; color: var(--text); }
.ship-group-label em { font-style: normal; font-weight: 500; font-size: 0.76rem; color: var(--text-dim); }
.ship-group-head > b { font-size: 1rem; font-variant-numeric: tabular-nums; }
.ship-group-items { display: flex; flex-wrap: wrap; gap: 6px; }
.ship-group-items img { width: 44px; height: 44px; padding: 3px; border-radius: 10px; background: #fff; object-fit: contain; border: 1px solid rgba(0, 0, 0, 0.08); }
.ship-group-break { font-size: 0.74rem; color: var(--text-dim); }
.ship-split-total { display: flex; justify-content: space-between; margin: 14px 2px 4px; font-weight: 700; color: var(--text); }

/* The address step's quote, above Confirm. */
.ship-quote { display: grid; gap: 6px; margin: 14px 0 4px; padding: 12px 14px; border-radius: 14px; background: var(--surface-2); font-size: 0.84rem; }
.ship-quote:empty { display: none; }
.ship-quote-title { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-dim); }
.ship-quote-row { display: flex; justify-content: space-between; gap: 12px; color: var(--text); }
.ship-quote-row b { font-variant-numeric: tabular-nums; }
.ship-quote-note { font-size: 0.74rem; color: var(--text-dim); }
.ship-quote-total { padding-top: 6px; border-top: 1px solid rgba(0, 0, 0, 0.1); font-weight: 700; }

/* Tracking several: one card per order. */
.ship-orders { display: grid; gap: 10px; margin-bottom: 18px; }
.ship-orders.hidden, .ship-steps.hidden { display: none; }
.ship-order-status { margin: 0; font-size: 0.84rem; color: var(--text); }
.ship-steps-compact { margin: 0; }
.ship-steps-compact .ship-step-time { font-size: 0.7rem; }
/* A tile keeps its shape whatever the photo's: a tall graded slab sits
   inside it rather than stretching the card. */
.market-item-media { min-height: 0; overflow: hidden; }
.market-item-media > img { min-height: 0; }

/* Picked from both vaults: a note just above the bar. */
.ship-vault-note {
  position: fixed;
  left: 50%;
  bottom: 88px;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 12px;
  width: min(560px, calc(100vw - 24px));
  padding: 12px 14px;
  border: 1.5px solid var(--text);
  border-radius: 18px;
  background: var(--panel);
  color: var(--text);
  font-size: 0.84rem;
  line-height: 1.4;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18);
  transform: translateX(-50%);
  animation: ship-note-in 0.25s ease;
}
.ship-vault-note.hidden { display: none; }
.ship-vault-marks { display: flex; flex: none; }
.ship-vault-marks .dc-brand { height: 30px; padding: 0 10px; }
.ship-vault-marks .dc-brand + .dc-brand { margin-left: -8px; }
.ship-vault-marks .brand-mark-odto { height: 11px; width: auto; }
.ship-vault-marks .brand-mark-cc { height: 18px; width: auto; }
@keyframes ship-note-in { from { opacity: 0; transform: translate(-50%, 8px); } }
@media (max-width: 640px) {
  .ship-vault-note { bottom: calc(var(--bottom-nav-h) + 76px); font-size: 0.78rem; }
  .ship-vault-marks { display: none; }
}
