  /* ── Equipment tab ─────────────────────────────────────────────────
     Rendered by src/equipment-tab.js on EQUIPMENT-tab activate. 4
     stacked sections (Shield / Main Gun / Secondary / Drone), each
     with a header (slot name + shard counter) and a grid of 5 cards.
     Cards: head row (icon + name + stars + desc + action button) +
     bottom upgrade row (cost + UPGRADE button, or MAX / LOCKED hint). */
  /* ── GEAR tab — open storybook (rc332, Figma-matched) ──────────────
     Mirror the SHOP tab: the panel becomes the wood-framed open book and
     the loadout sits on the two parchment pages. Replaces the default
     gold/blue book-bg.jpg (shown by #stage-select-panel) on this tab. */
  .play-hub-panel[data-tab="equipment"] {
    background: #2a1a0e url('../assets/shop/shop-book-bg.webp') center center / cover no-repeat;
    position: relative;
  }
  /* (Removed the decorative teal/magenta crystal clusters that framed the
     book's top corners — they read as stray colored blobs. Per design
     feedback.) */
  .eq-tab-scroll {
    height: 100%;
    overflow-y: auto;
    /* Width-locked + centred so the stat ribbon, loadout grid and
       super-weapon banner all land on the two book pages (instead of
       overflowing into the dark desk margins as before). */
    width: min(1160px, 94%);
    margin: 0 auto;
    padding: 56px 40px 12px;
    display: flex; flex-direction: column;
    gap: 12px;
    box-sizing: border-box;
  }
  /* GEAR slot cards (rc332) — override the dark rarity-tile surface with
     the mock's vibrant portal look: gold ornate frame + radial portal bg
     (purple for weapon slots, blue for defense slots) + a rarity gem at the
     top. Panel-scoped so specificity beats `.eq-slot-card[class*="eq-tier-"]`
     and the picker-modal rows keep the original rarity-tile styling. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] {
    border: 5px solid #a9803c;
    border-radius: 14px;
    box-shadow:
      inset 0 0 0 2px rgba(255, 222, 160, 0.32),
      inset 0 0 24px rgba(0, 0, 0, 0.5),
      0 5px 16px rgba(20, 10, 0, 0.5);
  }
  /* (2026-06-07 rollback: the candy gradient briefly painted the WHOLE card
     interior here, which destroyed the framed-portal look. The rarity stone
     belongs on the WEAPON WINDOW — .eq-slot-card-canvas-wrap, styled near
     line ~360 — not the card. Original per-slot interiors restored:) */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"] {
    background: radial-gradient(circle at 50% 44%, #9a47c4 0%, #6a2a9e 42%, #34125f 100%);
  }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] {
    background: radial-gradient(circle at 50% 44%, #3a8fe0 0%, #2059aa 42%, #103066 100%);
  }
  /* The mock uses a top gem instead of the left rarity bar. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[class*="eq-tier-"]::after { display: none; }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot]:not([data-slot="superweapon"])[class*="eq-tier-"]::before {
    content: '';
    position: absolute;
    top: -9px; left: 50%;
    transform: translateX(-50%) rotate(45deg);
    width: 15px; height: 15px;
    background: var(--rarity, #ffd166);
    border: 2px solid #a9803c;
    border-radius: 3px;
    box-shadow: 0 0 9px color-mix(in srgb, var(--rarity, #ffd166) 60%, transparent), 0 2px 4px rgba(0,0,0,.4);
    z-index: 4;
    pointer-events: none;
  }
  /* Super-weapon banner — a flat compact parchment strip (mock) with all
     content on one inline row, not the rolled scroll. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] {
    /* rc-gear: the real curled parchment scroll (Figma 3336-2) as a 9-slice
       border-image — fixed curl ends, flat centre stretches. Asset is the
       clean Figma background-export scroll (assets/gear/super-scroll.png,
       893×145, curls ≈90/83px, transparent surround). */
    background: none;
    border-style: solid;
    border-color: transparent;
    border-width: 0 36px 0 39px;
    border-image: url('../assets/gear/super-scroll.png') 0 83 0 90 fill / 0 36px 0 39px / 0 stretch;
    border-radius: 0;
    box-shadow: none;
    filter: drop-shadow(0 3px 6px rgba(30, 15, 0, 0.38));
    width: min(440px, 86%);
    min-height: 58px;
    margin: 2px auto 0;
    padding: 6px 12px;
    /* #7 — one vertically-centred row so the icon + label sit in the MIDDLE of
       the scroll (portrait was display:block, stacking the icon at the top and
       the label at the bottom). Desktop/landscape re-state this below. */
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: center;
    gap: 12px;
  }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] .eq-slot-card-label {
    position: static;
    transform: none;
    background: none;
    color: #5a3a1e;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 1.4px;
    padding: 0;
    text-shadow: none;
    margin: 0;
    border-radius: 0;
  }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] .eq-slot-card-canvas-wrap {
    width: 46px; height: 46px; flex: 0 0 46px;
    background: linear-gradient(180deg, #2a3358 0%, #1a2340 100%);
    border: 1.5px solid #b89a5e;
    border-radius: 9px;
    box-shadow: inset 0 1px 2px rgba(255,255,255,0.12), 0 1px 3px rgba(0,0,0,0.4);
  }
  /* rc-gear: Lv / rarity chips on the scroll read as small tan plaques (Figma
     3336-2 "Lv 1" / "T1"), not the old dark-card faint white chips. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] .eq-slot-card-lv,
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] .eq-slot-card-tier {
    background: rgba(120, 86, 46, 0.16);
    border: 1px solid rgba(120, 86, 46, 0.55);
    border-radius: 7px;
    padding: 1px 8px;
    color: #5a3f22 !important;
    font-size: 10px; font-weight: 800; letter-spacing: 0.3px;
  }
  /* The GEAR tab's active state matches every other bottom-nav tab — the gold
     icon halo from .ss-nav-tab.is-active. (The old bright-blue selection frame
     was removed per request so it no longer stands out from the row.) */
  /* Mobile guard (rc332) — the desktop side columns (≥140px) crowd out the
     centre hero on phones; shrink them so the 1-2-1 grid still fits and the
     ornate frame/ribbon scale down. */
  /* ── Narrow / portrait phones (rc332) ──────────────────────────────
     The desktop 1-2-1 book row crams the cards to ~90px on a phone. Reflow
     to a vertical stack — stat ribbon, hero on top, then the 4 gear cards
     in a roomy 2×2, then the super-weapon strip — so the cards are big and
     legible. Landscape phones (≥641px wide) keep the desktop book layout.
     `#stage-select` prefix raises specificity over the desktop gear rules. */
  @media (max-width: 640px) {
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-tab-scroll {
      width: 100%; padding: 50px 12px 8px; gap: 12px;
    }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-loadout-grid {
      grid-template-columns: 1fr 1fr;
      grid-template-rows: auto auto auto;
      gap: 14px 14px;
      padding: 4px 6px 0;
      align-items: stretch;
    }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-character-card {
      grid-column: 1 / 3; grid-row: 1;
      max-width: none; width: 100%;
      height: clamp(165px, 26vh, 230px);
      justify-self: stretch;
    }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"]       { grid-column: 1; grid-row: 2; }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"]    { grid-column: 2; grid-row: 2; }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"] { grid-column: 1; grid-row: 3; }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"]     { grid-column: 2; grid-row: 3; }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-stats { width: 100%; padding: 0 16px; height: clamp(48px, 7vh, 66px); }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] { width: 96%; }
    /* #5 — the base label clamps to its 9px floor on a ~412px phone (1.1vw ≈
       4.5px); bump it up so "Main Gun" / "Shield" etc. read clearly in the
       roomy 2×2 portrait grid. */
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot]:not([data-slot="superweapon"]) .eq-slot-card-label { font-size: clamp(13px, 3.6vw, 17px); }
  }
  /* ── Landscape phones (wide but short) ─────────────────────────────
     Keep the desktop 1-2-1 book layout but shrink everything so all 10
     elements fit the short viewport (iPhone 13 / S20 Ultra landscape). */
  @media (orientation: landscape) and (max-height: 460px) {
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-tab-scroll { padding: 16px 30px 4px; gap: 4px; }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-loadout-grid {
      grid-template-columns: clamp(84px, 11.5%, 112px) 1fr clamp(84px, 11.5%, 112px);
      gap: 5px 16px; padding: 1px 0 0;
    }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-character-card {
      max-width: none; height: clamp(108px, 30vh, 156px);
    }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"],
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"],
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"],
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] {
      border-width: 8px; border-image-width: 8px;
    }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-stats { width: min(700px, 96%); height: clamp(34px, 9.5vh, 46px); padding: 0 24px; }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot]:not([data-slot="superweapon"]) .eq-slot-card-label { font-size: 9px; padding: 2px 2px 3px; }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] { width: min(360px, 74%); min-height: 38px; padding: 4px 14px; margin-top: 0; }
    #stage-select .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] .eq-slot-card-canvas-wrap { width: 32px; height: 32px; flex: 0 0 32px; }
  }
  /* Stat ribbon (rc332) — the mock's is a wide scroll spanning the top of
     both pages with the three stats spread out + dividers between them.
     The base rule centred them in a ~460px cluster. */
  /* Three discrete parchment cartouche cells (mock), not one ribbon. */
  .play-hub-panel[data-tab="equipment"] .eq-stats {
    width: min(960px, 100%);
    align-self: center;
    justify-content: center;
    gap: clamp(10px, 1.6vw, 20px);
    background: none;
    height: auto;
    padding: 0 clamp(20px, 4%, 56px);
  }
  .play-hub-panel[data-tab="equipment"] .eq-stat {
    flex: 1 1 0;
    justify-content: center;
    gap: 8px;
    padding: 9px 16px;
    /* Real parchment plaque (assets/gear/parchment.png) under a soft depth
       gradient — replaces the flat CSS fill. */
    background:
      linear-gradient(180deg, rgba(255,251,238,0.38) 0%, rgba(150,118,72,0.22) 100%),
      url('../assets/gear/parchment.png') center / cover no-repeat;
    border: 1.5px solid rgba(120, 86, 46, 0.6);
    border-radius: 11px;
    box-shadow: 0 2px 6px rgba(40, 22, 8, 0.3), inset 0 1px 0 rgba(255, 250, 235, 0.5), inset 0 0 13px rgba(120, 86, 40, 0.2);
  }
  .play-hub-panel[data-tab="equipment"] .eq-stat-icon { font-size: clamp(15px, 2vw, 22px); }
  .play-hub-panel[data-tab="equipment"] .eq-stat-label { font-size: clamp(13px, 1.7vw, 17px); letter-spacing: 0.06em; }
  .play-hub-panel[data-tab="equipment"] .eq-stat-val { font-size: clamp(14px, 1.9vw, 19px); }

  /* Loadout grid fills the page height so the two stacked cards become big
     plaques (mock) instead of small top-anchored tiles (rc332). */
  .play-hub-panel[data-tab="equipment"] .eq-loadout-grid {
    grid-template-columns: clamp(118px, 14.5%, 156px) 1fr clamp(118px, 14.5%, 156px);
    grid-template-rows: auto auto;
    gap: 30px 34px;
    padding: 10px 62px 0;
    align-items: center;
    justify-items: center;
  }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] {
    width: 100%; max-width: 156px;
  }
  /* Central hero sits on a distinct lighter-parchment card (mock), with a
     soft aged border — not floating on the page. Capped + centred so it
     reads like the mock's compact pod. */
  .play-hub-panel[data-tab="equipment"] .eq-character-card {
    align-self: center; justify-self: center;
    width: 100%; max-width: 300px;
    height: clamp(252px, 42vh, 374px);
    /* Distinct lighter-parchment card (mock) — clear tan border + drop
       shadow + inner vignette so the hero clearly sits ON a card, not
       floating on the page. The preview canvas is alpha-transparent so
       this shows around the model. */
    background: radial-gradient(ellipse at 50% 38%, #f9efd8 0%, #efe0bd 56%, #e1cb9c 100%);
    border: 2px solid rgba(120, 84, 42, 0.52);
    border-radius: 14px;
    box-shadow:
      0 9px 22px rgba(38, 20, 6, 0.38),
      inset 0 0 42px rgba(140, 100, 52, 0.22);
  }
  .play-hub-panel[data-tab="equipment"] .eq-character-canvas { border-radius: 12px; }
  /* Bigger card frame — ornate gold corner-bracket frame via an inline-SVG
     border-image (corner brackets + thin gold edge), with the label moved
     INSIDE the card's lower strip in warm cream, like the mock. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] {
    border: 16px solid transparent;
    border-radius: 16px;
    border-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='none'%3E%3ClinearGradient id='g' x1='0' x2='0' y1='0' y2='1'%3E%3Cstop offset='0' stop-color='%23f4d98e'/%3E%3Cstop offset='.45' stop-color='%23cda455'/%3E%3Cstop offset='1' stop-color='%238a6326'/%3E%3C/linearGradient%3E%3Crect x='7' y='7' width='86' height='86' rx='12' stroke='url(%23g)' stroke-width='5'/%3E%3Cpath d='M7 32 V18 Q7 7 18 7 H32' stroke='url(%23g)' stroke-width='13' stroke-linecap='round'/%3E%3Cpath d='M68 7 H82 Q93 7 93 18 V32' stroke='url(%23g)' stroke-width='13' stroke-linecap='round'/%3E%3Cpath d='M93 68 V82 Q93 93 82 93 H68' stroke='url(%23g)' stroke-width='13' stroke-linecap='round'/%3E%3Cpath d='M32 93 H18 Q7 93 7 82 V68' stroke='url(%23g)' stroke-width='13' stroke-linecap='round'/%3E%3C/svg%3E") 33 / 16px stretch;
    box-shadow: inset 0 0 0 2px rgba(60, 30, 0, 0.45), inset 0 0 26px rgba(0, 0, 0, 0.5), 0 6px 18px rgba(20, 10, 0, 0.5);
    margin-bottom: 0;
  }
  /* Portal glows in the item's RARITY-tier colour — grey / green / blue /
     purple / gold / red as the weapon levels up — driven by the --rarity
     var that .eq-tier-1…6 already set. (Replaces the old fixed per-slot
     purple/blue so the colour now reads as the item's level/tier.) */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] {
    background:
      radial-gradient(118% 96% at 50% 37%,
        color-mix(in srgb, var(--rarity, #b674ff) 55%, #ffffff 45%) 0%,
        var(--rarity, #b674ff) 22%,
        color-mix(in srgb, var(--rarity, #b674ff) 40%, #0a0010) 54%,
        color-mix(in srgb, var(--rarity, #b674ff) 14%, #06000a) 100%);
  }
  /* Label inside the card's lower strip (mock), warm cream, title-case. */
  /* Name sits ON the frame's built-in parchment ribbon (assets/gear/equip-frame
     .png already paints the banner) — just centered text, NO separate plate and
     NO bottom anchor (the old bottom:-10px + this rule's higher specificity were
     stretching the label into a tall empty box). */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot]:not([data-slot="superweapon"]) .eq-slot-card-label {
    position: absolute;
    top: 88%; bottom: auto; left: 50%;            /* #6 — centred on the frame's bottom banner (~82-97%), nudged up off the bottom edge */
    transform: translate(-50%, -50%);
    width: 74%; max-width: 74%; height: auto;
    padding: 0; margin: 0;
    background: none; border: 0; border-radius: 0; box-shadow: none;
    color: #5a3a1c;
    font-family: 'EB Garamond', 'Cinzel', serif;
    font-size: clamp(9px, 1.1vw, 14px);
    line-height: 1.02;
    font-weight: 700;
    letter-spacing: 0.2px;
    text-transform: none;
    text-align: center;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    text-shadow: 0 1px 0 rgba(255, 248, 224, 0.6);
  }

  /* ─── rc-gear: provided ornate equipment frame (assets/gear/equip-frame.png) ───
     Matches Figma node 3336-2. The PNG carries the gold/purple border + top
     gem + bottom parchment name-banner with a transparent icon window; we drop
     the equipment preview into the window (on a purple/blue glow per the mock —
     purple for the left page's weapons, blue for the right page's defense) and
     the item name onto the banner. Appended last so it wins over the earlier
     border-image + portal-fill rules. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] {
    position: relative;
    aspect-ratio: 632 / 640;
    width: 100%; max-width: 200px;
    border: 0; border-image: none; border-radius: 0;
    background: url('../assets/gear/equip-frame.png') center / 100% 100% no-repeat;
    box-shadow: none;
    overflow: visible;
    padding: 0;
    display: block;
  }
  /* The frame supplies its own gem — hide the separate rarity gem. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot]:not([data-slot="superweapon"])[class*="eq-tier-"]::before { display: none; }
  /* Equipment preview fills the frame's transparent window (~15-82% of the
     card), on a glow tinted to the item's RARITY via --rc (set per data-rarity
     below) — NOT a fixed purple/blue. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"] .eq-slot-card-canvas-wrap,
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"] .eq-slot-card-canvas-wrap,
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"] .eq-slot-card-canvas-wrap,
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] .eq-slot-card-canvas-wrap {
    position: absolute;
    top: 13%; left: 8%; width: 84%; height: 70%;   /* fill the frame window (≈9-91% × 15-83%) */
    margin: 0; border-radius: 16px;
    display: flex; align-items: center; justify-content: center;
    box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.32);
    background: radial-gradient(ellipse at 50% 44%,
      color-mix(in srgb, var(--rc, #9aa3ad) 62%, #ffffff 38%) 0%,
      var(--rc, #9aa3ad) 30%,
      color-mix(in srgb, var(--rc, #9aa3ad) 48%, #0a0010) 66%,
      color-mix(in srgb, var(--rc, #9aa3ad) 20%, #06000a) 100%);
  }
  /* Rarity → glow colour (matches inventory RARITY_COLORS):
     0 common · 1 uncommon · 2 rare · 3 ultra rare · 4 epic · 5 mythic. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="0"] { --rc: #9aa3ad; }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="1"] { --rc: #5ec46a; }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="2"] { --rc: #4fa6ff; }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="3"] { --rc: #b674ff; }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="4"] { --rc: #ffc23d; }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="5"] { --rc: #ff5660; }
  /* WEAPON-WINDOW jelly candy gems (owner, 2026-06-07): the rarity stone
     fills the frame window BEHIND the weapon — the card frame + per-slot
     interior stay exactly as the Figma mock. Full inventory-cell recipe
     (css/inventory.css "Jelly Candy Gem"): radial stone + white candy-coat
     rim + glass gloss dome (::before) + injected .iv-spark twinkles
     (src/equipment-tab.js _slotCardHtml; the spark class/keyframes live in
     inventory.css — both sheets always load) + Epic/Mythic light-sweep
     (::after, reuses iv-sheen). Keyed off data-rarity, which the card
     already carries. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot]:not([data-slot="superweapon"]) .eq-slot-card-canvas-wrap {
    border: 2.5px solid rgba(255, 255, 255, 0.78);
    overflow: hidden;
    box-shadow:
      inset 0 -6px 12px rgba(0, 0, 0, 0.18),
      inset 0 4px 8px rgba(255, 255, 255, 0.25),
      inset 0 0 14px rgba(0, 0, 0, 0.2);
  }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot]:not([data-slot="superweapon"]) .eq-slot-card-canvas-wrap::before {
    content: '';
    position: absolute;
    left: 10%; right: 40%; top: 6%; height: 30%;
    border-radius: 50%;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.10) 80%, transparent);
    transform: rotate(-8deg);
    pointer-events: none;
    z-index: 1;
  }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="0"] .eq-slot-card-canvas-wrap { background: radial-gradient(90% 90% at 50% 38%, #c9cedd 0%, #8a91ad 52%, #545d7e 100%); }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="1"] .eq-slot-card-canvas-wrap { background: radial-gradient(90% 90% at 50% 38%, #8af0b4 0%, #3ecc7c 55%, #1a9a54 100%); }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="2"] .eq-slot-card-canvas-wrap { background: radial-gradient(90% 90% at 50% 38%, #7fc3ff 0%, #3e8ef0 55%, #1f5cc0 100%); }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="3"] .eq-slot-card-canvas-wrap { background: radial-gradient(90% 90% at 50% 38%, #d9a6ff 0%, #a861ec 55%, #7430bc 100%); }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="4"] .eq-slot-card-canvas-wrap { background: radial-gradient(90% 90% at 50% 38%, #ffd980 0%, #ffab2e 55%, #e07c0e 100%); }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="5"] .eq-slot-card-canvas-wrap { background: radial-gradient(90% 90% at 50% 38%, #ff92a8 0%, #f24a6a 55%, #c01d3e 100%); }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="4"] .eq-slot-card-canvas-wrap::after,
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="5"] .eq-slot-card-canvas-wrap::after {
    content: '';
    position: absolute; inset: 0;
    background: linear-gradient(112deg, transparent 40%, rgba(255, 255, 255, 0.28) 50%, transparent 60%);
    background-size: 240% 100%;
    animation: iv-sheen 4.2s ease-in-out infinite;
    pointer-events: none;
    z-index: 1;
  }
  /* Bigger sparkles for the bigger window (13px is the ~60px-tile size). */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card .eq-slot-card-canvas-wrap .iv-spark { width: 17px; height: 17px; }
  @media (prefers-reduced-motion: reduce) {
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="4"] .eq-slot-card-canvas-wrap::after,
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-rarity="5"] .eq-slot-card-canvas-wrap::after { animation: none; background: none; }
  }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot]:not([data-slot="superweapon"]) .eq-slot-card-canvas,
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot]:not([data-slot="superweapon"]) .eq-slot-card-svg {
    width: 100%; height: 100%; display: block;
  }
  /* Item name on the frame's bottom parchment banner. */
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"] .eq-slot-card-label,
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"] .eq-slot-card-label,
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"] .eq-slot-card-label,
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] .eq-slot-card-label {
    position: absolute;
    bottom: auto; top: 88%; left: 50%;            /* #6 — match the base rule (centred on the banner) */
    transform: translate(-50%, -50%);
    width: 76%; max-width: 76%;
    background: none; border: 0; box-shadow: none; border-radius: 0;
    padding: 0; margin: 0;
    color: #5a3a1c;
    font-family: 'EB Garamond', 'Cinzel', serif;
    font-weight: 700;
    font-size: clamp(10px, 1.25vw, 15px);
    line-height: 1.05; letter-spacing: 0.2px;
    text-align: center;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    text-shadow: 0 1px 0 rgba(255, 248, 224, 0.6);
  }
  /* Bigger cards aligned onto the two book pages (mock). */
  .play-hub-panel[data-tab="equipment"] .eq-loadout-grid {
    grid-template-columns: clamp(150px, 17.5%, 204px) 1fr clamp(150px, 17.5%, 204px);
    gap: 16px 30px;
    padding: 8px 56px 0;
  }
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"],
  .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] { max-width: 204px; }

  /* ─── rc-gear: fixed-aspect book + absolute middle (Figma 3336-2) ──────────
     The play-hub panel aspect varies with the window, so `cover` cropped the
     book and the cards drifted. Desktop/landscape only (≥641px; mobile keeps
     its vertical reflow above): make the BOOK a fixed 1440:804 box centered in
     a dark-wood panel, then pin the stat ribbon, 4 equipment cards, character
     pod and super-weapon bar at the exact Figma percentages of that box — so
     the middle aligns to the book on every screen. */
  @media (min-width: 641px) {
    .play-hub-panel[data-tab="equipment"] {
      background: radial-gradient(125% 96% at 50% 32%, #3a2412 0%, #241405 66%, #150b03 100%);
    }
    .play-hub-panel[data-tab="equipment"] .eq-tab-scroll {
      position: relative;
      /* Fill the panel using the EXACT same book settings as the STAGES tab
         (#stage-select-panel, stage-theme.css): same image, `cover` sizing,
         centered. Was a height-locked 1440:804 box (read smaller than the other
         tabs); a brief `100% 100%` fill stretched the art. `cover` keeps the
         book's true proportions like STAGES/SHOP. The %-pinned cards track it. */
      width: 100%; height: 100%;
      margin: 0; padding: 0; overflow: hidden;
      display: block;
      background: #2a1a0e url('../assets/shop/shop-book-bg.webp') center / cover no-repeat;
    }
    /* Stat ribbon — three cartouches across the top of both pages. */
    .play-hub-panel[data-tab="equipment"] .eq-stats {
      position: absolute; top: 12%; left: 19%; width: 62%;
      transform: none; padding: 0; gap: clamp(8px, 1.2vw, 18px);
      align-self: auto; justify-content: center;
    }
    /* Grid becomes a positioning canvas; cards are pinned individually. */
    .play-hub-panel[data-tab="equipment"] .eq-loadout-grid {
      position: absolute; inset: 0;
      display: block; padding: 0; gap: 0;
    }
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"],
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"],
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"],
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"] {
      position: absolute; width: 15.5%; max-width: none;
    }
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="gun"]       { left: 14.2%; top: 18%; }
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="secondary"] { left: 14.2%; top: 48%; }
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="shield"]    { left: 70.3%; top: 18%; }
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="drone"]     { left: 70.3%; top: 48%; }
    /* Center: player pod on the spine. */
    .play-hub-panel[data-tab="equipment"] .eq-character-card {
      position: absolute; left: 38%; top: 22%; width: 24%; height: 52%;
      max-width: none; margin: 0;
      align-self: auto; justify-self: auto;
      /* #8 — distinct opaque parchment pod (same as portrait) so the fox
         clearly sits INSIDE a parchment, per request — not blended away.
         #9 — slightly wider/taller box so the fox has headroom and isn't
         clipped (the fit logic in equipment-tab.js also frames to the box). */
      background: radial-gradient(ellipse at 50% 38%, #f9efd8 0%, #efe0bd 56%, #e1cb9c 100%);
      border: 2px solid rgba(120, 84, 42, 0.52);
      border-radius: 14px;
      box-shadow: 0 9px 22px rgba(38, 20, 6, 0.38), inset 0 0 42px rgba(140, 100, 52, 0.22);
    }
    /* Super-weapon bar below the player — a compact single-row parchment strip
       (the old min-height:58/72 + stacked meta blew it up to ~104px). */
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] {
      position: absolute; left: 30%; top: 82%; width: 40%; margin: 0;
      height: 9%; min-height: 0;
      display: flex; flex-direction: row; flex-wrap: nowrap;
      align-items: center; justify-content: flex-start; gap: 11px;
      padding: 0 18px; overflow: hidden;
    }
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] .eq-slot-card-canvas-wrap {
      width: clamp(32px, 6vh, 44px); height: clamp(32px, 6vh, 44px); flex: 0 0 auto;
    }
    /* One centred row (Figma 3336-2): icon · SUPER WEAPON · …spacer… · Nuke · Lv/Tier.
       The base label is position:absolute; rule 86 already statics it — keep it
       in-flow here and push the name + meta to the right edge. */
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] .eq-slot-card-label {
      flex: 0 0 auto; white-space: nowrap;
    }
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] .eq-slot-card-name {
      flex: 0 0 auto; margin-left: auto; margin-right: 8px; white-space: nowrap;
    }
    .play-hub-panel[data-tab="equipment"] .eq-slot-card[data-slot="superweapon"] .eq-slot-card-meta {
      flex: 0 0 auto; white-space: nowrap;
    }
  }
  .eq-section-head {
    padding-right: 48px;
  }
  .eq-section { display: flex; flex-direction: column; gap: 10px; }
  .eq-section-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 4px;
  }
  .eq-section-title {
    margin: 0;
    color: var(--text);
    font-size: 14px; font-weight: 800;
    letter-spacing: 1.6px;
  }
  .eq-section-shards {
    display: inline-flex; align-items: baseline; gap: 5px;
    padding: 4px 10px;
    background: rgba(126, 226, 255, 0.10);
    border: 1px solid rgba(126, 226, 255, 0.32);
    border-radius: var(--radius-pill);
    font-size: 11px; font-weight: 800;
    color: #d8f4ff;
    letter-spacing: 0.5px;
    white-space: nowrap;
  }
  .eq-section-shards-icon { color: #7ee2ff; font-size: 11px; }
  .eq-section-shards-label {
    font-size: 9px; font-weight: 700;
    letter-spacing: 1.2px;
    color: rgba(220, 230, 255, 0.55);
  }
  .eq-section-grid {
    display: flex; flex-direction: column;
    gap: 8px;
  }

  /* Single equipment card. Two rows: head (icon + text + action) + a
     thin upgrade row at the bottom. Locked cards dim to ~55% and
     replace the bottom row with a hint. Equipped cards get a gold
     ring + a checkmark badge. */
  .eq-card {
    display: flex; flex-direction: column;
    gap: 6px;
    padding: 10px 12px;
    /* rc158 — opaque card surface (was translucent purple-grey stack). */
    background: #1c1836;
    border: 1px solid #3a3464;
    border-radius: 12px;
    color: var(--text);
    transition: border-color 0.15s, transform 0.12s, box-shadow 0.15s;
  }
  .eq-card.is-locked {
    opacity: 0.55;
    background: #14122a;
  }
  .eq-card.is-equipped {
    border-color: #ffd766;
    background: #2a2238;
    box-shadow: 0 0 0 1px #ffd766 inset, 0 0 14px rgba(255, 180, 84, 0.35);
  }

  .eq-card-head {
    display: grid;
    grid-template-columns: 40px 1fr auto;
    align-items: center;
    gap: 10px;
  }
  .eq-card-icon {
    width: 40px; height: 40px;
    display: flex; align-items: center; justify-content: center;
    background: #25304a;
    border: 1px solid #3a4e78;
    border-radius: 10px;
    font-size: 20px;
    line-height: 1;
  }
  .eq-card.is-equipped .eq-card-icon {
    background: #443420;
    border-color: #ffd766;
  }
  .eq-card-text { min-width: 0; }
  .eq-card-name {
    margin: 0 0 1px;
    font-size: 13px; font-weight: 800;
    letter-spacing: 0.4px;
    color: var(--text);
    line-height: 1.2;
  }
  /* Level + tier badge row. Lv X / 100 stays understated; the tier
     chip on the right uses a per-tier accent color so the player can
     read their progression at a glance. */
  .eq-card-meta {
    display: inline-flex; align-items: center; gap: 6px;
    margin-bottom: 2px;
  }
  .eq-card-level {
    font-size: 10px;
    color: #c8d4ff;
    letter-spacing: 0.4px;
  }
  .eq-card-tier-chip {
    display: inline-block;
    padding: 1px 6px;
    font-size: 9px; font-weight: 800;
    letter-spacing: 0.8px;
    border-radius: 4px;
  }
  /* rc158 — opaque tier chips so they read at full saturation. */
  .eq-card-tier-chip-0 { background: #786a55;  color: #f6efd5; }
  .eq-card-tier-chip-1 { background: #6e6e7e;  color: #ffffff; }
  .eq-card-tier-chip-2 { background: #c98c40;  color: #fff5d6; }
  .eq-card-tier-chip-3 { background: linear-gradient(180deg, #c4a3ff, #8a6cff); color: #1a0f04; }
  .eq-card-desc {
    margin: 0;
    color: var(--text-dim);
    font-size: 10.5px;
    line-height: 1.35;
  }

  /* Action button — EQUIP / EQUIPPED / LOCKED. Always 80px wide so
     the alignment grid stays clean across cards. */
  .eq-card-action {
    display: inline-flex; align-items: center; justify-content: center;
    gap: 4px;
    min-width: 88px;
    padding: 8px 10px;
    border: 1px solid transparent;
    border-radius: 8px;
    font: inherit; font-size: 10.5px; font-weight: 800;
    letter-spacing: 0.8px;
    cursor: pointer;
    transition: transform 0.12s, filter 0.14s, background 0.14s;
    white-space: nowrap;
  }
  /* rc158 — opaque action buttons. The alpha gradient versions had
     to fight whichever card background sat behind them; flat colours
     give consistent contrast everywhere. */
  .eq-card-action.is-equip {
    background: #2a6f95;
    border-color: #7ee2ff;
    color: #ecfaff;
  }
  .eq-card-action.is-equip:hover { transform: translateY(-1px); filter: brightness(1.15); }
  .eq-card-action.is-equipped {
    background: #4a3a18;
    border-color: #ffd766;
    color: #ffe6a3;
    cursor: default;
  }
  .eq-card-action.is-locked {
    background: #1c2236;
    border-color: #2e3854;
    color: var(--text-dim);
    cursor: not-allowed;
  }

  /* Upgrade row at the bottom of every unlocked card. Locked cards
     show a "find a piece" hint in the same slot. */
  .eq-card-upgrade {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px;
    padding: 6px 4px 2px;
    border-top: 1px dashed rgba(255, 255, 255, 0.08);
  }
  .eq-card-upgrade.is-hint,
  .eq-card-upgrade.is-maxed {
    border-top: 1px dashed rgba(255, 255, 255, 0.08);
    color: var(--text-dim);
    font-size: 10.5px;
    padding: 6px 4px 2px;
    text-align: center;
    justify-content: center;
  }
  .eq-card-upgrade-label {
    font-size: 10.5px; letter-spacing: 0.4px;
    color: var(--text-dim);
  }
  .eq-card-upgrade.is-maxed .eq-card-upgrade-label {
    color: rgba(255, 215, 102, 0.85);
    font-weight: 800;
    letter-spacing: 1.2px;
  }
  .eq-card-upgrade-btn {
    padding: 6px 14px;
    /* rc158 — opaque upgrade pill. */
    background: #5e3aa8;
    border: 1px solid var(--lilac);
    border-radius: var(--radius-pill);
    color: #f4ebff;
    font: inherit; font-size: 10.5px; font-weight: 800;
    letter-spacing: 0.6px;
    cursor: pointer;
    transition: transform 0.12s, filter 0.14s, opacity 0.14s;
  }
  .eq-card-upgrade-btn:hover:not(:disabled) {
    transform: translateY(-1px);
    filter: brightness(1.10);
  }
  .eq-card-upgrade-btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
  }
  .eq-card-upgrade-cost {
    font-size: 10.5px; font-weight: 700;
    color: var(--text-dim);
    letter-spacing: 0.4px;
  }

  /* Evolution gate variant. Highlighted card border + the upgrade
     button paints in warm gold to read as a special action ("the
     next level isn't just stronger — it's an evolution"). */
  .eq-card.is-at-gate {
    border-color: #ffd766;
    box-shadow: 0 0 0 1px #ffd766 inset, 0 0 14px rgba(255, 180, 84, 0.45);
  }
  .eq-card-upgrade-btn.is-evolve {
    background: linear-gradient(180deg, #ffe28e 0%, #ffb454 60%, #d99528 100%);
    border: 1px solid rgba(140, 86, 18, 0.65);
    color: #2a1a08;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.55),
      0 4px 12px rgba(217, 149, 40, 0.45);
  }
  .eq-card-upgrade-btn.is-evolve:disabled {
    opacity: 0.50;
    filter: grayscale(0.4);
  }

  /* Evolution-stone counter at the top of the Equipment tab. Stones
     are slot-agnostic + rare — pulling them up gives them their own
     real estate above the per-slot shard counters. */
  .eq-tab-stones {
    display: inline-flex; align-items: baseline; gap: 6px;
    margin: 0 0 16px;
    padding: 7px 14px;
    /* rc158 — opaque stone counter. */
    background: #3b2a6c;
    border: 1px solid var(--lilac);
    border-radius: var(--radius-pill);
    color: #f4ebff;
    font-size: 13px; font-weight: 800;
    letter-spacing: 0.4px;
  }
  .eq-tab-stones-icon { color: #d6c4ff; font-size: 14px; }
  .eq-tab-stones-label {
    font-size: 10px; font-weight: 700;
    letter-spacing: 1.2px;
    color: rgba(220, 230, 255, 0.65);
  }

  /* ── PER-SLOT IDENTITY COLORS ─────────────────────────────────────
     Each slot gets its own hue so the tab reads like a 4-color cartoon
     loadout rather than a cyan-everywhere SaaS dashboard. The CSS vars
     cascade so card, chip, section header, and detail panel all inherit
     the slot identity from the nearest `data-slot` ancestor. */
  [data-slot="shield"]    { --slot: #4cc8ff; --slot-soft: rgba(76,200,255,.16); --slot-deep: rgba(76,200,255,.55); }
  [data-slot="gun"]       { --slot: #ff8a3a; --slot-soft: rgba(255,138,58,.16); --slot-deep: rgba(255,138,58,.55); }
  [data-slot="secondary"] { --slot: #4cdd8a; --slot-soft: rgba(76,221,138,.16); --slot-deep: rgba(76,221,138,.55); }
  [data-slot="drone"]     { --slot: #ff7fc6; --slot-soft: rgba(255,127,198,.16); --slot-deep: rgba(255,127,198,.55); }

  /* Equipment-tab character preview — top of the tab. Houses the Three.js
     canvas + the 4-chip loadout summary. Canvas auto-sizes; chips wrap on
     narrow. Per-chip slot color comes from the [data-slot] var above. */
  .eq-preview {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 14px;
    border-radius: 18px;
    background:
      radial-gradient(circle at 30% 0%, rgba(76,200,255,.10), transparent 50%),
      radial-gradient(circle at 80% 100%, rgba(255,127,198,.10), transparent 55%),
      linear-gradient(180deg, rgba(36,46,82,.65), rgba(18,24,44,.65));
    border: 1px solid rgba(140,180,230,.20);
    box-shadow: 0 12px 36px -16px rgba(0,0,0,.45) inset;
  }
  .eq-preview-canvas {
    width: 100%;
    height: min(40vh, 300px);
    display: block;
    border-radius: 14px;
    background:
      radial-gradient(ellipse at 50% 75%, rgba(76,200,255,.10) 0%, transparent 60%),
      radial-gradient(ellipse at center, #1a2444 0%, #0a0e1c 75%);
  }
  .eq-preview-chips {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px;
  }
  .eq-preview-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 10px;
    border-radius: 12px;
    background: linear-gradient(180deg, var(--slot-soft), rgba(20,26,48,.6));
    border: 1.5px solid color-mix(in srgb, var(--slot, #4cc8ff) 40%, transparent);
    color: #f3f7ff;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: transform .12s ease, border-color .15s ease, box-shadow .15s ease;
    min-width: 0;
  }
  .eq-preview-chip:hover {
    border-color: var(--slot);
    box-shadow: 0 6px 18px -8px var(--slot-deep);
    transform: translateY(-1px);
  }
  .eq-preview-chip:active { transform: scale(.97); }
  .eq-preview-chip-icon {
    width: 24px; height: 24px;
    flex-shrink: 0;
    color: var(--slot);
    display: flex;
    align-items: center;
    justify-content: center;
    filter: drop-shadow(0 0 8px color-mix(in srgb, var(--slot) 35%, transparent));
  }
  .eq-preview-chip-icon svg { width: 100%; height: 100%; display: block; }
  .eq-preview-chip-name {
    font-size: 13px;
    font-weight: 700;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: 0.15px;
    min-width: 0;
    flex: 1 1 auto;
  }
  .eq-preview-chip-lv {
    font-size: 10px;
    font-weight: 800;
    color: var(--slot);
    letter-spacing: 0.3px;
    flex-shrink: 0;
    background: color-mix(in srgb, var(--slot) 18%, transparent);
    padding: 2px 7px;
    border-radius: var(--radius-pill);
    border: 1px solid color-mix(in srgb, var(--slot) 35%, transparent);
  }

  /* ── SLOT-COLOR CARD ICONS ─────────────────────────────────────── */
  .eq-card-icon {
    color: var(--slot, #88c8ff);
    filter: drop-shadow(0 0 10px color-mix(in srgb, var(--slot, #88c8ff) 35%, transparent));
  }
  .eq-card-icon svg { width: 100%; height: 100%; display: block; }

  /* ── EQUIPPED CARD HERO TREATMENT ──────────────────────────────────
     The currently-equipped card glows with its slot color, ribbons a
     "★ EQUIPPED" corner, and lifts slightly on hover. So the active
     loadout is unmissable. */
  .eq-card.is-equipped {
    border-color: var(--slot);
    background:
      linear-gradient(135deg, var(--slot-soft) 0%, transparent 55%),
      rgba(18,24,44,.85);
    box-shadow:
      0 0 0 2px var(--slot-deep),
      0 14px 38px -16px var(--slot-deep);
    position: relative;
  }
  .eq-card.is-equipped::before {
    content: "★ EQUIPPED";
    position: absolute;
    top: 10px; right: 10px;
    background: var(--slot);
    color: #0a0e1c;
    font-size: 10px;
    font-weight: 900;
    letter-spacing: 1.4px;
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    box-shadow: 0 4px 14px -4px var(--slot-deep);
    pointer-events: none;
    z-index: 2;
  }
  /* Hide the now-redundant equipped action badge — corner ribbon is the
     hero. Keep the markup for screen readers; just zero its layout. */
  .eq-card.is-equipped .eq-card-action.is-equipped {
    visibility: hidden;
    width: 0;
    padding: 0;
    margin: 0;
  }

  /* ── SELECTED CARD HIGHLIGHT ─────────────────────────────────────── */
  .eq-card.is-selected {
    border-color: var(--slot);
    box-shadow:
      0 0 0 2px var(--slot-deep),
      0 10px 30px -8px var(--slot-deep);
  }

  /* ── INLINE DETAIL PANEL — STAT VALUES ARE HERO ───────────────────
     The actual value at current level is the most informative thing in
     the entire tab. Render the value at hero size (big bold colored)
     with the label smaller and quieter. */
  .eq-card-details {
    grid-column: 1 / -1;
    margin-top: 10px;
    padding: 14px 16px;
    border-top: 1px dashed color-mix(in srgb, var(--slot) 35%, transparent);
    background:
      linear-gradient(180deg, var(--slot-soft) 0%, transparent 80%),
      rgba(12,18,32,.55);
    border-radius: 12px;
  }
  .eq-card-details-blurb {
    margin: 0 0 12px 0;
    font-size: 13px;
    line-height: 1.5;
    color: rgba(225, 235, 255, 0.9);
    font-style: italic;
  }
  .eq-card-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 10px;
    margin: 0;
  }
  .eq-card-stats > * { margin: 0; }
  .eq-stat-row-key {
    font-size: 10px;
    color: rgba(200, 215, 245, 0.65);
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    margin-bottom: 2px;
  }
  .eq-stat-row-val {
    font-size: 24px;
    color: var(--slot, #88e2ff);
    font-weight: 900;
    letter-spacing: 0.2px;
    text-align: left;
    line-height: 1.1;
    text-shadow: 0 0 18px color-mix(in srgb, var(--slot, #88e2ff) 30%, transparent);
  }
  .eq-card-details.is-locked-details .eq-card-details-blurb {
    color: rgba(220, 230, 255, 0.55);
  }

  /* ── SECTION HEADER — slot-tinted ─────────────────────────────────── */
  .eq-section-title {
    color: var(--slot, #fff) !important;
    text-shadow: 0 0 14px color-mix(in srgb, var(--slot, #fff) 25%, transparent);
  }
  .eq-section-shards {
    background: color-mix(in srgb, var(--slot) 12%, rgba(20,26,48,.7)) !important;
    border-color: color-mix(in srgb, var(--slot) 40%, transparent) !important;
  }
  .eq-section-shards-icon { color: var(--slot, #7ee2ff) !important; }
  .eq-section-shards-count { color: #fff !important; }

  /* ── MOBILE — preview shrinks, chips stack 2×2 ─────────────────── */
  @media (max-width: 480px) {
    .eq-preview-canvas { height: 220px; }
    .eq-preview-chips { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .eq-card-details { padding: 12px; }
    .eq-stat-row-val { font-size: 20px; }
  }

  /* ──────────────────────────────────────────────────────────────────
     ITEM DETAIL MODAL (popup detail sheet for equipment cards)
     Lives outside .play-hub-panel so it can float above the panel's
     overflow:hidden + ride atop the existing hub modal.
       - Mobile (<480px): bottom sheet, slides up from bottom
       - Desktop: centered modal, fade+scale in
     Slot color cascades from data-slot on the modal root, same vars
     defined above so the modal panel auto-themes per item.
     ────────────────────────────────────────────────────────────────── */
  .eq-detail-modal {
    position: fixed;
    inset: 0;
    z-index: 280;  /* above the play-hub modal (z 250-260) */
    display: none;
    pointer-events: none;
  }
  .eq-detail-modal.is-open {
    display: block;
    pointer-events: auto;
  }
  .eq-detail-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(6, 10, 22, 0.72);
    opacity: 0;
    transition: opacity 0.20s ease;
  }
  .eq-detail-modal.is-open .eq-detail-modal-backdrop { opacity: 1; }

  .eq-detail-modal-panel {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%) scale(0.94);
    width: min(440px, 92vw);
    max-height: 86vh;
    display: flex;
    flex-direction: column;
    /* rc158 — opaque modal panel; was a translucent dark gradient
       that mixed with the gameplay canvas behind it. */
    background: var(--panel-bg, #131a2e);
    border: 2px solid var(--slot, #4cc8ff);
    border-radius: 20px;
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--slot, #4cc8ff) 30%, transparent),
      0 28px 60px -20px rgba(0, 0, 0, 0.6),
      0 12px 28px -8px color-mix(in srgb, var(--slot, #4cc8ff) 30%, transparent);
    opacity: 0;
    transition: transform 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.1), opacity 0.18s ease;
    overflow: hidden;
  }
  .eq-detail-modal.is-open .eq-detail-modal-panel {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
  }

  /* Mobile bottom-sheet override */
  @media (max-width: 480px) {
    .eq-detail-modal-panel {
      left: 0;
      right: 0;
      top: auto;
      bottom: 0;
      width: 100%;
      max-width: none;
      max-height: 82vh;
      transform: translateY(100%);
      border-radius: 20px 20px 0 0;
      border-bottom: none;
    }
    .eq-detail-modal.is-open .eq-detail-modal-panel {
      transform: translateY(0);
    }
  }

  .eq-detail-modal-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 18px 18px 12px 18px;
    border-bottom: 1px dashed color-mix(in srgb, var(--slot) 30%, transparent);
    position: relative;
  }
  /* Drag handle (mobile only) — subtle visual cue this is a draggable sheet */
  @media (max-width: 480px) {
    .eq-detail-modal-head::before {
      content: "";
      position: absolute;
      top: 6px;
      left: 50%;
      transform: translateX(-50%);
      width: 36px;
      height: 4px;
      border-radius: 2px;
      background: rgba(255, 255, 255, 0.18);
    }
    .eq-detail-modal-head { padding-top: 22px; }
  }
  .eq-detail-modal-icon {
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    color: var(--slot);
    background: color-mix(in srgb, var(--slot) 18%, rgba(20, 26, 48, 0.5));
    border: 2px solid color-mix(in srgb, var(--slot) 45%, transparent);
    border-radius: 14px;
    padding: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    filter: drop-shadow(0 0 14px color-mix(in srgb, var(--slot) 40%, transparent));
  }
  .eq-detail-modal-icon svg { width: 100%; height: 100%; display: block; }
  .eq-detail-modal-title {
    flex: 1 1 auto;
    min-width: 0;
  }
  .eq-detail-modal-name {
    font-size: 20px;
    font-weight: 800;
    color: #fff;
    margin: 0 0 4px 0;
    letter-spacing: 0.2px;
  }
  .eq-detail-modal-meta {
    display: flex;
    gap: 8px;
    align-items: center;
    font-size: 12px;
    color: rgba(220, 230, 255, 0.75);
  }
  .eq-detail-modal-level {
    font-weight: 700;
    color: var(--slot);
  }
  .eq-detail-modal-tier {
    background: color-mix(in srgb, var(--slot) 20%, transparent);
    border: 1px solid color-mix(in srgb, var(--slot) 45%, transparent);
    color: var(--slot);
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 1px;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
  }
  .eq-detail-modal-close {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.14);
    color: #fff;
    font-size: 22px;
    font-weight: 300;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease, transform 0.1s ease;
    flex-shrink: 0;
  }
  .eq-detail-modal-close:hover {
    background: rgba(255, 255, 255, 0.16);
  }
  .eq-detail-modal-close:active { transform: scale(0.92); }

  .eq-detail-modal-body {
    padding: 16px 18px;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
  }
  .eq-detail-modal-blurb {
    margin: 0 0 16px 0;
    font-size: 14px;
    line-height: 1.5;
    color: rgba(230, 240, 255, 0.92);
    font-style: italic;
  }
  .eq-detail-modal-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 14px;
    margin: 0 0 12px 0;
  }
  .eq-detail-modal-stats > * { margin: 0; }
  .eq-detail-modal-stat-key {
    font-size: 10px;
    color: rgba(200, 215, 245, 0.65);
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    margin-bottom: 4px;
  }
  .eq-detail-modal-stat-val {
    font-size: 32px;
    color: var(--slot);
    font-weight: 900;
    letter-spacing: 0.2px;
    line-height: 1;
    text-shadow: 0 0 24px color-mix(in srgb, var(--slot) 40%, transparent);
  }

  .eq-detail-modal-foot {
    padding: 14px 18px 18px 18px;
    border-top: 1px dashed color-mix(in srgb, var(--slot) 25%, transparent);
    display: flex;
    gap: 10px;
    flex-direction: column;
  }
  .eq-detail-modal-action {
    flex: 1 1 auto;
    padding: 14px 16px;
    border-radius: 12px;
    font-size: 15px;
    font-weight: 800;
    letter-spacing: 1px;
    cursor: pointer;
    transition: transform 0.1s ease, background 0.15s ease, box-shadow 0.15s ease;
    border: none;
  }
  .eq-detail-modal-action.is-equip {
    background: linear-gradient(135deg, var(--slot), color-mix(in srgb, var(--slot) 65%, #fff));
    color: #0a0e1c;
    box-shadow: 0 6px 20px -6px var(--slot-deep);
  }
  .eq-detail-modal-action.is-equipped {
    background: rgba(255, 255, 255, 0.06);
    color: var(--slot);
    border: 1.5px solid var(--slot);
    cursor: default;
  }
  .eq-detail-modal-action.is-upgrade {
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    border: 1.5px solid color-mix(in srgb, var(--slot) 50%, transparent);
  }
  .eq-detail-modal-action.is-upgrade:hover:not(:disabled) {
    background: color-mix(in srgb, var(--slot) 25%, rgba(255, 255, 255, 0.08));
    border-color: var(--slot);
  }
  .eq-detail-modal-action.is-evolve {
    background: linear-gradient(135deg, #ffd000, #ff8a3a);
    color: #0a0e1c;
    border: none;
    box-shadow: 0 6px 20px -6px rgba(255, 200, 60, 0.6);
  }
  .eq-detail-modal-action:disabled {
    opacity: 0.45;
    cursor: not-allowed;
  }
  .eq-detail-modal-action:not(:disabled):hover { transform: translateY(-1px); }
  .eq-detail-modal-action:not(:disabled):active { transform: translateY(0) scale(0.98); }
  .eq-detail-modal-cost {
    font-size: 12px;
    text-align: center;
    color: rgba(220, 230, 255, 0.7);
    margin-top: -4px;
  }
  .eq-detail-modal-cost strong {
    color: var(--slot);
    font-weight: 800;
  }
  .eq-detail-modal.is-locked .eq-detail-modal-foot,
  .eq-detail-modal.is-maxed .eq-detail-modal-action.is-upgrade {
    display: none;
  }
  .eq-detail-modal-maxed-note {
    text-align: center;
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 1.4px;
    color: var(--slot);
    padding: 8px;
    text-transform: uppercase;
  }

  /* ══════════════════════════════════════════════════════════════════
     EQUIPMENT TAB — LOADOUT-FIRST LAYOUT (rc69)
     The 4 slot tiles ARE the primary UI. Each tile shows the currently
     equipped item with personality (slot color, watermark glyph, big
     name). Tap a tile → slot picker modal lists the 5 items in that
     slot. No more scrollable card grid.
     ══════════════════════════════════════════════════════════════════ */

  .eq-loadout {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    padding: 4px 0 0;
  }
  /* Mobile (≤640px): v3 (rc81) — vertical stack of full-width tiles.
     The 3D hero preview is gone, so the loadout has the screen to itself.
     Tiles become horizontal rows (icon left, name + meta right) to read
     comfortably on portrait phones. Per-tile vertical layout rules are
     overridden in the inner block below. */
  @media (max-width: 640px) {
    .eq-loadout {
      grid-template-columns: 1fr;
      gap: 12px;
      padding: 8px 0 0;
    }
  }

  /* ══════════════════════════════════════════════════════════════════
     EQUIPMENT TAB — 1-2-1 LOADOUT GRID (rc116)
     Replaces the vertical stack. Center column is the live character
     preview; flanking columns host the 4 slot cards (gun + secondary
     on the left, shield + drone on the right). Each card has its own
     mini WebGL canvas streaming the equipped item's GLB. Tap a card
     to open the picker (same modal as before).
     ══════════════════════════════════════════════════════════════════ */
  .eq-loadout-grid {
    display: grid;
    grid-template-columns: clamp(80px, 18vh, 190px) 1fr clamp(80px, 18vh, 190px);
    grid-template-rows: auto auto;
    gap: 4px 10px;
    padding: 4px 0 0;
  }
  .eq-slot-card[data-slot="gun"]       { grid-column: 1; grid-row: 1; }
  .eq-slot-card[data-slot="secondary"] { grid-column: 1; grid-row: 2; }
  .eq-character-card                   { grid-column: 2; grid-row: 1 / 3; }
  .eq-slot-card[data-slot="shield"]    { grid-column: 3; grid-row: 1; }
  .eq-slot-card[data-slot="drone"]     { grid-column: 3; grid-row: 2; }
  .eq-slot-card[data-slot="superweapon"] {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 14px;
    padding: 12px 16px;
    min-height: 72px;
    margin-top: 10px;
  }
  .eq-slot-card[data-slot="superweapon"] {
    --slot-color: #ffd166;
    /* Parchment scroll banner (rc332) — same ribbon art as the stat strip,
       so the super-weapon row reads as a scroll on the page rather than a
       transparent pill over the dark desk. */
    background: url('../assets/stage-select/figma/chapter-ribbon.png') center / 100% 100% no-repeat;
    border: none;
    border-radius: 0;
    box-shadow: none;
    width: min(560px, 92%);
    margin-left: auto; margin-right: auto;
    justify-content: center;
    gap: 16px;
  }
  .eq-slot-card[data-slot="superweapon"] .eq-slot-card-canvas-wrap {
    width: 56px; height: 56px; flex: 0 0 56px;
    background: rgba(80, 60, 30, 0.3);
    border-radius: 12px;
    border: 1px solid rgba(180, 150, 100, 0.35);
  }
  .eq-slot-card[data-slot="superweapon"] .eq-slot-card-svg svg {
    width: 70%; height: 70%;
  }
  /* rc156 — superweapon pill text needs a stronger left-aligned hierarchy
     since the row form-factor lays the label / name / meta horizontally.
     Without these overrides the meta clings to the canvas and the level
     pill is hard to scan. */
  .eq-slot-card[data-slot="superweapon"] .eq-slot-card-label {
    font-size: 10px;
    letter-spacing: 2px;
    color: #6a5640;
    margin-right: 0;
  }
  .eq-slot-card[data-slot="superweapon"] .eq-slot-card-name {
    display: inline;
    font-size: 16px;
    font-weight: 900;
    color: #4b3522;
    margin-right: 12px;
  }
  .eq-slot-card[data-slot="superweapon"] .eq-slot-card-lv {
    color: #6a5640 !important;
  }
  .eq-slot-card[data-slot="superweapon"] .eq-slot-card-meta {
    display: flex;
    gap: 8px;
    align-items: center;
    flex: 0 0 auto;
  }
  .eq-slot-card[data-slot="superweapon"] .eq-slot-card-lv {
    font-size: 12px;
    font-weight: 800;
    color: rgba(200, 180, 140, 0.85);
  }

  .eq-slot-card {
    position: relative;
    display: block;
    padding: 0;
    border-radius: 8px;
    background: linear-gradient(160deg, rgba(80, 40, 120, 0.88), rgba(40, 20, 80, 0.94));
    border: 5px solid #a07838;
    box-shadow:
      inset 0 0 0 2px rgba(255, 220, 160, 0.3),
      inset 0 0 0 4px rgba(80, 50, 20, 0.35),
      0 4px 16px rgba(0, 0, 0, 0.55);
    color: #e8effa;
    cursor: pointer;
    overflow: visible;
    transition: transform 120ms ease, border-color 120ms ease;
    font-family: inherit;
    -webkit-tap-highlight-color: transparent;
    margin-bottom: 14px;
  }
  .eq-slot-card[data-slot="shield"]    { --slot-color: #4cc8ff; background: linear-gradient(160deg, rgba(20, 50, 120, 0.90), rgba(10, 25, 80, 0.95)); }
  .eq-slot-card[data-slot="gun"]       { --slot-color: #ff8a3a; background: linear-gradient(160deg, rgba(100, 30, 140, 0.90), rgba(50, 15, 90, 0.95)); }
  .eq-slot-card[data-slot="secondary"] { --slot-color: #66ff88; background: linear-gradient(160deg, rgba(90, 30, 130, 0.90), rgba(45, 15, 85, 0.95)); }
  .eq-slot-card[data-slot="drone"]     { --slot-color: #ff6fb3; background: linear-gradient(160deg, rgba(15, 50, 110, 0.90), rgba(8, 25, 75, 0.95)); }
  .eq-slot-card:hover  { transform: translateY(-1px); border-color: #c8a04a; }
  .eq-slot-card:active { transform: translateY(0) scale(0.985); }

  .eq-slot-card-canvas-wrap {
    position: relative;
    width: 100%;
    aspect-ratio: 1;
    display: block;
    border-radius: inherit;
    overflow: hidden;
  }
  .eq-slot-card-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
  }
  .eq-slot-card-label {
    position: absolute;
    bottom: -20px;
    left: 50%;
    transform: translateX(-50%);
    white-space: nowrap;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: clamp(11px, 1.4vw, 15px);
    font-weight: 700;
    letter-spacing: 0.05em;
    color: #5a4a35;
    text-shadow: 0 1px 0 rgba(255, 240, 200, 0.4);
    text-transform: capitalize;
    pointer-events: none;
  }
  .eq-slot-card-name {
    display: none;
  }
  .eq-slot-card-meta {
    display: none;
  }
  .eq-slot-card-lv, .eq-slot-card-tier {
    padding: 2px 8px;
    border-radius: 8px;
    background: rgba(255,255,255,.06);
    white-space: nowrap;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.4px;
  }

  /* Center character card — bigger, taller, and the canvas takes nearly
     the whole card. Drag interaction is wired in JS via pointer events. */
  .eq-character-card {
    position: relative;
    display: block;
    min-width: 0;
    border-radius: 0;
    background: transparent;
    border: none;
    overflow: hidden;
  }
  .eq-character-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    /* The pointer-events sit on the canvas so dragging works; the parent
       card has no other interactive children. */
    touch-action: none;
    cursor: grab;
  }
  .eq-character-canvas:active { cursor: grabbing; }
  .eq-character-hint {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    padding: 4px 10px;
    border-radius: 10px;
    background: rgba(0,0,0,.45);
    color: #cbd6ee;
    font-size: 9px;
    letter-spacing: 0.4px;
    pointer-events: none;
    opacity: 0.7;
  }

  /* Narrow phones — keep the same 1-2-1 grid (the sketch demands it)
     but tighten gaps + label sizes so it fits at 390px wide. */
  @media (max-width: 540px) {
    .eq-loadout-grid { gap: 8px 6px; }
    .eq-slot-card { border-width: 4px; margin-bottom: 16px; }
    .eq-slot-card-label { font-size: 9px; bottom: -16px; }
    .eq-character-hint { font-size: 8px; padding: 3px 8px; }
    .eq-slot-card[data-slot="superweapon"] { margin-top: 4px; margin-bottom: 0; }
  }

  /* ══════════════════════════════════════════════════════════════════
     Live build summary (rc79+, kept in v3)
     The 3D preview is gone in v3 (rc81) — showcase moved into the
     picker — but the DMG / HP / UTIL pill row stays as a quick-read
     loadout summary above the slot tiles.
     ══════════════════════════════════════════════════════════════════ */

  /* Live stat strip — DMG / HP / UTIL pills computed from the loadout.
     Always visible (mobile + desktop). Per-pill slot color via --slot. */
  .eq-stats {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(12px, 3vw, 32px);
    padding: 0 clamp(24px, 6%, 48px);
    background: url('../assets/stage-select/figma/chapter-ribbon.png') center / 100% 100% no-repeat;
    height: clamp(38px, 6vh, 72px);
    margin: 0 auto;
    max-width: 100%;
  }
  .eq-stat {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: clamp(10px, 1.6vw, 16px);
    font-weight: 700;
    color: #542e1f;
    letter-spacing: 0.04em;
    overflow: hidden;
    white-space: nowrap;
  }
  .eq-stat-icon { font-size: clamp(12px, 1.8vw, 18px); line-height: 1; }
  .eq-stat-label { color: #542e1f; font-weight: 800; }
  .eq-stat-val {
    margin-left: 4px;
    color: #3a1e12;
    font-size: clamp(12px, 1.8vw, 18px);
    font-weight: 900;
    text-shadow: none;
  }

  /* Stat strip entry animation — slides up on tab open. Gated on
     prefers-reduced-motion below. */
  @keyframes eq-stats-enter {
    from { opacity: 0; translate: 0 8px; }
    to   { opacity: 1; translate: 0 0; }
  }
  .eq-stats { animation: eq-stats-enter 0.45s ease-out 0.10s both; }
  @media (prefers-reduced-motion: reduce) {
    .eq-stats { animation: none; }
  }


  .eq-slot-tile {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    min-height: 168px;
    padding: 14px 14px 14px;
    border-radius: 18px;
    /* rc158 — opaque tile + solid slot-tinted top, replacing the
       layered alpha radial that washed out the slot accent. */
    border: 2px solid var(--slot, #4cc8ff);
    background: color-mix(in srgb, var(--slot, #4cc8ff) 18%, var(--card-bg, #1a2138));
    color: #fff;
    font: inherit;
    text-align: left;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 6px;
    transition: transform .14s cubic-bezier(0.25, 0.9, 0.3, 1.05),
                border-color .15s ease,
                box-shadow .18s ease;
    box-shadow:
      0 6px 22px -10px color-mix(in srgb, var(--slot) 38%, transparent),
      0 0 0 1px color-mix(in srgb, var(--slot) 22%, transparent) inset;
    /* Subtle slot-color glow breath (paused under reduced-motion).
       Animates box-shadow + border-color so the tile feels alive without
       moving content. */
    animation: eq-tile-breath 4.5s ease-in-out infinite alternate;
  }
  .eq-slot-tile:nth-child(2) { animation-delay: -1.0s; }
  .eq-slot-tile:nth-child(3) { animation-delay: -2.2s; }
  .eq-slot-tile:nth-child(4) { animation-delay: -3.3s; }
  @keyframes eq-tile-breath {
    0%   {
      box-shadow:
        0 6px 22px -10px color-mix(in srgb, var(--slot) 30%, transparent),
        0 0 0 1px color-mix(in srgb, var(--slot) 18%, transparent) inset;
      border-color: color-mix(in srgb, var(--slot) 45%, transparent);
    }
    100% {
      box-shadow:
        0 14px 36px -10px color-mix(in srgb, var(--slot) 65%, transparent),
        0 0 0 1px color-mix(in srgb, var(--slot) 35%, transparent) inset;
      border-color: color-mix(in srgb, var(--slot) 75%, transparent);
    }
  }

  /* Per-slot asymmetric clipped corner — breaks the uniform rounded
     rectangle so each tile reads as having custom personality. */
  [data-slot="shield"]    .eq-slot-tile { clip-path: polygon(0 0, 100% 0, 100% calc(100% - 22px), calc(100% - 22px) 100%, 0 100%); }
  [data-slot="gun"]       .eq-slot-tile { clip-path: polygon(22px 0, 100% 0, 100% 100%, 0 100%, 0 22px); }
  [data-slot="secondary"] .eq-slot-tile { clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 0 100%); }
  [data-slot="drone"]     .eq-slot-tile { clip-path: polygon(0 0, 100% 0, 100% 100%, 22px 100%, 0 calc(100% - 22px)); }

  .eq-slot-tile:hover {
    transform: translateY(-3px);
    border-color: var(--slot);
    box-shadow:
      0 16px 36px -10px color-mix(in srgb, var(--slot) 60%, transparent),
      0 0 0 1px var(--slot) inset;
  }
  .eq-slot-tile:active { transform: translateY(0) scale(0.985); }

  /* Holographic shine — diagonal light sweep on hover. */
  .eq-slot-tile::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
      120deg,
      transparent 30%,
      color-mix(in srgb, var(--slot) 32%, white 12%) 50%,
      transparent 70%
    );
    transform: translateX(-110%);
    pointer-events: none;
    z-index: 3;
    opacity: 0;
    transition: transform 0.9s ease, opacity 0.2s ease;
  }
  .eq-slot-tile:hover::after {
    transform: translateX(110%);
    opacity: 0.45;
  }

  /* Big watermark icon — large, vivid, sits behind everything. */
  .eq-slot-tile-watermark {
    position: absolute;
    right: -34px;
    bottom: -38px;
    width: 180px;
    height: 180px;
    color: var(--slot);
    opacity: 0.18;
    pointer-events: none;
    z-index: 0;
    transform: rotate(-18deg);
    filter: blur(0.5px) drop-shadow(0 0 24px color-mix(in srgb, var(--slot) 30%, transparent));
  }
  .eq-slot-tile-watermark svg { width: 100%; height: 100%; display: block; }

  /* Slot label — pill in upper-right corner. */
  .eq-slot-tile-slot {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 2;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 1.4px;
    color: color-mix(in srgb, var(--slot) 85%, white 15%);
    text-transform: uppercase;
    background: color-mix(in srgb, var(--slot) 24%, rgba(14, 18, 36, .72));
    border: 1px solid color-mix(in srgb, var(--slot) 45%, transparent);
    padding: 3px 9px;
    border-radius: var(--radius-pill);
  }

  /* Hero icon (slot-color glyph in upper-left of tile body). */
  .eq-slot-tile-icon {
    position: relative;
    z-index: 1;
    width: 42px;
    height: 42px;
    color: var(--slot);
    margin-bottom: 4px;
    filter: drop-shadow(0 0 14px color-mix(in srgb, var(--slot) 45%, transparent));
  }
  .eq-slot-tile-icon svg { width: 100%; height: 100%; display: block; }

  /* Drone tile thumbnail — replaces the slot SVG with a render of the
     equipped drone's GLB. <img> sits on top of the fallback SVG (the
     fallback shows until the thumbnail data URL resolves). */
  .eq-slot-tile-icon-thumb {
    width: 64px;
    height: 64px;
    margin-bottom: 6px;
    filter: drop-shadow(0 0 18px color-mix(in srgb, var(--slot) 55%, transparent));
  }
  .eq-slot-tile-thumb-fallback {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    color: var(--slot);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity .2s ease;
  }
  .eq-slot-tile-thumb-fallback svg { width: 60%; height: 60%; }
  /* Live revolving GLB canvas. Mounted by _mountLoadoutTilePreview after
     render(); fade in on .is-mounted so it doesn't pop before the GLB
     resolves. Fallback SVG underneath fades out at the same time. */
  .eq-slot-tile-thumb-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    opacity: 0;
    transition: opacity .25s ease;
  }
  .eq-slot-tile-thumb-canvas.is-mounted { opacity: 1; }
  .eq-slot-tile-icon-thumb:has(.eq-slot-tile-thumb-canvas.is-mounted) .eq-slot-tile-thumb-fallback {
    opacity: 0;
  }

  .eq-slot-tile-name {
    position: relative; z-index: 1;
    font-size: 18px;
    font-weight: 900;
    letter-spacing: 0.2px;
    color: #fff;
    line-height: 1.15;
    margin: 2px 0 6px;
    /* Allow up to 2 lines for long names like "Grenade Launcher" without
       splitting mid-word. The slot pill is absolute-positioned in the
       upper-right corner, so name has full tile width below it. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: normal;
    word-break: normal;
    hyphens: none;
  }
  .eq-slot-tile-meta {
    position: relative; z-index: 1;
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
    margin-top: auto;
  }
  .eq-slot-tile-lv {
    font-size: 11px;
    font-weight: 800;
    color: var(--slot);
    letter-spacing: 0.5px;
    background: color-mix(in srgb, var(--slot) 22%, transparent);
    padding: 3px 9px;
    border-radius: var(--radius-pill);
    border: 1px solid color-mix(in srgb, var(--slot) 40%, transparent);
  }
  .eq-slot-tile-tier {
    font-size: 10px;
    font-weight: 900;
    letter-spacing: 0.8px;
    color: #0a0e1c;
    background: color-mix(in srgb, var(--slot) 95%, white 5%);
    padding: 2px 8px;
    border-radius: 6px;
    white-space: nowrap;
  }

  /* Respect reduced-motion preference — pause breath + shine. */
  @media (prefers-reduced-motion: reduce) {
    .eq-slot-tile { animation: none; }
    .eq-slot-tile::after { transition: none; }
    .eq-slot-tile:hover::after { transform: translateX(-110%); opacity: 0; }
  }

  /* ── Mobile horizontal-row tile (v3, rc81+) ──────────────────────
     The card-style tile (vertical: icon-top, name-mid, badges-bottom)
     was great when 4 fit on a 2×2 grid; now that mobile has a single
     vertical column, the tiles are too tall and have a lot of dead
     space below the icon. Re-flow as a horizontal row: icon on the
     left, name + slot-label up top, level + tier badges below. The
     watermark dims into a backdrop. Tap target stays the whole tile.
     ────────────────────────────────────────────────────────────── */
  @media (max-width: 640px) {
    .eq-slot-tile {
      flex-direction: row;
      align-items: center;
      gap: 14px;
      min-height: 0;
      padding: 14px 18px;
    }
    /* No asymmetric clip on mobile rows — keeps long lines clean. */
    [data-slot="shield"]    .eq-slot-tile,
    [data-slot="gun"]       .eq-slot-tile,
    [data-slot="secondary"] .eq-slot-tile,
    [data-slot="drone"]     .eq-slot-tile { clip-path: none; }
    .eq-slot-tile-watermark {
      width: 92px;
      height: 92px;
      top: auto;
      right: -14px;
      bottom: -22px;
      opacity: 0.10;
    }
    .eq-slot-tile-icon {
      flex: 0 0 56px;
      width: 56px;
      height: 56px;
    }
    .eq-slot-tile-icon-thumb {
      flex: 0 0 56px;
      width: 56px;
      height: 56px;
    }
    .eq-slot-tile-name {
      flex: 1 1 auto;
      font-size: 16px;
      margin: 0;
      line-height: 1.15;
    }
    /* Slot label moves above the name as a small caps eyebrow */
    .eq-slot-tile-slot {
      position: static;
      align-self: flex-start;
      margin: 0 0 2px 0;
      font-size: 8.5px;
      padding: 2px 7px;
    }
    /* Right-side meta cluster: Lv + tier badges stack inline */
    .eq-slot-tile-meta {
      flex: 0 0 auto;
      display: inline-flex;
      flex-direction: column;
      align-items: flex-end;
      gap: 4px;
      margin: 0;
    }
    .eq-slot-tile-lv { font-size: 9px; padding: 2px 7px; }
    .eq-slot-tile-tier { font-size: 9px; padding: 2px 6px; }
    /* The name + slot label live in a flex column between the icon and
       the meta cluster so they share vertical centering with the icon.
       We add a wrapper via flex layout: icon (left) — body (flex column,
       center) — meta (right). Body needs to wrap the slot label + name. */
    .eq-slot-tile-body {
      flex: 1 1 auto;
      display: flex;
      flex-direction: column;
      gap: 2px;
      min-width: 0;
    }
    /* Hide the holographic shine sweep on mobile rows — at this width
       and at row aspect the sweep reads as a flicker, not a sheen. */
    .eq-slot-tile::after { display: none; }
  }

  /* ── SLOT PICKER MODAL ──────────────────────────────────────────
     Bottom sheet on mobile, centered on desktop. Lists the 5 items in
     the tapped slot. Each row has EQUIP/UPGRADE/EVOLVE inline. */
  .eq-slot-picker-modal {
    position: fixed;
    inset: 0;
    z-index: 280;
    display: none;
    pointer-events: none;
  }
  .eq-slot-picker-modal.is-open { display: block; pointer-events: auto; }
  .eq-slot-picker-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(6, 10, 22, 0.72);
    opacity: 0;
    transition: opacity .2s ease;
  }
  .eq-slot-picker-modal.is-open .eq-slot-picker-backdrop { opacity: 1; }

  .eq-slot-picker-panel {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%) scale(0.94);
    width: min(560px, 94vw);
    max-height: 86vh;
    display: flex;
    flex-direction: column;
    /* rc158 — opaque panel (was translucent dark-on-dark which let
       the gameplay scene bleed through and washed the slot accent). */
    background: var(--panel-bg, #131a2e);
    border: 2px solid var(--slot, #4cc8ff);
    border-radius: 22px;
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--slot, #4cc8ff) 30%, transparent),
      0 30px 70px -20px rgba(0, 0, 0, 0.7),
      0 14px 32px -8px color-mix(in srgb, var(--slot, #4cc8ff) 30%, transparent);
    opacity: 0;
    transition: transform .22s cubic-bezier(0.2, 0.9, 0.3, 1.1), opacity .18s ease;
    overflow: hidden;
  }
  .eq-slot-picker-modal.is-open .eq-slot-picker-panel {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
  }
  @media (max-width: 640px) {
    .eq-slot-picker-panel {
      left: 0;
      right: 0;
      top: auto;
      bottom: 0;
      width: 100%;
      max-width: none;
      max-height: 88vh;
      transform: translateY(100%);
      border-radius: 22px 22px 0 0;
      border-bottom: none;
    }
    .eq-slot-picker-modal.is-open .eq-slot-picker-panel { transform: translateY(0); }
  }

  /* Picker head — slot icon, name, shards + stones counters, close button */
  .eq-slot-picker-head {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 18px 14px;
    border-bottom: 1px dashed color-mix(in srgb, var(--slot) 28%, transparent);
    position: relative;
  }
  @media (max-width: 640px) {
    .eq-slot-picker-head::before {
      content: "";
      position: absolute;
      top: 6px;
      left: 50%;
      transform: translateX(-50%);
      width: 36px; height: 4px;
      border-radius: 2px;
      background: rgba(255,255,255,.18);
    }
    .eq-slot-picker-head { padding-top: 20px; }
  }
  /* Slot icon — demoted to a small inline glyph. The title ("DRONE",
     "SHIELD", etc.) right next to it already names the slot, so the
     icon doesn't need to be hero-sized. Flattened: no heavy border, no
     drop-shadow halo, just a tinted square that lets the new 140px
     equipment previews own the page's visual weight. */
  .eq-slot-picker-icon {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    color: var(--slot);
    background: color-mix(in srgb, var(--slot) 16%, rgba(20, 26, 48, 0.4));
    border: 1px solid color-mix(in srgb, var(--slot) 32%, transparent);
    border-radius: 10px;
    padding: 7px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .eq-slot-picker-icon svg { width: 100%; height: 100%; display: block; }
  .eq-slot-picker-title { flex: 1 1 auto; min-width: 0; }
  .eq-slot-picker-name {
    margin: 0 0 4px 0;
    /* Slot title — kept bold/uppercase but slightly smaller so it
       doesn't compete with the hero equipment previews below. */
    font-size: 18px;
    font-weight: 900;
    letter-spacing: 1.4px;
    color: #fff;
    text-transform: uppercase;
  }
  .eq-slot-picker-resources {
    display: flex;
    gap: 14px;
    align-items: center;
    flex-wrap: wrap;
  }
  .eq-slot-picker-resource {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    color: rgba(220, 230, 255, 0.85);
  }
  .eq-slot-picker-resource-icon {
    color: var(--slot);
    font-size: 13px;
    display: inline-flex;
    align-items: center;
    line-height: 0;
  }
  /* Inline shard SVG glyph from src/shard-icons.js. Sized to match the
     surrounding 13px font, color inherited from the slot-tinted parent. */
  .eq-shard-icon svg {
    width: 1.15em; height: 1.15em;
    fill: currentColor;
    display: block;
  }
  .eq-cost-icon.eq-shard-icon {
    display: inline-block; vertical-align: middle;
  }
  .eq-cost-icon.eq-shard-icon svg {
    width: 1em; height: 1em;
    display: inline-block; vertical-align: -0.15em;
  }
  .eq-slot-picker-resource-count {
    font-weight: 800;
    color: #fff;
  }
  .eq-slot-picker-resource-label {
    color: rgba(220, 230, 255, 0.55);
    text-transform: uppercase;
    font-size: 9px;
    letter-spacing: 1.1px;
    font-weight: 700;
  }
  .eq-slot-picker-close {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: #2a3454;
    border: 1px solid #4a5478;
    color: #fff;
    font-size: 22px;
    font-weight: 300;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .15s ease, transform .1s ease;
    flex-shrink: 0;
  }
  .eq-slot-picker-close:hover { background: #3a4470; }
  .eq-slot-picker-close:active { transform: scale(0.92); }

  /* Picker body — scrollable list of item rows */
  .eq-slot-picker-body {
    overflow-y: auto;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1 1 auto;
    min-height: 0;
  }

  /* ── ITEM ROW (5 of these inside the picker body) ─────────────── */
  .eq-pick-row {
    display: grid;
    /* Hero thumb + body. The dedicated right-hand actions column is gone
       — actions are now small inline pills inside the body. That gives
       the painted drone/SVG preview far more visual budget (140px square,
       up from 72px) so it reads as the subject, not a glyph. */
    grid-template-columns: 140px 1fr;
    gap: 14px;
    padding: 14px;
    border-radius: 16px;
    background: linear-gradient(160deg,
      color-mix(in srgb, var(--slot) 10%, rgba(20, 26, 48, 0.6)) 0%,
      rgba(20, 26, 48, 0.6) 100%);
    border: 1.5px solid color-mix(in srgb, var(--slot) 22%, transparent);
    position: relative;
    transition: border-color .15s ease, box-shadow .18s ease;
  }
  .eq-pick-row.is-equipped {
    border-color: var(--slot);
    background: linear-gradient(135deg,
      color-mix(in srgb, var(--slot) 22%, rgba(20, 26, 48, 0.8)) 0%,
      rgba(20, 26, 48, 0.85) 70%);
    box-shadow:
      0 0 0 1px var(--slot) inset,
      0 10px 26px -10px color-mix(in srgb, var(--slot) 40%, transparent);
  }
  .eq-pick-row.is-equipped::before {
    content: "★";
    position: absolute;
    top: -6px;
    left: 12px;
    background: var(--slot);
    color: #0a0e1c;
    font-size: 12px;
    font-weight: 900;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    /* rc154: dropped the slot-tinted box-shadow (was
       `0 4px 12px -2px color-mix(--slot 50% transparent)`). The badge
       is positioned at `top: -6px`, poking above the row edge, so its
       12px slot-coloured glow leaked into the row gap above the
       equipped card — exactly the orange spots the player flagged on
       gun-slot picker rows. The solid `--slot`-filled disc still
       carries the equipped tell without bleeding outside the row. */
  }
  .eq-pick-row.is-locked { opacity: 0.65; }

  .eq-pick-icon {
    width: 56px;
    height: 56px;
    color: var(--slot);
    background: color-mix(in srgb, var(--slot) 15%, rgba(20, 26, 48, 0.5));
    border: 1.5px solid color-mix(in srgb, var(--slot) 35%, transparent);
    border-radius: 12px;
    padding: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    filter: drop-shadow(0 0 10px color-mix(in srgb, var(--slot) 30%, transparent));
  }
  .eq-pick-icon svg { width: 100%; height: 100%; display: block; }

  /* ── Picker preview pane (v3, rc81+) ───────────────────────────────
     Replaces the static .eq-pick-icon with an ANIMATED visualization of
     what the item does. Drones use a live Three.js canvas (the actual
     GLB rotating + hovering); shield/gun/secondary use inline animated
     SVGs themed in the slot color. The pane sits at the left edge of
     each row, same footprint as the old icon. */
  .eq-pick-preview {
    position: relative;
    /* Hero-sized preview pane. The Three.js drone renderer auto-sizes
       its WebGL canvas off getBoundingClientRect() (see
       _spinUpDronePreview), so bumping this CSS size is enough — no JS
       changes needed for the drone to render bigger. Shield / gun /
       secondary SVG previews scale via their viewBox. */
    width: 140px;
    height: 140px;
    flex-shrink: 0;
    border-radius: 16px;
    background:
      radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--slot) 22%, transparent) 0%, transparent 65%),
      color-mix(in srgb, var(--slot) 10%, rgba(16, 22, 40, 0.75));
    border: 1.5px solid color-mix(in srgb, var(--slot) 38%, transparent);
    box-shadow:
      0 6px 20px -8px color-mix(in srgb, var(--slot) 40%, transparent),
      0 0 0 1px rgba(255,255,255,0.04) inset;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  /* All four GLB-backed slots drop the colored backdrop + frame so the
     live GLB sits cleanly on the row's own parchment (rc108 polish; gun
     extended in rc118; secondary + shield joined once they moved from
     animated SVGs to real GLBs — they no longer need the tinted backdrop
     for contrast, and it read as an inconsistent dark box vs gun/drone). */
  .eq-pick-row[data-slot="drone"] .eq-pick-preview,
  .eq-pick-row[data-slot="gun"] .eq-pick-preview,
  .eq-pick-row[data-slot="secondary"] .eq-pick-preview,
  .eq-pick-row[data-slot="shield"] .eq-pick-preview,
  .eq-pick-row[data-slot="superweapon"] .eq-pick-preview {
    background: none;
    border: none;
    box-shadow: none;
  }
  .eq-pick-canvas {
    display: block;
    width: 100%;
    height: 100%;
  }
  /* Fallback drone-icon SVG used to peek through behind the live GLB at
     35% opacity (intended as a graceful degradation if WebGL fails).
     In practice the GLB always loads and the fallback just adds visual
     noise — hide it entirely (rc108 polish). */
  .eq-pick-canvas-fallback {
    display: none;
  }
  .eq-pick-svg {
    width: 100%;
    height: 100%;
    display: block;
  }

  /* SHIELD — concentric rings rotating at different rates, central core
     pulses on opacity. */
  .eq-pick-svg-shield .eq-svg-core {
    fill: var(--slot);
    transform-origin: 40px 40px;
    animation: eq-svg-pulse 1.8s ease-in-out infinite alternate;
  }
  .eq-pick-svg-shield .eq-svg-ring {
    fill: none;
    stroke: var(--slot);
    stroke-width: 2.5;
    transform-origin: 40px 40px;
    filter: drop-shadow(0 0 4px color-mix(in srgb, var(--slot) 70%, transparent));
  }
  .eq-pick-svg-shield .eq-svg-ring-1 { animation: eq-svg-spin-cw  3.8s linear infinite; opacity: 0.95; }
  .eq-pick-svg-shield .eq-svg-ring-2 { animation: eq-svg-spin-ccw 5.4s linear infinite; opacity: 0.75; }
  .eq-pick-svg-shield .eq-svg-ring-3 { animation: eq-svg-spin-cw  7.0s linear infinite; opacity: 0.55; }
  @keyframes eq-svg-spin-cw  { to { transform: rotate(360deg); } }
  @keyframes eq-svg-spin-ccw { to { transform: rotate(-360deg); } }
  @keyframes eq-svg-pulse {
    0%   { transform: scale(0.85); opacity: 0.7; }
    100% { transform: scale(1.0);  opacity: 1.0; }
  }

  /* GUN — five parallel bullet trails with stroke-dashoffset flowing
     left-to-right at staggered offsets, plus a muzzle flash at the
     right edge. */
  .eq-pick-svg-gun .eq-svg-trail {
    stroke: var(--slot);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-dasharray: 8 14;
    animation: eq-svg-bullet 0.8s linear infinite;
    filter: drop-shadow(0 0 3px color-mix(in srgb, var(--slot) 80%, transparent));
  }
  .eq-pick-svg-gun .eq-svg-trail-1 { animation-duration: 0.9s; animation-delay: 0.00s; opacity: 0.55; }
  .eq-pick-svg-gun .eq-svg-trail-2 { animation-duration: 0.7s; animation-delay: 0.10s; opacity: 0.85; }
  .eq-pick-svg-gun .eq-svg-trail-3 { animation-duration: 0.6s; animation-delay: 0.00s; opacity: 1.00; stroke-width: 2.5; }
  .eq-pick-svg-gun .eq-svg-trail-4 { animation-duration: 0.7s; animation-delay: 0.15s; opacity: 0.85; }
  .eq-pick-svg-gun .eq-svg-trail-5 { animation-duration: 0.9s; animation-delay: 0.05s; opacity: 0.55; }
  .eq-pick-svg-gun .eq-svg-muzzle {
    fill: var(--slot);
    filter: drop-shadow(0 0 6px var(--slot));
    transform-origin: 78px 40px;
    animation: eq-svg-muzzle 0.18s ease-out infinite alternate;
  }
  @keyframes eq-svg-bullet {
    from { stroke-dashoffset: 22; }
    to   { stroke-dashoffset: 0; }
  }
  @keyframes eq-svg-muzzle {
    0%   { transform: scale(1.0); opacity: 0.5; }
    100% { transform: scale(1.4); opacity: 1.0; }
  }

  /* SECONDARY — three concentric burst rings + four shrapnel pieces.
     Inner ring fastest, outer slowest. Shrapnel flies outward. */
  .eq-pick-svg-secondary .eq-svg-burst {
    fill: none;
    stroke: var(--slot);
    stroke-width: 2;
    transform-origin: 40px 40px;
    filter: drop-shadow(0 0 5px color-mix(in srgb, var(--slot) 70%, transparent));
  }
  .eq-pick-svg-secondary .eq-svg-burst-1 { animation: eq-svg-burst 1.4s ease-out infinite; }
  .eq-pick-svg-secondary .eq-svg-burst-2 { animation: eq-svg-burst 1.4s ease-out 0.20s infinite; }
  .eq-pick-svg-secondary .eq-svg-burst-3 { animation: eq-svg-burst 1.4s ease-out 0.40s infinite; }
  .eq-pick-svg-secondary .eq-svg-shrapnel circle {
    fill: var(--slot);
    transform-origin: 40px 40px;
    animation: eq-svg-shrapnel 1.4s ease-out infinite;
  }
  .eq-pick-svg-secondary .eq-svg-shrapnel circle:nth-child(2) { animation-delay: 0.05s; }
  .eq-pick-svg-secondary .eq-svg-shrapnel circle:nth-child(3) { animation-delay: 0.10s; }
  .eq-pick-svg-secondary .eq-svg-shrapnel circle:nth-child(4) { animation-delay: 0.15s; }
  @keyframes eq-svg-burst {
    0%   { transform: scale(0.4); opacity: 0.0; }
    40%  { opacity: 1.0; }
    100% { transform: scale(1.2); opacity: 0.0; }
  }
  @keyframes eq-svg-shrapnel {
    0%   { transform: scale(0.0); opacity: 0.0; }
    30%  { opacity: 1.0; }
    100% { transform: scale(1.5); opacity: 0.0; }
  }

  /* Locked row → desaturate the preview so the cartoon mascot/aura
     feels muted rather than as alive as the unlocked ones. */
  .eq-pick-row.is-locked .eq-pick-preview {
    filter: grayscale(0.6) brightness(0.7);
  }

  /* Equipped row → rotating slot-tinted sunburst halo, no pink frame.
     Same treatment as the IAP success modal's .iap-success-rays — a
     conic-gradient ring of soft alternating stripes that slowly rotates
     behind the item. Color follows --slot so each weapon class has its
     own halo tint. The row-level is-equipped border + ★ badge still
     carry the primary equipped signal. */
  .eq-pick-row.is-equipped .eq-pick-preview {
    box-shadow: none;
    /* rc153: keep the base `overflow: hidden` so the rotating sunburst
       halo (the ::before below) is clipped to the preview thumb. The
       prior `overflow: visible` let the 200%-sized halo bleed outside
       the 140px preview and into the row gap, which read as "the
       glow is behind the card" — instead we want it strictly behind
       the weapon GLB inside the preview. */
  }
  .eq-pick-row.is-equipped .eq-pick-preview::before {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 200%; height: 200%;
    transform: translate(-50%, -50%);
    background: conic-gradient(
      from 0deg,
      transparent 0deg,   color-mix(in srgb, var(--slot) 30%, transparent) 8deg,  transparent 16deg,
      transparent 36deg,  color-mix(in srgb, var(--slot) 24%, transparent) 44deg, transparent 52deg,
      transparent 72deg,  color-mix(in srgb, var(--slot) 32%, transparent) 80deg, transparent 88deg,
      transparent 108deg, color-mix(in srgb, var(--slot) 22%, transparent) 116deg, transparent 124deg,
      transparent 144deg, color-mix(in srgb, var(--slot) 28%, transparent) 152deg, transparent 160deg,
      transparent 180deg, color-mix(in srgb, var(--slot) 24%, transparent) 188deg, transparent 196deg,
      transparent 216deg, color-mix(in srgb, var(--slot) 30%, transparent) 224deg, transparent 232deg,
      transparent 252deg, color-mix(in srgb, var(--slot) 22%, transparent) 260deg, transparent 268deg,
      transparent 288deg, color-mix(in srgb, var(--slot) 28%, transparent) 296deg, transparent 304deg,
      transparent 324deg, color-mix(in srgb, var(--slot) 24%, transparent) 332deg, transparent 340deg,
      transparent 360deg
    );
    mask: radial-gradient(circle at center, transparent 22%, #000 36%, #000 52%, transparent 78%);
    -webkit-mask: radial-gradient(circle at center, transparent 22%, #000 36%, #000 52%, transparent 78%);
    pointer-events: none;
    z-index: -1;
    will-change: transform;
    animation:
      eq-pick-spotlight-in 900ms ease-out both,
      eq-pick-spotlight-spin 14s linear infinite;
  }
  @keyframes eq-pick-spotlight-in {
    0%   { opacity: 0; }
    100% { opacity: 1; }
  }
  @keyframes eq-pick-spotlight-spin {
    to { transform: translate(-50%, -50%) rotate(360deg); }
  }
  @media (prefers-reduced-motion: reduce) {
    .eq-pick-row.is-equipped .eq-pick-preview::before {
      animation: eq-pick-spotlight-in 900ms ease-out both;
      opacity: 0.7;
    }
  }

  /* prefers-reduced-motion — freeze all SVG animations */
  @media (prefers-reduced-motion: reduce) {
    .eq-pick-svg-shield *,
    .eq-pick-svg-gun *,
    .eq-pick-svg-secondary * {
      animation: none !important;
    }
  }

  .eq-pick-body { min-width: 0; }
  .eq-pick-name {
    margin: 0 0 4px;
    font-size: 16px;
    font-weight: 800;
    color: #fff;
    letter-spacing: 0.2px;
    line-height: 1.2;
  }
  .eq-pick-dupe-badge {
    color: #ffd700;
    font-size: 0.85em;
    margin-left: 6px;
    font-weight: 700;
  }
  .eq-pick-meta {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 6px;
  }
  .eq-pick-lv {
    font-size: 11px;
    font-weight: 700;
    color: var(--slot);
    letter-spacing: 0.3px;
  }
  .eq-pick-tier {
    font-size: 10px;
    font-weight: 900;
    letter-spacing: 0.8px;
    color: #0a0e1c;
    background: color-mix(in srgb, var(--slot) 90%, white 10%);
    padding: 2px 8px;
    border-radius: 5px;
    white-space: nowrap;
  }
  .eq-pick-lv-cap {
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.6px;
    color: #ffc23d;
    margin-left: 4px;
  }

  /* rc158 — evolution rarity tiers, opaque rebuild. Each tier owns a
     pair: `--rarity` is the bright accent colour (used by the left-
     edge bar, tier pill, and bright glow), `--tier-bg` is the
     muted opaque card surface.
     rc149 (rc164 follow-up): collapsed all six `--tier-bg` values to
     a single neutral navy. The previous per-tier hues (warm amber for
     T5, deep red for T6, etc.) overlapped with weapon GLB colours —
     gold boomerang on amber bg, red laser on red bg, orange shotgun
     on warm bg — so the card surface fought the silhouette. The
     `--rarity` accent (left edge bar, border, tier pill) still varies
     per tier and carries the rarity tell on its own. */
  .eq-tier-1 { --rarity: #c4cdda; --tier-bg: #1a1e2c; }
  .eq-tier-2 { --rarity: #5ec46a; --tier-bg: #1a1e2c; }
  .eq-tier-3 { --rarity: #4fa6ff; --tier-bg: #1a1e2c; }
  .eq-tier-4 { --rarity: #b674ff; --tier-bg: #1a1e2c; }
  .eq-tier-5 { --rarity: #ffc23d; --tier-bg: #1a1e2c; }
  .eq-tier-6 { --rarity: #ff5660; --tier-bg: #1a1e2c; }
  .eq-pick-row[class*="eq-tier-"],
  .eq-slot-card[class*="eq-tier-"] {
    position: relative;
  }
  /* Jelly Candy Gem rarity wells (owner pick T, 2026-06-07 — replaced the
     corner gem). The picker row's ICON WELL becomes a glossy candy-gem
     surface in the tier's stone color (Moonstone → Emerald → Sapphire →
     Amethyst → Imperial Topaz → Ruby), matching the inventory tiles
     (css/inventory.css). Applied to the well rather than the whole row so
     name/stat text keeps its contrast. Slot cards keep their top-edge gem
     (storybook skin, file head). */
  /* NOTE: the storybook picker-panel skin (later in this file) restyles
     `.eq-slot-picker-panel .eq-pick-preview` at equal specificity — the
     panel-scoped variants below outrank it (0,3,0) so the candy wells win
     inside the actual picker. */
  .eq-pick-row[class*="eq-tier-"] .eq-pick-preview,
  .eq-slot-picker-panel .eq-pick-row[class*="eq-tier-"] .eq-pick-preview {
    border: 2.5px solid rgba(255, 255, 255, 0.78);
    border-radius: 14px;
    position: relative;
    overflow: hidden;
    box-shadow:
      0 3px 8px rgba(20, 10, 4, 0.4),
      inset 0 -6px 12px rgba(0, 0, 0, 0.18),
      inset 0 4px 8px rgba(255, 255, 255, 0.25);
  }
  .eq-tier-1 .eq-pick-preview, .eq-slot-picker-panel .eq-tier-1 .eq-pick-preview { background: radial-gradient(90% 90% at 50% 38%, #c9cedd 0%, #8a91ad 52%, #545d7e 100%); }
  .eq-tier-2 .eq-pick-preview, .eq-slot-picker-panel .eq-tier-2 .eq-pick-preview { background: radial-gradient(90% 90% at 50% 38%, #8af0b4 0%, #3ecc7c 55%, #1a9a54 100%); }
  .eq-tier-3 .eq-pick-preview, .eq-slot-picker-panel .eq-tier-3 .eq-pick-preview { background: radial-gradient(90% 90% at 50% 38%, #7fc3ff 0%, #3e8ef0 55%, #1f5cc0 100%); }
  .eq-tier-4 .eq-pick-preview, .eq-slot-picker-panel .eq-tier-4 .eq-pick-preview { background: radial-gradient(90% 90% at 50% 38%, #d9a6ff 0%, #a861ec 55%, #7430bc 100%); }
  .eq-tier-5 .eq-pick-preview, .eq-slot-picker-panel .eq-tier-5 .eq-pick-preview { background: radial-gradient(90% 90% at 50% 38%, #ffd980 0%, #ffab2e 55%, #e07c0e 100%); }
  .eq-tier-6 .eq-pick-preview, .eq-slot-picker-panel .eq-tier-6 .eq-pick-preview { background: radial-gradient(90% 90% at 50% 38%, #ff92a8 0%, #f24a6a 55%, #c01d3e 100%); }
  /* Candy gloss highlight on the well. */
  .eq-pick-row[class*="eq-tier-"] .eq-pick-preview::before {
    content: '';
    position: absolute;
    left: 10%; right: 40%; top: 6%; height: 30%;
    border-radius: 50%;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.10) 80%, transparent);
    transform: rotate(-8deg);
    pointer-events: none;
    z-index: 2;
  }
  /* Epic/Mythic wells get the slow light-sweep (reduced-motion aware). */
  .eq-tier-5 .eq-pick-preview::after,
  .eq-tier-6 .eq-pick-preview::after {
    content: '';
    position: absolute; inset: 0;
    background: linear-gradient(112deg, transparent 40%, rgba(255, 255, 255, 0.28) 50%, transparent 60%);
    background-size: 240% 100%;
    animation: eq-gem-sheen 4.2s ease-in-out infinite;
    pointer-events: none;
    z-index: 2;
  }
  @keyframes eq-gem-sheen {
    0% { background-position: 150% 0; }
    55% { background-position: -70% 0; }
    100% { background-position: -70% 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    .eq-tier-5 .eq-pick-preview::after,
    .eq-tier-6 .eq-pick-preview::after { animation: none; background: none; }
  }
  .eq-pick-row[class*="eq-tier-"],
  .eq-slot-card[class*="eq-tier-"] {
    background: var(--tier-bg);
    border: 1.5px solid var(--rarity);
    box-shadow: 0 6px 18px -6px color-mix(in srgb, var(--rarity) 35%, transparent);
  }
  .eq-pick-tier-0, .eq-tier-1 .eq-pick-tier { background: #c4cdda; color: #0a0e1c; }
  .eq-pick-tier-1, .eq-tier-2 .eq-pick-tier { background: #5ec46a; color: #0a1f10; }
  .eq-pick-tier-2, .eq-tier-3 .eq-pick-tier { background: #4fa6ff; color: #061226; }
  .eq-pick-tier-3, .eq-tier-4 .eq-pick-tier { background: #b674ff; color: #160a26; }
  .eq-pick-tier-4, .eq-tier-5 .eq-pick-tier { background: #ffc23d; color: #2a1e00; }
  .eq-pick-tier-5, .eq-tier-6 .eq-pick-tier { background: #ff5660; color: #2a0410; }
  .eq-pick-desc {
    margin: 0 0 8px;
    font-size: 12px;
    line-height: 1.4;
    color: rgba(225, 235, 255, 0.82);
    font-style: italic;
  }
  .eq-pick-desc.is-locked-hint {
    color: rgba(220, 230, 255, 0.5);
  }
  .eq-pick-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 4px 12px;
    margin: 0;
  }
  .eq-pick-stat-key {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 1px;
    color: rgba(200, 215, 245, 0.55);
    text-transform: uppercase;
  }
  .eq-pick-stat-val {
    font-size: 16px;
    font-weight: 900;
    color: var(--slot);
    margin: 0;
    line-height: 1.1;
    text-shadow: 0 0 14px color-mix(in srgb, var(--slot) 30%, transparent);
  }

  /* Actions row — small inline pills, bottom of the body. The vertical
     column to the right of each card is gone (rc95 redesign); the
     remaining buttons are sized to look like quick affordances, not
     screen-dominating CTAs. */
  .eq-pick-actions {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 10px;
    align-items: stretch;
  }
  .eq-pick-action {
    padding: 7px 12px;
    border-radius: 8px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.8px;
    cursor: pointer;
    text-align: center;
    transition: transform .1s ease, background .15s ease, box-shadow .15s ease;
    border: none;
    line-height: 1.1;
    display: inline-flex;
    flex-direction: row;
    gap: 6px;
    align-items: center;
    justify-content: center;
    flex: 0 1 auto;
    min-height: 28px;
  }
  .eq-pick-action.is-equip {
    background: linear-gradient(135deg, var(--slot), color-mix(in srgb, var(--slot) 60%, #fff));
    color: #0a0e1c;
    box-shadow: 0 4px 14px -4px color-mix(in srgb, var(--slot) 50%, transparent);
    /* rc156 — force a heavier weight + tighter tracking so the dark-on-
       slot-colour label survives even when the card's rarity gradient
       bleeds warm hues underneath. Without this the text reads as
       "watermark" on gold / red / purple tiers. */
    font-weight: 900;
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.35);
  }
  /* Equipped state — invert to high-contrast white-on-dark so the
     "EQUIPPED" label stays legible regardless of slot accent. The
     previous slot-tinted background blended into gold/red/purple
     rarity gradients on the underlying card. */
  /* rc158 — opaque equipped / locked / upgrade pills. The is-locked
     and is-upgrade variants previously used rgba(white) at 4-7%
     which was barely a "lighter than the card" lift; flat colours
     give cleaner, more confident contrast. */
  .eq-pick-action.is-equipped,
  .eq-pick-action.is-equipped-state {
    background: #0c1322;
    color: #fff;
    border: 1.5px solid var(--slot);
    box-shadow: 0 0 0 1px var(--slot) inset;
    cursor: default;
    font-weight: 900;
    letter-spacing: 1px;
  }
  .eq-pick-action.is-equipped::before,
  .eq-pick-action.is-equipped-state::before {
    content: '✓';
    margin-right: 4px;
    color: var(--slot);
  }
  .eq-pick-action.is-locked {
    background: #1c2236;
    color: #7c87a3;
    border: 1px solid #2e3854;
    cursor: not-allowed;
  }
  .eq-pick-action.is-upgrade {
    background: #2a3454;
    color: #fff;
    border: 1.5px solid var(--slot);
  }
  .eq-pick-action.is-upgrade:hover:not(:disabled) {
    background: color-mix(in srgb, var(--slot) 35%, #2a3454);
    border-color: var(--slot);
  }
  .eq-pick-action.is-evolve {
    background: linear-gradient(135deg, #ffd000, #ff8a3a);
    color: #0a0e1c;
    border: none;
    box-shadow: 0 4px 14px -4px rgba(255, 200, 60, 0.55);
  }
  /* rc153 — BUY pill for superweapon unlocks. Reads relic-shop "buy"
     vibes (purple/violet) so it's visually distinct from the
     shard-driven UPGRADE / EVOLVE pills sharing the row. */
  .eq-pick-action.is-buy {
    background: linear-gradient(135deg, #b674ff, #6b3ed8);
    color: #fff;
    border: none;
    box-shadow: 0 4px 14px -4px rgba(168, 110, 255, 0.55);
  }
  .eq-pick-action.is-buy:hover:not(:disabled) {
    filter: brightness(1.1);
  }

  /* ════════════════════════════════════════════════════════════════════
     PARCHMENT THEME (Figma 3327-2) — overrides the dark navy picker above
     so the popup matches the warm storybook GEAR/SHOP tabs + the mock:
     a parchment page in a wood frame, a scroll-banner title naming the
     slot TYPE, and item cards with a dark glowing icon well + bronze EQUIP
     / navy EMPOWER buttons. Appended last so equal-specificity rules win
     on source order; tier-bg overrides use a panel-scoped ancestor to beat
     `.eq-pick-row[class*="eq-tier-"]`. The GLB/SVG previews, item names and
     descriptions are untouched. */
  .eq-slot-picker-backdrop {
    background: rgba(24, 14, 4, 0.62);
    backdrop-filter: blur(2px);
  }
  .eq-slot-picker-panel {
    width: min(540px, 94vw);
    background:
      radial-gradient(120% 80% at 50% 0%, #f3e7c8 0%, #e7d3a6 55%, #ddc794 100%);
    border: 7px solid #6e4a26;
    border-radius: 20px;
    box-shadow:
      0 0 0 2px #a9803c,
      0 0 0 4px #6e4a26,
      inset 0 0 0 2px rgba(255, 246, 222, 0.5),
      inset 0 0 38px rgba(120, 78, 30, 0.28),
      0 30px 70px -18px rgba(20, 10, 0, 0.7);
  }
  /* Scroll-banner header: centred title naming the slot type, on a parchment
     ribbon with darker rolled ends; close button floats top-right; the shard
     balance sits as a small warm chip so the banner stays clean like the mock. */
  .eq-slot-picker-head {
    display: block;
    text-align: center;
    border-bottom: none;
    padding: 18px 16px 6px;
  }
  .eq-slot-picker-head::after {
    content: "";
    display: block;
    width: min(82%, 380px);
    height: 2px;
    margin: 10px auto 0;
    background: linear-gradient(90deg, transparent, rgba(110, 74, 30, 0.55), transparent);
  }
  .eq-slot-picker-icon { display: none; }
  .eq-slot-picker-title {
    display: inline-block;
    position: relative;
    background: linear-gradient(180deg, #efdcae 0%, #e2c98f 100%);
    border: 2px solid #a9803c;
    border-radius: 9px;
    box-shadow:
      inset 0 0 0 1px rgba(255, 248, 228, 0.55),
      inset 0 0 16px rgba(150, 100, 40, 0.25),
      0 3px 8px rgba(40, 22, 8, 0.4);
    padding: 7px 30px;
    margin: 0 auto;
    max-width: 88%;
  }
  /* Rolled scroll ends flanking the banner. */
  .eq-slot-picker-title::before,
  .eq-slot-picker-title::after {
    content: "";
    position: absolute;
    top: 50%;
    width: 14px; height: 128%;
    transform: translateY(-50%);
    background: linear-gradient(180deg, #c9a063 0%, #8a5e2c 100%);
    border: 2px solid #6e4a26;
    border-radius: 4px;
  }
  .eq-slot-picker-title::before { left: -10px; }
  .eq-slot-picker-title::after  { right: -10px; }
  .eq-slot-picker-name {
    margin: 0;
    font-family: 'EB Garamond', 'Cinzel', serif;
    font-size: 22px;
    font-weight: 800;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: #3a2613;
    text-shadow: 0 1px 0 rgba(255, 248, 228, 0.55);
  }
  /* Mock keeps the header a clean title banner — the player's shard/stone
     balance isn't shown here (it's on the gear slot card behind the modal,
     and the EMPOWER button dims when unaffordable). */
  .eq-slot-picker-resources { display: none; }
  .eq-slot-picker-close {
    position: absolute;
    top: 12px; right: 14px;
    background: linear-gradient(180deg, #ecdcb6 0%, #d8c191 100%);
    border: 2px solid #8a6a3a;
    color: #4a3320;
    box-shadow: inset 0 1px 0 rgba(255, 250, 235, 0.5), 0 2px 5px rgba(40, 22, 8, 0.4);
  }
  .eq-slot-picker-close:hover { background: linear-gradient(180deg, #f3e6c5 0%, #e0caa0 100%); }
  .eq-slot-picker-body { padding: 8px 16px 16px; gap: 12px; }

  /* Item card → parchment plaque. Panel-scoped so it beats the dark
     `.eq-pick-row[class*="eq-tier-"]` tier-bg + rarity border above. */
  .eq-slot-picker-panel .eq-pick-row,
  .eq-slot-picker-panel .eq-pick-row[class*="eq-tier-"] {
    background: linear-gradient(165deg, #f1e6c8 0%, #e6d3a6 100%);
    border: 2px solid #b68a52;
    border-radius: 14px;
    box-shadow:
      inset 0 0 0 1px rgba(255, 248, 228, 0.5),
      inset 0 0 22px rgba(150, 100, 40, 0.18),
      0 4px 12px -3px rgba(40, 22, 8, 0.4);
    gap: 16px;
    align-items: center;
  }
  /* ::after is now the corner rarity GEM (2026-06-07) — the storybook
     picker SHOWS it (this rule used to display:none the old vertical
     rarity bar). No clipping needed; the gem sits fully inside the row. */
  .eq-slot-picker-panel .eq-pick-row.is-equipped {
    border-color: #c9a24a;
    box-shadow:
      inset 0 0 0 2px rgba(255, 220, 130, 0.6),
      inset 0 0 24px rgba(180, 130, 50, 0.25),
      0 4px 14px -3px rgba(120, 80, 20, 0.5);
  }
  /* Icon well — dark rounded square with a warm inner glow (mock). The GLB
     canvas / SVG preview inside is unchanged. */
  .eq-slot-picker-panel .eq-pick-preview {
    background: radial-gradient(circle at 50% 42%, #2a2236 0%, #15101e 78%);
    border: 2px solid #8a6a3a;
    border-radius: 12px;
    box-shadow: inset 0 0 22px rgba(0, 0, 0, 0.55), inset 0 0 0 1px rgba(201, 162, 74, 0.3);
  }
  /* Text → warm serif, like the mock. */
  .eq-slot-picker-panel .eq-pick-name {
    font-family: 'EB Garamond', 'Cinzel', serif;
    font-size: 19px;
    font-weight: 800;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #3a2613;
    text-shadow: 0 1px 0 rgba(255, 248, 228, 0.4);
  }
  .eq-slot-picker-panel .eq-pick-lv { color: #6a5034; }
  .eq-slot-picker-panel .eq-pick-desc {
    color: #5e4a32;
    font-style: normal;
    margin-bottom: 6px;
  }
  .eq-slot-picker-panel .eq-pick-stat-key { color: #7a6244; }
  .eq-slot-picker-panel .eq-pick-stat-val {
    color: #6a3a12;
    text-shadow: none;
    font-size: 15px;
  }
  /* EQUIP — bronze plaque button (mock). */
  .eq-slot-picker-panel .eq-pick-action.is-equip {
    background: linear-gradient(180deg, #c08a44 0%, #8c5a28 100%);
    color: #fbecca;
    border: 2px solid #6e4a20;
    box-shadow: inset 0 1px 0 rgba(255, 240, 205, 0.45), 0 3px 7px -2px rgba(40, 22, 8, 0.5);
    text-shadow: 0 1px 1px rgba(60, 30, 8, 0.6);
    font-family: 'EB Garamond', 'Cinzel', serif;
    letter-spacing: 1px;
  }
  /* EQUIPPED — gold confirm. */
  .eq-slot-picker-panel .eq-pick-action.is-equipped,
  .eq-slot-picker-panel .eq-pick-action.is-equipped-state {
    background: linear-gradient(180deg, #e7c25a 0%, #c2922f 100%);
    color: #3a2a10;
    border: 2px solid #8a6520;
    box-shadow: inset 0 1px 0 rgba(255, 250, 220, 0.6);
    text-shadow: none;
  }
  .eq-slot-picker-panel .eq-pick-action.is-equipped::before,
  .eq-slot-picker-panel .eq-pick-action.is-equipped-state::before { color: #3a2a10; }
  /* EMPOWER (upgrade) — navy plaque with gold rim + cost (mock). */
  .eq-slot-picker-panel .eq-pick-action.is-upgrade {
    background: linear-gradient(180deg, #34467e 0%, #1d2a50 100%);
    color: #eaf0ff;
    border: 2px solid #c9a24a;
    box-shadow: inset 0 1px 0 rgba(180, 200, 255, 0.25), 0 3px 7px -2px rgba(20, 14, 4, 0.5);
  }
  .eq-slot-picker-panel .eq-pick-action.is-upgrade:hover:not(:disabled) {
    background: linear-gradient(180deg, #3e528f 0%, #243262 100%);
    border-color: #e0bd66;
  }
  .eq-slot-picker-panel .eq-pick-action.is-upgrade .eq-pick-action-label { font-weight: 900; letter-spacing: 0.6px; }
  .eq-slot-picker-panel .eq-pick-action.is-upgrade .eq-pick-action-cost { color: #ffe49a; }
  /* FUSE — keep the bright gold gradient (already warm) but gold rim. */
  .eq-slot-picker-panel .eq-pick-action.is-evolve { border: 2px solid #8a6520; }
  /* BUY (superweapon) — violet stays for "spend relics", warm gold rim. */
  .eq-slot-picker-panel .eq-pick-action.is-buy { border: 2px solid #c9a24a; }
  .eq-slot-picker-panel .eq-pick-action.is-broke { opacity: 0.55; }
  /* Locked rows: dim the parchment a touch rather than the dark treatment. */
  .eq-slot-picker-panel .eq-pick-row.is-locked { opacity: 0.7; filter: saturate(0.8); }

  /* Landscape phones (iPhone 13 844×390, S20 Ultra 915×412): the centred
     modal is short here, so the default banner + 140px cards only show ~1
     row. Use more of the height and compact the banner + cards (smaller icon
     well, tighter spacing/fonts) so 2-3 cards read cleanly and the list
     scrolls smoothly. The single-column mock layout is preserved. */
  @media (orientation: landscape) and (max-height: 500px) {
    .eq-slot-picker-panel { width: min(660px, 92vw); max-height: 94vh; }
    .eq-slot-picker-head { padding: 9px 14px 3px; }
    .eq-slot-picker-head::after { margin-top: 6px; }
    .eq-slot-picker-title { padding: 4px 26px; }
    .eq-slot-picker-title::before, .eq-slot-picker-title::after { width: 11px; }
    .eq-slot-picker-name { font-size: 17px; letter-spacing: 1px; }
    .eq-slot-picker-body { padding: 8px 12px 12px; gap: 9px; }
    .eq-slot-picker-panel .eq-pick-row {
      grid-template-columns: 86px 1fr;
      gap: 13px;
      padding: 9px 11px;
    }
    .eq-slot-picker-panel .eq-pick-preview { width: 86px; height: 86px; border-radius: 12px; }
    .eq-slot-picker-panel .eq-pick-name { font-size: 16px; margin-bottom: 2px; }
    .eq-pick-meta { margin-bottom: 3px; }
    .eq-slot-picker-panel .eq-pick-desc { font-size: 11px; line-height: 1.3; margin-bottom: 4px; }
    .eq-pick-stats { gap: 2px 10px; }
    .eq-slot-picker-panel .eq-pick-stat-val { font-size: 14px; }
    .eq-pick-actions { margin-top: 6px; gap: 6px; }
    .eq-slot-picker-panel .eq-pick-action { padding: 5px 11px; min-height: 24px; font-size: 10px; }
  }

  /* Slot-card SVG icon for superweapon (no GLB preview available). */
  .eq-slot-card-svg {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    color: var(--slot, #ffd166);
  }
  .eq-slot-card-svg svg { width: 80%; height: 80%; }
  /* Picker preview wrapper for superweapon SVG icons. */
  .eq-pick-svg-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    color: var(--slot, #ffd166);
  }
  .eq-pick-svg-wrap svg { width: 70%; height: 70%; }
  .eq-pick-action.is-maxed {
    background: #0c1322;
    color: var(--slot);
    border: 1.5px solid var(--slot);
    cursor: default;
    font-size: 10px;
    letter-spacing: 1.2px;
  }
  .eq-pick-action:disabled { opacity: 0.45; cursor: not-allowed; }
  /* "Broke" state — clickable but dim, signals the player can't afford
     the cost yet. Click intercepts and pops the insufficient-resources
     dialog with a link to the IAP store. */
  .eq-pick-action.is-broke {
    opacity: 0.55;
    filter: grayscale(0.4);
  }
  .eq-pick-action.is-broke:hover {
    opacity: 0.8;
    filter: grayscale(0.2);
  }
  .eq-pick-action:not(:disabled):hover { transform: translateY(-1px); }
  .eq-pick-action:not(:disabled):active { transform: translateY(0) scale(0.96); }

  /* Insufficient-resources popup — opens on top of the slot picker
     when the player taps UPGRADE/EVOLVE without enough shards/stones.
     Smaller and lighter than a full modal; closes back to the picker. */
  .eq-pick-insufficient {
    position: fixed;
    inset: 0;
    z-index: 9100;
    display: none;
    align-items: center;
    justify-content: center;
    pointer-events: none;
  }
  .eq-pick-insufficient.is-open {
    display: flex;
    pointer-events: auto;
    animation: eq-pick-insufficient-in 180ms ease-out both;
  }
  @keyframes eq-pick-insufficient-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }
  .eq-pick-insufficient-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(6, 10, 22, 0.65);
  }
  .eq-pick-insufficient-card {
    position: relative;
    width: min(380px, calc(100% - 32px));
    /* rc158 — opaque popup card. */
    background: var(--panel-bg, #131a2e);
    border: 1px solid #2a3454;
    border-radius: 18px;
    padding: 28px 24px 22px;
    box-shadow:
      0 24px 60px -16px rgba(0,0,0,0.7),
      0 0 0 1px #2a3454 inset;
    animation: eq-pick-insufficient-card-in 240ms cubic-bezier(0.2,1.2,0.4,1) both;
  }
  @keyframes eq-pick-insufficient-card-in {
    from { transform: scale(0.92) translateY(8px); opacity: 0; }
    to   { transform: scale(1) translateY(0);    opacity: 1; }
  }
  .eq-pick-insufficient-close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: #2a3454;
    border: 1px solid #4a5478;
    color: #cfd5e8;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }
  .eq-pick-insufficient-close:hover { background: #3a4470; color: #fff; }
  .eq-pick-insufficient-title {
    margin: 0 0 8px;
    font-size: 18px;
    font-weight: 800;
    letter-spacing: 0.2px;
    color: #fff;
  }
  .eq-pick-insufficient-body {
    margin: 0 0 18px;
    color: #cfd5e8;
    font-size: 13px;
    line-height: 1.45;
  }
  .eq-pick-insufficient-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
  }
  .eq-pick-insufficient-cancel,
  .eq-pick-insufficient-buy {
    border: none;
    padding: 10px 16px;
    border-radius: 10px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
  }
  .eq-pick-insufficient-cancel {
    background: #2a3454;
    color: #cfd5e8;
    border: 1px solid #4a5478;
  }
  .eq-pick-insufficient-cancel:hover { background: #3a4470; color: #fff; }
  .eq-pick-insufficient-buy {
    background: linear-gradient(135deg, #ffd000, #ff8a3a);
    color: #0a0e1c;
    box-shadow: 0 4px 14px -4px rgba(255, 200, 60, 0.55);
  }
  .eq-pick-insufficient-buy:hover { transform: translateY(-1px); }
  .eq-pick-insufficient-buy:active { transform: translateY(0) scale(0.97); }
  .eq-pick-action-cost {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.4px;
    opacity: 0.85;
  }

  /* Mobile (≤480px) — shrink the hero preview a touch and let action
     pills fill the body width so they're comfortable to tap. */
  @media (max-width: 480px) {
    .eq-pick-row {
      grid-template-columns: 110px 1fr;
      gap: 12px;
      padding: 12px;
    }
    .eq-pick-icon { width: 44px; height: 44px; padding: 7px; }
    .eq-pick-preview {
      width: 110px;
      height: 110px;
      border-radius: 14px;
    }
    .eq-pick-actions { gap: 6px; }
    .eq-pick-action { flex: 1 1 auto; min-width: 0; }
  }

  /* ══════════════════════════════════════════════════════════════════
     UPGRADE POPUP — multi-level upgrade with stat preview
     Shown when the player taps UPGRADE on an equipment card. Lets them
     choose how many levels to upgrade, previews stat changes, and shows
     total cost before confirming.
     ══════════════════════════════════════════════════════════════════ */
  .eq-upgrade-popup {
    position: fixed;
    inset: 0;
    z-index: 9100;
    display: none;
    align-items: center;
    justify-content: center;
    pointer-events: none;
  }
  .eq-upgrade-popup.is-open {
    display: flex;
    pointer-events: auto;
    animation: eq-upgrade-fade-in 180ms ease-out both;
  }
  @keyframes eq-upgrade-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }
  .eq-upgrade-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(6, 10, 22, 0.72);
  }
  .eq-upgrade-card {
    position: relative;
    width: min(380px, calc(100% - 32px));
    background: var(--panel-bg, #131a2e);
    border: 1px solid #2a3454;
    border-radius: 18px;
    padding: 28px 24px 22px;
    box-shadow:
      0 24px 60px -16px rgba(0, 0, 0, 0.7),
      0 0 0 1px #2a3454 inset;
    animation: eq-upgrade-card-in 240ms cubic-bezier(0.2, 1.2, 0.4, 1) both;
  }
  @keyframes eq-upgrade-card-in {
    from { transform: translateY(20px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
  }
  .eq-upgrade-close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: #2a3454;
    border: 1px solid #4a5478;
    color: #cfd5e8;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }
  .eq-upgrade-close:hover { background: #3a4470; color: #fff; }

  .eq-upgrade-title {
    margin: 0 0 4px;
    font-size: 18px;
    font-weight: 800;
    letter-spacing: 0.4px;
    color: #fff;
  }
  .eq-upgrade-item-name {
    color: var(--slot, #4cc8ff);
  }
  .eq-upgrade-level {
    font-size: 14px;
    font-weight: 700;
    color: rgba(220, 230, 255, 0.8);
    margin-bottom: 16px;
    letter-spacing: 0.2px;
  }
  .eq-upgrade-lv-to {
    color: #66ff99;
    font-weight: 800;
  }

  /* Stat preview rows */
  .eq-upgrade-stats {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 18px;
    padding: 12px 14px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 12px;
  }
  .eq-upgrade-stat-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
  }
  .eq-upgrade-stat-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1px;
    color: rgba(200, 215, 245, 0.6);
    text-transform: uppercase;
    width: 100%;
    margin-bottom: -2px;
  }
  .eq-upgrade-stat-current {
    font-size: 18px;
    font-weight: 800;
    color: #cfd5e8;
  }
  .eq-upgrade-stat-arrow {
    font-size: 14px;
    color: rgba(220, 230, 255, 0.45);
    margin: 0 2px;
  }
  .eq-upgrade-stat-new {
    font-size: 18px;
    font-weight: 900;
    color: #66ff99;
  }
  .eq-upgrade-stat-delta {
    font-size: 12px;
    font-weight: 700;
    color: #66ff99;
    opacity: 0.85;
  }

  /* Level selector row */
  .eq-upgrade-selector {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-bottom: 16px;
  }
  .eq-upgrade-minus,
  .eq-upgrade-plus {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: #2a3454;
    border: 1px solid #4a5478;
    color: #fff;
    font-size: 18px;
    font-weight: 700;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.12s ease, transform 0.1s ease;
    padding: 0;
  }
  .eq-upgrade-minus:hover:not(:disabled),
  .eq-upgrade-plus:hover:not(:disabled) {
    background: #3a4a70;
    transform: translateY(-1px);
  }
  .eq-upgrade-minus:disabled,
  .eq-upgrade-plus:disabled {
    opacity: 0.35;
    cursor: not-allowed;
  }
  .eq-upgrade-count {
    font-size: 24px;
    font-weight: 900;
    color: #fff;
    min-width: 48px;
    text-align: center;
    letter-spacing: 0.2px;
  }
  .eq-upgrade-max {
    padding: 7px 14px;
    border-radius: 8px;
    background: #2a3454;
    border: 1px solid #4a5478;
    color: #fff;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 1px;
    cursor: pointer;
    transition: background 0.12s ease, transform 0.1s ease;
  }
  .eq-upgrade-max:hover:not(:disabled) {
    background: #3a4a70;
    transform: translateY(-1px);
  }
  .eq-upgrade-max:disabled {
    opacity: 0.35;
    cursor: not-allowed;
  }

  /* Cost display */
  .eq-upgrade-cost {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    margin-bottom: 18px;
    font-size: 13px;
    font-weight: 700;
    color: #cfd5e8;
  }
  .eq-upgrade-cost-shards,
  .eq-upgrade-cost-stars {
    display: inline-flex;
    align-items: center;
    gap: 4px;
  }
  .eq-upgrade-cost-stars {
    color: #ffd766;
  }

  /* Action buttons */
  .eq-upgrade-actions {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
  }
  .eq-upgrade-cancel {
    padding: 10px 18px;
    border-radius: 10px;
    background: #2a3454;
    border: 1px solid #4a5478;
    color: #cfd5e8;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
    transition: background 0.12s ease;
  }
  .eq-upgrade-cancel:hover { background: #3a4470; color: #fff; }
  .eq-upgrade-confirm {
    padding: 10px 22px;
    border-radius: 10px;
    background: linear-gradient(135deg, #6b3ed8, #b674ff);
    border: none;
    color: #fff;
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
    box-shadow: 0 4px 14px -4px rgba(168, 110, 255, 0.55);
    transition: transform 0.1s ease, filter 0.12s ease;
  }
  .eq-upgrade-confirm:hover:not(:disabled) {
    transform: translateY(-1px);
    filter: brightness(1.1);
  }
  .eq-upgrade-confirm:active:not(:disabled) {
    transform: translateY(0) scale(0.97);
  }
  .eq-upgrade-confirm:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    filter: grayscale(0.5);
  }

  /* ── Per-instance spares (item 6) + FUSE EQUIPPED pill (item 5) ── */
  .eq-pick-spares {
    margin-top: 8px;
    display: flex; flex-direction: column; gap: 5px;
  }
  .eq-pick-spares-label {
    font-size: 9px; font-weight: 800; letter-spacing: 1.2px;
    text-transform: uppercase; color: rgba(255, 255, 255, 0.4);
  }
  .eq-spare-chips { display: flex; flex-wrap: wrap; gap: 5px; }
  .eq-spare-chip {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 9px 3px 7px; border-radius: 999px;
    font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
    color: #f3ecd8; cursor: pointer;
    background: color-mix(in srgb, var(--sc, #ffd700) 14%, rgba(10, 10, 18, 0.85));
    border: 1.5px solid color-mix(in srgb, var(--sc, #ffd700) 55%, transparent);
    transition: transform 0.12s ease, filter 0.12s ease;
  }
  .eq-spare-chip:hover:not(:disabled) { transform: translateY(-1px); filter: brightness(1.18); }
  .eq-spare-chip:disabled { opacity: 0.45; cursor: not-allowed; }
  .eq-spare-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--sc, #ffd700);
    box-shadow: 0 0 5px var(--sc, #ffd700);
    flex-shrink: 0;
  }
  /* FUSE EQUIPPED reads as a hotter variant of the FUSE pill. */
  .eq-pick-action.is-evolve-primary {
    background: linear-gradient(135deg, rgba(255, 120, 70, 0.25), rgba(180, 60, 200, 0.25));
    border-color: rgba(255, 150, 90, 0.6);
  }
