    /* ==========================================================================
       BASE = EXECUTIVE LOUNGE
       --------------------------------------------------------------------
       These are the app's defaults: no data-theme attribute means Executive
       Lounge. Until recently this block held the Neon Grid palette, which is
       why Neon had no [data-theme="neon"] rules of its own - the base WAS
       the neon skin, and every other theme was a patch over it. Neon is a
       normal theme now, and anything added to the base from here on inherits
       the restrained look rather than a cyberpunk one.

       applyTheme() in index.html overwrites all of these as inline styles on
       <html> the moment JS runs, so what is written here only governs first
       paint. The per-theme token blocks further down keep that first paint
       correct for the other five themes.
       ========================================================================== */
    :root {
      --bg-base: #050507;
      --accent-gold: #D4AF37;
      --accent-gold-hover: #E5C158;
      --accent-gold-dim: rgba(212, 175, 55, 0.15);
      --accent-gold-glow: rgba(212, 175, 55, 0.15);
      /* Poured-metal fill for the controls that mean money: the primary CTA,
         the collect button, the wordmark's brand word. One definition
         instead of the same three-stop gradient copy-pasted per selector -
         retune the bar once, every gold surface follows. */
      --gold-metal: linear-gradient(180deg, #F3DA92 0%, #D4AF37 48%, #A87A22 100%);
      --accent-silver: #E3E4E5;
      --accent-bronze: #CD7F32;
      --accent-green: #3FBF8F;
      --accent-green-dim: rgba(63, 191, 143, 0.15);
      --accent-pink: #B4485C;
      --accent-pink-dim: rgba(180, 72, 92, 0.15);
      --accent-orange: #C2843C;
      --accent-orange-dim: rgba(194, 132, 60, 0.15);
      --accent-cyan: #7E8794;
      --accent-cyan-dim: rgba(126, 135, 148, 0.15);
      --glass-border: rgba(255, 255, 255, 0.08);
      --glass-highlight: rgba(232, 205, 140, 0.09);
      --text-main: #F8F9FA;
      --text-muted: #8A8D93;
      --text-dim: #5A5D63;
      /* Podium ramp: gold, silver, bronze. The tier washes downstream derive
         from these, so remapping a tier here remaps its badge fill too. */
      --tier-s: var(--accent-gold);
      --tier-a: var(--accent-silver);
      --tier-b: var(--accent-bronze);
      --tier-c: #8A8D93;
      --tier-d: #5A5D63;
      /* Added 2026-09-23 with the six-band tier system. Not per-themed, same
         as --tier-d above - the ramp's bottom rungs stay one shared neutral
         (or, for F, one shared warning tone) across every theme rather than
         each theme tuning its own "this platform is bad" color. */
      --tier-f: #8B4A4A;
      --tier-notrankable: #6E5A8C;
    }

    /* ==========================================================================
       PER-THEME TOKEN OVERRIDES
       --------------------------------------------------------------------
       Mirrors THEMES.<id>.vars in index.html exactly. Without this block, a
       theme's first paint (before applyTheme() runs) fell through to
       whatever :root held - previously always the neon palette, now always
       Executive's. A Prism or Obsidian user's very first frame used to be
       (very briefly) neon-colored; this closes that gap for every theme.
       [data-theme="X"] and :root share specificity (both a single attribute/
       pseudo-class selector) on the same <html> element, so source order
       decides the tie - these must stay AFTER :root to win it.
       Executive Lounge has no block here: it IS the base now. ========================================================================== */
    [data-theme="western"] {
      --bg-base: #0B0B0B;
      --accent-gold: #FFC107;
      --accent-gold-hover: #E0A800;
      --accent-gold-dim: rgba(255, 193, 7, 0.18);
      --accent-green: #8AA624;
      --accent-green-dim: rgba(138, 166, 36, 0.18);
      --accent-pink: #810000;
      --accent-pink-dim: rgba(129, 0, 0, 0.22);
      --accent-orange: #C16B2C;
      --accent-orange-dim: rgba(193, 107, 44, 0.18);
      --accent-cyan: #6E7C7C;
      --accent-cyan-dim: rgba(110, 124, 124, 0.18);
      --glass-border: rgba(234, 234, 234, 0.15);
      --glass-highlight: rgba(234, 234, 234, 0.08);
      --text-main: #E3DAC9;
      --text-muted: #B8AD9A;
      --text-dim: #6b6b66;
      --tier-s: #810000;
      --tier-a: #C16B2C;
      --tier-b: #6E7C7C;
      --tier-c: #5C4B51;
    }

    [data-theme="prism"] {
      --bg-base: #0a0b0a;
      --accent-gold: #c9a227;
      --accent-gold-hover: #e0bb45;
      --accent-gold-dim: rgba(201, 162, 39, 0.14);
      --accent-green: #3d8767;
      --accent-green-dim: rgba(61, 135, 103, 0.14);
      --accent-pink: #9e3540;
      --accent-pink-dim: rgba(158, 53, 64, 0.16);
      --accent-orange: #a8763f;
      --accent-orange-dim: rgba(168, 118, 63, 0.14);
      --accent-cyan: #c4b998;
      --accent-cyan-dim: rgba(196, 185, 152, 0.12);
      --glass-border: rgba(201, 162, 39, 0.18);
      --glass-highlight: rgba(255, 250, 235, 0.07);
      --text-main: #f4efe4;
      --text-muted: #9c958a;
      --text-dim: #645e56;
      --tier-s: #c9a227;
      --tier-a: #b9c0c4;
      --tier-b: #3d8767;
      --tier-c: #7a736a;
      --wire-cyan: #00e5ff;
      --wire-magenta: #ff2fb0;
      --wire-amber: #ff8a1f;
      --wire-violet: #a45cff;
    }

    [data-theme="neon"] {
      --bg-base: #070a10;
      --accent-gold: #ffcc00;
      --accent-gold-hover: #e6b800;
      --accent-gold-dim: rgba(255, 204, 0, 0.15);
      --accent-green: #00ff66;
      --accent-green-dim: rgba(0, 255, 102, 0.15);
      --accent-pink: #ff007f;
      --accent-pink-dim: rgba(255, 0, 127, 0.15);
      --accent-orange: #ff6600;
      --accent-orange-dim: rgba(255, 102, 0, 0.15);
      --accent-cyan: #00e5ff;
      --accent-cyan-dim: rgba(0, 229, 255, 0.15);
      --glass-border: rgba(255, 255, 255, 0.08);
      --glass-highlight: rgba(255, 255, 255, 0.2);
      --text-main: #e2f1ec;
      --text-muted: #8b9bb4;
      --text-dim: #4d665b;
      --tier-s: #ff007f;
      --tier-a: #ff6600;
      --tier-b: #00e5ff;
      --tier-c: #8b5cf6;
    }

    [data-theme="obsidian"] {
      --bg-base: #161514;
      --accent-gold: #b08d57;
      --accent-gold-hover: #9a7a49;
      --accent-gold-dim: rgba(176, 141, 87, 0.15);
      --accent-green: #7d9b7a;
      --accent-green-dim: rgba(125, 155, 122, 0.15);
      --accent-pink: #a86b62;
      --accent-pink-dim: rgba(168, 107, 98, 0.15);
      --accent-orange: #a07450;
      --accent-orange-dim: rgba(160, 116, 80, 0.15);
      --accent-cyan: #5e7c6e;
      --accent-cyan-dim: rgba(94, 124, 110, 0.15);
      --glass-border: rgba(240, 232, 220, 0.10);
      --glass-highlight: rgba(240, 232, 220, 0.06);
      --text-main: #ece5d9;
      --text-muted: #9b9287;
      --text-dim: #655e56;
      --tier-s: #b08d57;
      --tier-a: #a07450;
      --tier-b: #5e7c6e;
      --tier-c: #7a6e8c;
    }

    [data-theme="glitch"] {
      --bg-base: #060806;
      --accent-gold: #39FF14;
      --accent-gold-hover: #5EFF42;
      --accent-gold-dim: rgba(57, 255, 20, 0.16);
      --accent-green: #00FFA0;
      --accent-green-dim: rgba(0, 255, 160, 0.16);
      --accent-pink: #FF2A2A;
      --accent-pink-dim: rgba(255, 42, 42, 0.18);
      --accent-orange: #FFB000;
      --accent-orange-dim: rgba(255, 176, 0, 0.16);
      --accent-cyan: #00E5FF;
      --accent-cyan-dim: rgba(0, 229, 255, 0.16);
      --glass-border: rgba(57, 255, 20, 0.18);
      --glass-highlight: rgba(57, 255, 20, 0.08);
      --text-main: #D6FFD6;
      --text-muted: #7FAE7F;
      --text-dim: #3F5C3F;
      --tier-s: #FF2A2A;
      --tier-a: #FFB000;
      --tier-b: #00E5FF;
      --tier-c: #3F5C3F;
    }

    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      -webkit-tap-highlight-color: transparent;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    }

    body {
      /* Pre-paint ground only. applyTheme() overwrites this with the active
         theme's bodyBg as soon as JS runs, and Executive Lounge's version is
         the one carrying assets/background.webp. That url() cannot live in
         this file: CSS resolves relative urls against the STYLESHEET, so
         "assets/background.webp" here would mean assets/assets/... and 404.
         It is set from index.html instead, where the document is the base. */
      background: linear-gradient(180deg, #050507 0%, #08090c 100%);
      background-attachment: fixed;
      color: var(--text-main);
      min-height: 100vh;
      padding: 20px 16px 100px;
      overflow-x: hidden;
    }

    /* Dark frosted glass. 0.75 opacity with a 12px blur is the Executive
       Lounge card: opaque enough to read as a surface, blurred enough that
       the ground texture still moves behind it. Don't trade blur radius for
       opacity if this ever needs clawing back on low-end hardware - the
       opacity is what makes it read as glass. */
    .glass-panel {
      background: rgba(22, 24, 29, 0.75);
      backdrop-filter: blur(12px);
      -webkit-backdrop-filter: blur(12px);
      border: 1px solid var(--glass-border);
      border-top: 1px solid var(--glass-highlight);
      border-left: 1px solid var(--glass-highlight);
      box-shadow: 0 1px 0 rgba(255, 255, 255, 0.03) inset, 0 6px 24px rgba(0, 0, 0, 0.55);
    }

    .app-container { max-width: 640px; margin: 0 auto; position: relative; }
    .top-bar-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
    .date-header { font-size: 0.75rem; font-weight: 800; letter-spacing: 0.15em; text-transform: uppercase; color: var(--text-muted); }
    .btn-settings-gear { background: transparent; border: none; color: var(--text-muted); font-size: 1.2rem; cursor: pointer; padding: 4px; transition: all 0.2s; }
    .btn-settings-gear:hover { color: var(--accent-gold); }

    /* The wordmark is the one place the base gets to be ornamental: a served
       serif, the brand word in gold. Neon's hollow monospace stroke is an
       override now, not the default. */
    .app-title { font-family: Georgia, "Times New Roman", serif; font-size: 2rem; font-weight: 700; color: var(--text-main); margin-bottom: 24px; letter-spacing: 0.01em; text-transform: none; text-align: center; }
    .app-title span { color: var(--accent-gold); }

    .hero-stat-card { border-radius: 20px; padding: 20px; display: flex; align-items: center; gap: 18px; margin-bottom: 20px; }
    .btn-start-run.hero-run-btn { width: auto; margin: 0; padding: 6px 2px; font-size: 0.85rem; text-align: left; }
    .hero-ring-wrapper { position: relative; width: 72px; height: 72px; flex-shrink: 0; }
    .hero-ring-circle { width: 100%; height: 100%; border-radius: 50%; border: 2px solid var(--accent-green); display: flex; align-items: center; justify-content: center; font-size: 1.5rem; font-weight: 900; color: var(--text-main); background: color-mix(in srgb, var(--accent-green) 8%, transparent); cursor: pointer; }
    /* Popout: collapsed by default, tapping the ring number reveals it -
       the ring used to just sit there looking pretty; now it's the way
       in to this detail instead of the detail being permanently on
       screen. Height-animated (not display:none/block) so it opens and
       closes instead of snapping. */
    .hero-details-popout { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; }
    .hero-details-popout.open { max-height: 160px; }
    .hero-details h2 { font-size: 1.15rem; font-weight: 800; color: var(--text-main); margin: 8px 0 4px; }
    .hero-details p { font-size: 0.78rem; color: var(--text-muted); font-family: "Courier New", Courier, monospace; }

    .nav-pill-group { display: flex; gap: 6px; margin-bottom: 12px; padding: 6px; border-radius: 30px; }
    .nav-tab { flex: 1; padding: 9px 6px; background: transparent; border: 1px solid transparent; border-radius: 24px; color: var(--text-muted); font-size: 0.76rem; font-weight: 700; cursor: pointer; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 3px; transition: all 0.3s ease; }
    .nav-tab.active { background: var(--accent-gold-dim); color: var(--accent-gold); border: 1px solid var(--accent-gold); }

    .filter-sort-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
    .filter-chips { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; flex: 1; }
    .filter-chips::-webkit-scrollbar { display: none; }
    .filter-btn { padding: 6px 12px; background: rgba(0,0,0,0.4); border: 1px solid var(--glass-border); border-radius: 20px; color: var(--text-muted); font-size: 0.76rem; font-weight: 600; cursor: pointer; white-space: nowrap; transition: all 0.2s; }
    .filter-btn.active { background: var(--accent-gold-dim); color: var(--accent-gold); border-color: var(--accent-gold); }
    .sort-trigger-btn { padding: 6px 12px; background: rgba(0,0,0,0.4); border: 1px solid var(--accent-gold); border-radius: 20px; color: var(--accent-gold); font-size: 0.78rem; font-weight: 800; cursor: pointer; display: flex; align-items: center; gap: 4px; flex-shrink: 0; white-space: nowrap; }
    .sort-trigger-btn.secondary { color: var(--text-main); border-color: var(--glass-highlight); box-shadow: none; text-shadow: none; }

    .tier-action-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .tier-action-card { background: rgba(0,0,0,0.3); border: 1px solid var(--glass-border); border-radius: 8px; padding: 10px; display: flex; flex-direction: column; gap: 10px; }
    .tier-action-card-header { display: flex; align-items: center; justify-content: space-between; }
    .tier-btn-pair { display: flex; gap: 6px; width: 100%; }
    .btn-tier-toggle { flex: 1; padding: 8px 4px; border-radius: 6px; border: 1px solid var(--glass-border); font-size: 0.72rem; font-weight: 800; cursor: pointer; background: rgba(0,0,0,0.5); color: var(--text-main); transition: all 0.2s; }
    .btn-tier-toggle.add:hover { background: var(--accent-green-dim); color: var(--text-main); border-color: var(--accent-green); }
    .btn-tier-toggle.remove:hover { background: var(--accent-pink-dim); color: var(--text-main); border-color: var(--accent-pink); }

    .active-sort-stack { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; min-height: 24px; }
    .sort-stack-chip { background: rgba(0, 0, 0, 0.5); border: 1px solid var(--accent-orange); color: var(--accent-orange); font-size: 0.7rem; font-weight: 700; padding: 4px 10px; border-radius: 6px; display: flex; align-items: center; gap: 6px; }
    .sort-stack-chip .btn-remove-sort { cursor: pointer; opacity: 0.7; }
    .sort-stack-chip .btn-remove-sort:hover { opacity: 1; }

    .sort-drawer { display: none; border-radius: 14px; padding: 14px; margin-bottom: 14px; animation: fadeIn 0.2s ease-in-out; }
    .sort-drawer.open { display: block; }
    @keyframes fadeIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
    .sort-drawer-header { font-size: 0.75rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; color: var(--accent-gold); margin-bottom: 12px; display: flex; justify-content: space-between; }
    .sort-options-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
    .sort-option-btn { padding: 10px; background: rgba(0,0,0,0.4); border: 1px solid var(--glass-border); border-radius: 8px; color: var(--text-muted); font-size: 0.76rem; font-weight: 600; text-align: left; cursor: pointer; display: flex; justify-content: space-between; align-items: center; transition: all 0.2s; }
    .sort-option-btn.active { border-color: var(--accent-orange); color: var(--text-main); background: var(--accent-orange-dim); }
    .sort-priority-num { background: var(--accent-orange); color: #000; width: 18px; height: 18px; border-radius: 50%; font-size: 0.65rem; font-weight: 900; display: inline-flex; align-items: center; justify-content: center; text-shadow: none; }

    .game-list { display: flex; flex-direction: column; gap: 12px; }
    .ledger-card-wrapper { display: flex; flex-direction: column; gap: 6px; }
    /* Column, not a single left/actions row - that row had name+tier+LIVE
       squeezed into whatever was left after four action buttons
       (clock/check/open/dots, ~213px on a 420px phone) claimed their
       space, leaving the name as little as ~70px to work with before it
       had to ellipsis, and even then the tier/LIVE badges still wrapped
       onto their own line - a platform with a longer name or a LIVE
       badge silently got a taller, misaligned card. Splitting into two
       full-width rows (top: avatar+name+badges, bottom: status+actions)
       gives the name the entire card width instead of a leftover sliver. */
    .ledger-card { border-radius: 14px; padding: 14px; display: flex; flex-direction: column; gap: 10px; transition: transform 0.2s; }
    .ledger-card:active { transform: scale(0.98); }
    .card-left { display: flex; align-items: center; gap: 14px; flex: 1; min-width: 0; }
    /* nowrap, not wrap: wrapping is what made the list look ragged - a
       card whose status line ran long pushed its buttons onto a second
       row while its neighbours kept theirs on the first, so no two cards
       agreed on where anything sat. Status takes the slack and truncates;
       the button cluster never moves. */
    .card-bottom-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: nowrap; position: relative; z-index: 1; }
    .casino-avatar { width: 46px; height: 46px; border-radius: 50%; border: 1px solid var(--glass-border); background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center; font-family: "Courier New", Courier, monospace; font-weight: 900; font-size: 1rem; color: var(--text-main); flex-shrink: 0; cursor: pointer; transition: all 0.2s; }
    .casino-avatar:active { transform: scale(0.9); }

    .keen-info-popover { display: none; border: 1px dashed var(--accent-pink); border-radius: 12px; padding: 12px 14px; font-size: 0.8rem; color: var(--text-main); line-height: 1.5; animation: fadeIn 0.2s ease-in-out; box-shadow: 0 8px 32px rgba(0,0,0,0.5); background: rgba(10, 16, 22, 0.85); backdrop-filter: blur(10px); }
    .keen-info-popover.open { display: block; }
    .keen-title { font-weight: 800; color: var(--accent-pink); margin-bottom: 4px; }

    /* The plain-English readout casual users actually want, built from
       structured fields rather than the verbose research notes below it.
       Blocked platforms (a purchase gate, a lifetime cap) get a louder
       warning treatment since that's the one fact nobody should miss. */
    .keen-summary { font-size: 0.78rem; color: var(--text-muted); margin-bottom: 8px; }
    .keen-summary-blocked { color: var(--accent-orange); font-weight: 700; }

    /* Full research notes: collapsed by default behind a native <details>
       disclosure, so the history stays on record without burying the
       summary above it under a wall of text. */
    .keen-notes-toggle { margin-bottom: 4px; }
    .keen-notes-toggle summary { cursor: pointer; font-size: 0.72rem; font-weight: 700; color: var(--text-dim); letter-spacing: 0.03em; text-transform: uppercase; padding: 2px 0; }
    .keen-notes-toggle summary:hover { color: var(--text-muted); }
    .keen-notes-toggle[open] summary { color: var(--accent-cyan); margin-bottom: 6px; }
    .keen-notes-body { font-size: 0.78rem; color: var(--text-muted); line-height: 1.5; }

    .strategy-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
    .strategy-row { background: rgba(0, 0, 0, 0.4); border: 1px solid var(--glass-border); border-radius: 8px; overflow: hidden; transition: all 0.2s; }
    .strategy-row.interactive { cursor: pointer; }
    .strategy-row.interactive:hover { border-color: var(--accent-gold); background: color-mix(in srgb, var(--accent-gold) 8%, transparent); }
    .strategy-row-header { padding: 8px 10px; font-size: 0.78rem; font-weight: 700; display: flex; justify-content: space-between; align-items: center; color: var(--accent-gold); }
    .strategy-row-body { display: none; padding: 10px; font-size: 0.75rem; color: var(--text-main); background: rgba(0,0,0,0.6); border-top: 1px solid var(--glass-border); line-height: 1.5; }
    .strategy-row.expanded .strategy-row-body { display: block; }
    .strategy-row.expanded .expand-icon { transform: rotate(180deg); }

    /* flex:1 + min-width:0 is what actually lets .casino-name's own
       ellipsis rule bite - without it a flex item's min-width defaults
       to auto (its content's full natural size), so the row would just
       overflow instead of truncating the name and keeping the badges on
       the same line. */
    .card-title-row { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
    .card-title-row .casino-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
    .card-title-row .tier-badge, .card-title-row .type-badge { flex-shrink: 0; }
    /* Pushed to the far end of the title row, so every card has its
       cooldown in the same place. */
    .card-title-row .cooldown-chip { margin-left: auto; flex-shrink: 0; }
    .casino-name { flex-shrink: 1; min-width: 0; font-size: 0.98rem; font-weight: 800; color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .tier-badge { font-size: 0.65rem; font-weight: 900; padding: 2px 6px; border-radius: 4px; text-transform: uppercase; }
    .type-badge { font-size: 0.62rem; font-weight: 800; padding: 2px 5px; border-radius: 4px; background: var(--accent-orange-dim); color: var(--accent-orange); border: 1px solid var(--accent-orange); }

    /* Tier washes derive from the tier token rather than restating its hex,
       so a theme that remaps a tier (Executive Lounge runs gold/silver/bronze
       for S/A/B) gets the matching wash for free. */
    .tier-S { background: color-mix(in srgb, var(--tier-s) 20%, transparent); color: var(--tier-s); border: 1px solid var(--tier-s); }
    .tier-A { background: color-mix(in srgb, var(--tier-a) 20%, transparent); color: var(--tier-a); border: 1px solid var(--tier-a); }
    .tier-B { background: color-mix(in srgb, var(--tier-b) 20%, transparent); color: var(--tier-b); border: 1px solid var(--tier-b); }
    .tier-C { background: color-mix(in srgb, var(--tier-c) 20%, transparent); color: var(--tier-c); border: 1px solid var(--tier-c); }
    .tier-D { background: color-mix(in srgb, var(--tier-d) 18%, transparent); color: var(--tier-d); border: 1px dashed var(--tier-d); text-shadow: none; }
    .tier-F { background: color-mix(in srgb, var(--tier-f) 20%, transparent); color: var(--tier-f); border: 1px dashed var(--tier-f); text-shadow: none; }
    .tier-Unranked { background: rgba(255,255,255,0.06); color: var(--text-muted); border: 1px solid var(--glass-border); }
    /* Deliberately NOT styled like Unranked, even though both are "nothing to
       show" badges - Unranked is a data gap (a screenshot fixes it),
       Not Rankable is permanent (this platform has no guaranteed daily SC to
       rank at all). A dotted violet border keeps the two from reading as the
       same badge at a glance. */
    .tier-Not-Rankable { background: color-mix(in srgb, var(--tier-notrankable) 14%, transparent); color: var(--tier-notrankable); border: 1px dotted var(--tier-notrankable); text-shadow: none; }

    .card-status { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; color: var(--text-main); opacity: 0.8; flex: 1; min-width: 0; overflow: hidden; }
    .status-time { font-family: monospace; font-weight: 600; flex-shrink: 0; }
    .card-status .ready-at { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
    .status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent-green); display: inline-block; }
    .status-dot.cooldown { background: var(--text-muted); box-shadow: none; }

    /* Catalog data-freshness signal: neutral once actually verified,
       warning-colored when stale/never-checked so a rotting entry is
       visibly distrustable rather than looking identical to a fresh one. */
    .verify-tag { font-size: 0.68rem; color: var(--text-dim); margin-top: 2px; }
    .verify-tag.stale { color: var(--accent-orange); font-weight: 600; }

    .card-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
    /* The primary action on every card. Executive Lounge reads it as solid
       metallic gold on near-black rather than a lit gradient - this is the
       one control that must look expensive. */
    .btn-open { padding: 8px 18px; background: var(--accent-gold); color: #0a0a0a; border: none; border-radius: 20px; font-size: 0.85rem; font-weight: 900; cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45); transition: all 0.2s; }
    .btn-open:hover { background: var(--accent-gold-hover); transform: translateY(-1px); }
    .btn-open.cooldown { background: rgba(0,0,0,0.5); border: 1px solid var(--glass-border); color: var(--text-muted); font-weight: 700; font-size: 0.75rem; padding: 7px 14px; box-shadow: none; text-shadow: none; }
    .btn-dots { background: transparent; border: none; color: var(--text-main); font-size: 1.2rem; padding: 4px 8px; cursor: pointer; opacity: 0.7; transition: opacity 0.2s; }
    .btn-dots:hover { opacity: 1; }

    .catalog-search { width: 100%; padding: 12px 16px; border-radius: 12px; color: var(--text-main); font-size: 0.9rem; margin-bottom: 14px; outline: none; transition: all 0.2s; }
    .catalog-search:focus { border-color: var(--accent-gold); }
    .catalog-item-row { border-radius: 12px; padding: 12px 16px; display: flex; align-items: center; justify-content: space-between; cursor: pointer; transition: all 0.2s; }
    .catalog-item-row:hover { background: rgba(255,255,255,0.05); }
    .catalog-item-row.tracked { border-color: var(--accent-green); background: var(--accent-green-dim); }

    .docked-footer { position: fixed; bottom: 0; left: 0; right: 0; background: rgba(5, 7, 13, 0.6); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-top: 1px solid var(--glass-highlight); padding: 16px; display: flex; justify-content: center; z-index: 50; box-shadow: 0 -10px 40px rgba(0,0,0,0.8); }
    /* Two rows: Start Daily Run (moved here from the Platforms tab so
       it's reachable from every tab) stacked above the existing
       Add/Import row, both centered and capped at the same max width
       the rest of the app uses. */
    .docked-footer-inner { width: 100%; max-width: 640px; display: flex; flex-direction: column; gap: 10px; }
    .docked-footer-row { display: flex; justify-content: center; gap: 12px; }
    .btn-dock { flex: 1; max-width: 240px; padding: 12px 16px; background: rgba(0,0,0,0.6); border: 1px solid var(--glass-border); border-radius: 12px; color: var(--text-main); font-size: 0.9rem; font-weight: 800; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px; transition: all 0.2s; }
    .btn-dock:hover { background: var(--accent-gold-dim); border-color: var(--accent-gold); color: var(--accent-gold); }

    .landing-screen { position: fixed; inset: 0; background: radial-gradient(circle at center, #0c0d11 0%, #050507 100%); z-index: 200; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 32px; text-align: center; transition: opacity 0.4s ease, visibility 0.4s; }
    .landing-screen.hidden { opacity: 0; visibility: hidden; pointer-events: none; }
    /* A very faint film-grain layer over every theme's landing screen, to
       mask 8-bit colour banding on the near-black radial gradients behind
       it - two colour stops as close as #0c0d11 and #050507 don't have
       enough real steps between them to interpolate smoothly on an actual
       phone display, and paint as a visible ring instead of a blend
       ("like there's a wall" rather than atmosphere). Grain breaks a flat
       band up into high-frequency noise the eye reads as texture rather
       than an edge - it's the standard fix for this, not unique to this
       app, and it's also just a more expensive-looking surface than flat
       CSS gradients on their own. [data-theme="glitch"] .landing-screen::
       after (its own signal-corruption effect) outranks this by
       specificity, so that theme keeps its own texture instead of
       stacking both. */
    .landing-screen::after {
      content: '';
      position: absolute;
      inset: 0;
      pointer-events: none;
      opacity: 0.05;
      mix-blend-mode: overlay;
      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    }

    /* ---- Landing circuit board ---- */
    #circuitBg { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; pointer-events: none; transition: opacity .6s ease; }

    /* ---- Ember field (Boot Hill only, see THEME: Western below) ---- */
    #emberField { position: fixed; inset: 0; z-index: 1; opacity: 0; pointer-events: none; transition: opacity .6s ease; overflow: hidden; }

    /* ---- Demonic smoke field (Boot Hill only, see THEME: Western below) ---- */
    #smokeField { position: fixed; top: 0; left: 0; right: 0; height: 280px; z-index: 1; opacity: 0; pointer-events: none; transition: opacity .6s ease; overflow: hidden; }
    [data-theme="prism"] .landing-inner::before {
      background: radial-gradient(ellipse 78% 62% at 50% 50%, rgba(10,11,8,0.985) 0%, rgba(10,11,8,0.95) 50%, rgba(10,11,8,0.75) 74%, transparent 90%);
    }
    /* Wallet bezel around the landing copy: gold edge, stitched inner seam */
    [data-theme="prism"] .landing-inner {
      background: rgba(8,9,7,0.72);
      backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
      border: 1px solid rgba(201,162,39,0.5);
      border-radius: 3px;
      box-shadow: inset 0 0 0 1px rgba(233,214,150,0.10), 0 18px 50px rgba(0,0,0,0.65);
    }
    [data-theme="prism"] .landing-inner::after {
      content: ''; position: absolute; inset: 5px; pointer-events: none;
      border: 1px dashed rgba(214,178,74,0.4); border-radius: 2px;
    }
    /* Machined corner brackets, matching the cards */
    [data-theme="prism"] .landing-screen > .corner {
      position: absolute; width: 20px; height: 20px; pointer-events: none; z-index: 3;
      border-color: var(--accent-gold); opacity: 0.85;
    }

    .landing-inner { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; padding: 34px 26px 36px; max-width: 90vw; }
    /* Soft well behind the text so the dense board doesn't fight the copy */
    .landing-inner::before {
      content: ''; position: absolute; inset: -10% -14%; z-index: -1; pointer-events: none;
      background: radial-gradient(ellipse 72% 56% at 50% 50%, rgba(6,7,5,0.97) 0%, rgba(6,7,5,0.93) 46%, rgba(6,7,5,0.7) 70%, transparent 88%);
    }
    [data-theme="prism"] #circuitBg { opacity: 1; }

    #circuitBg .tr { fill: none; stroke-width: 1.1; opacity: 0.16; stroke-linecap: round; }
    #circuitBg .tr-c { stroke: #00e5ff; } #circuitBg .tr-m { stroke: #ff2fb0; }
    #circuitBg .tr-a { stroke: #ff8a1f; } #circuitBg .tr-v { stroke: #a45cff; }
    #circuitBg .tr-g { stroke: #c9a227; }

    /* Base-pair rungs between the two strands */
    #circuitBg .rung { stroke-width: 1; opacity: 0.10; }
    #circuitBg .rung-c { stroke: #00e5ff; } #circuitBg .rung-m { stroke: #ff2fb0; }
    #circuitBg .rung-a { stroke: #ff8a1f; } #circuitBg .rung-v { stroke: #a45cff; }

    #circuitBg .pulse {
      fill: none; stroke-width: 1.8; stroke-linecap: round;
      stroke-dasharray: 34 1000; stroke-dashoffset: 1034;
      opacity: 0; filter: drop-shadow(0 0 4px currentColor);
    }
    #circuitBg .p-c { stroke: #00e5ff; color: #00e5ff; } #circuitBg .p-m { stroke: #ff2fb0; color: #ff2fb0; }
    #circuitBg .p-a { stroke: #ff8a1f; color: #ff8a1f; } #circuitBg .p-v { stroke: #a45cff; color: #a45cff; }
    #circuitBg .p-g { stroke: #ffd76a; color: #ffd76a; }

    #circuitBg .pad { opacity: 0.16; }
    #circuitBg .pad-c { fill: #00e5ff; } #circuitBg .pad-m { fill: #ff2fb0; }
    #circuitBg .pad-a { fill: #ff8a1f; } #circuitBg .pad-v { fill: #a45cff; }
    #circuitBg .pad-g { fill: #c9a227; }

    /* X-ray layer: the same board again, fully lit, revealed only where a
       travelling spotlight passes. Reads as light shining through the board. */
    #circuitXray {
      position: absolute; inset: 0; width: 100%; height: 100%;
      opacity: 0; pointer-events: none; transition: opacity .6s ease;
      mask-image: radial-gradient(circle at 50% 50%, #000 0%, rgba(0,0,0,0.65) 22%, transparent 46%);
      -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 0%, rgba(0,0,0,0.65) 22%, transparent 46%);
      mask-size: 190% 120%; -webkit-mask-size: 190% 120%;
      mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat;
    }
    [data-theme="prism"] #circuitXray { opacity: 1; }
    #circuitXray .xr { fill: none; stroke-width: 1.5; opacity: 0.95; stroke-linecap: round; }
    #circuitXray .xr-c { stroke: #7df6ff; } #circuitXray .xr-m { stroke: #ff7ccd; }
    #circuitXray .xr-a { stroke: #ffb264; } #circuitXray .xr-v { stroke: #c99cff; }
    #circuitXray .xr-g { stroke: #ffe08a; }
    #circuitXray .xrung { stroke-width: 1.2; opacity: 0.8; }
    #circuitXray .xrung-c { stroke: #7df6ff; } #circuitXray .xrung-m { stroke: #ff7ccd; }
    #circuitXray .xrung-a { stroke: #ffb264; } #circuitXray .xrung-v { stroke: #c99cff; }
    #circuitXray .xpad { opacity: 1; }
    #circuitXray .xpad-c { fill: #bdfaff; } #circuitXray .xpad-m { fill: #ffb3e2; }
    #circuitXray .xpad-a { fill: #ffd0a0; } #circuitXray .xpad-v { fill: #ddc4ff; }
    #circuitXray .xpad-g { fill: #fff0bb; }

      #circuitBg .pulse { animation-name: trace-fire; animation-timing-function: linear; animation-iteration-count: infinite; }
      @keyframes trace-fire {
        0%   { stroke-dashoffset: 1034; opacity: 0; }
        6%   { opacity: 1; }
        60%  { opacity: 1; }
        72%  { stroke-dashoffset: 0; opacity: 0; }
        100% { stroke-dashoffset: 0; opacity: 0; }
      }
      /* Base pairs fire in sequence down the strand - reads as transcription */
      #circuitBg .rung { animation: rung-read 3.6s ease-in-out infinite; }
      @keyframes rung-read {
        0%, 100% { opacity: 0.08; }
        40%      { opacity: 0.75; filter: drop-shadow(0 0 4px currentColor); }
      }
      #circuitBg .rung-c { color: #00e5ff; } #circuitBg .rung-m { color: #ff2fb0; }
      #circuitBg .rung-a { color: #ff8a1f; } #circuitBg .rung-v { color: #a45cff; }

      #circuitBg .pad { animation: pad-fire 3.6s ease-in-out infinite; }
      @keyframes pad-fire {
        0%, 100% { opacity: 0.14; }
        42%      { opacity: 1; filter: drop-shadow(0 0 5px currentColor); }
      }
      #circuitBg .pad-c { color: #00e5ff; } #circuitBg .pad-m { color: #ff2fb0; }
      #circuitBg .pad-a { color: #ff8a1f; } #circuitBg .pad-v { color: #a45cff; }
      #circuitBg .pad-g { color: #c9a227; }

      [data-theme="prism"] #circuitBg { animation: board-surge 9s ease-in-out infinite; }
      @keyframes board-surge {
        0%, 82%, 100% { opacity: 1; filter: none; }
        88%           { filter: brightness(2.1) saturate(1.3); }
        94%           { filter: brightness(1); }
      }
      [data-theme="prism"] .landing-title { animation: title-charge 9s ease-in-out infinite; }
      @keyframes title-charge {
        0%, 84%, 100% { filter: none; }
        89%           { filter: drop-shadow(0 0 14px rgba(255,215,106,0.55)); }
      }
      [data-theme="prism"] .landing-btn { animation: btn-charge 9s ease-in-out infinite; }
      @keyframes btn-charge {
        0%   { box-shadow: none;                                                             border-color: rgba(201,162,39,0.55); }
        84%  { box-shadow: none;                                                             border-color: rgba(201,162,39,0.55); }
        89%  { box-shadow: 0 0 22px rgba(201,162,39,0.5), inset 0 0 14px rgba(201,162,39,0.2); border-color: rgba(230,198,90,1); }
        95%  { box-shadow: none;                                                             border-color: rgba(201,162,39,0.55); }
        100% { box-shadow: none;                                                             border-color: rgba(201,162,39,0.55); }
      }
      #circuitXray { animation: xray-sweep 14s ease-in-out infinite; }
      @keyframes xray-sweep {
        0%   { mask-position: 10% 8%;  -webkit-mask-position: 10% 8%; }
        22%  { mask-position: 85% 26%; -webkit-mask-position: 85% 26%; }
        45%  { mask-position: 22% 58%; -webkit-mask-position: 22% 58%; }
        68%  { mask-position: 92% 78%; -webkit-mask-position: 92% 78%; }
        86%  { mask-position: 45% 40%; -webkit-mask-position: 45% 40%; }
        100% { mask-position: 10% 8%;  -webkit-mask-position: 10% 8%; }
      }

    .landing-title { font-family: Georgia, "Times New Roman", serif; font-size: 2.6rem; font-weight: 700; color: var(--text-main); letter-spacing: 0.01em; margin-bottom: 12px; text-transform: none; }
    .landing-title span { color: var(--accent-gold); }
    .landing-subtitle { font-size: 0.9rem; color: var(--text-muted); margin-bottom: 40px; font-family: monospace; letter-spacing: 0.15em; font-weight: 700; }
    .landing-btn { padding: 14px 36px; background: var(--accent-gold); color: #0a0a0a; border: 1px solid var(--accent-gold); border-radius: 30px; font-size: 1rem; font-weight: 900; cursor: pointer; transition: all 0.2s; }
    .landing-btn:hover { background: var(--accent-gold-hover); border-color: var(--accent-gold-hover); }

    .sheet-backdrop { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); z-index: 100; align-items: center; justify-content: center; padding: 16px; }
    .sheet-backdrop.open { display: flex; }
    #bulkTierModal.sheet-backdrop { background: rgba(0, 0, 0, 0.2); backdrop-filter: blur(1px); align-items: flex-start; padding-top: 12vh; }
    .sheet-modal { border-radius: 20px; width: 100%; max-width: 440px; padding: 24px; }
    .sheet-modal h3 { font-size: 1.35rem; color: var(--text-main); margin-bottom: 8px; font-family: Georgia, "Times New Roman", serif; text-transform: uppercase; font-weight: 400; letter-spacing: 0.04em; }
    .form-group { margin-bottom: 16px; }
    .form-group label { display: block; font-size: 0.75rem; color: var(--text-muted); margin-bottom: 6px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; }
    .form-group input, .form-group textarea, .form-group select { width: 100%; padding: 12px 14px; border-radius: 10px; border: 1px solid var(--glass-border); background: rgba(0,0,0,0.5); color: var(--text-main); font-size: 0.9rem; transition: all 0.2s; }
    .form-group input:focus, .form-group textarea:focus { outline: none; border-color: var(--accent-gold); }
    .toggle-row { display: flex; align-items: center; justify-content: space-between; padding: 12px 0; border-bottom: 1px solid var(--glass-border); font-size: 0.9rem; font-weight: 600; }
    .toggle-row input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--accent-pink); }
    .modal-actions { display: flex; gap: 10px; margin-top: 20px; flex-wrap: wrap; }
    .btn-primary { flex: 1; padding: 12px; background: var(--accent-gold); color: #0a0a0a; border: none; border-radius: 10px; font-weight: 900; font-size: 0.9rem; cursor: pointer; transition: all 0.2s; }
    .btn-primary:hover { background: var(--accent-gold-hover); }
    .btn-cancel { flex: 1; padding: 12px; background: rgba(0,0,0,0.6); color: var(--text-main); border: 1px solid var(--glass-border); border-radius: 10px; font-weight: 700; cursor: pointer; transition: all 0.2s; }
    .btn-cancel:hover { background: rgba(255,255,255,0.1); }
    .btn-danger { flex: 1; padding: 12px; background: var(--accent-pink-dim); border: 1px solid var(--accent-pink); color: var(--accent-pink); border-radius: 10px; font-weight: 800; cursor: pointer; transition: all 0.2s; }
    .btn-danger:hover { background: var(--accent-pink); color: var(--text-main); text-shadow: none; }

    .tour-tooltip-box { position: fixed; background: var(--accent-gold); backdrop-filter: blur(10px); color: #0a0a0a; padding: 14px 16px; border-radius: 14px; font-size: 0.85rem; font-weight: 900; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.55); z-index: 150; cursor: pointer; display: none; line-height: 1.4; transition: opacity 0.2s, top 0.3s cubic-bezier(0.16, 1, 0.3, 1), left 0.3s cubic-bezier(0.16, 1, 0.3, 1); }
    .tour-tooltip-box::before { content: ""; position: absolute; top: -10px; left: var(--arrow-pos, 50%); transform: translateX(-50%); border-width: 0 10px 10px 10px; border-style: solid; border-color: transparent transparent var(--accent-gold) transparent; transition: left 0.3s cubic-bezier(0.16, 1, 0.3, 1); }
    .tour-tooltip-box.arrow-below::before { top: auto; bottom: -10px; border-width: 10px 10px 0 10px; border-color: var(--accent-gold) transparent transparent transparent; }
    .tour-tooltip-box.no-arrow::before { display: none; }
    .tour-advance-subtext { display: block; font-size: 0.65rem; font-weight: 900; color: rgba(0, 0, 0, 0.6); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 8px; border-top: 1px solid rgba(0, 0, 0, 0.2); padding-top: 6px; }
    .tour-target-active { position: relative; z-index: 151; animation: targetPulse 1.5s infinite !important; }
    /* currentColor, not a literal: the pulse then takes the colour of whatever
       it is highlighting, so every theme gets a correct ring without its own
       copy of this keyframe. */
    @keyframes targetPulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-gold) 90%, transparent); } 70% { box-shadow: 0 0 0 12px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }

    .tour-popover-highlight { border: 1px dashed var(--accent-gold) !important; box-shadow: 0 0 0 3px var(--accent-gold-dim) !important; }

    /* Daily Run mode */
    #dailyRunOverlay { position: fixed; inset: 0; z-index: 300; display: none; flex-direction: column; padding: 20px 16px calc(20px + env(safe-area-inset-bottom)); background: radial-gradient(circle at 50% 0%, color-mix(in srgb, var(--accent-gold) 10%, transparent), transparent 60%), var(--bg-base); overflow-y: auto; }
    #dailyRunOverlay.open { display: flex; }
    .run-header { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-shrink: 0; }
    .run-progress-text { font-family: "Courier New", Courier, monospace; font-weight: 900; font-size: 0.85rem; color: var(--accent-gold); letter-spacing: 0.1em; }
    .btn-exit-run { background: transparent; border: 1px solid var(--glass-border); color: var(--text-muted); border-radius: 20px; padding: 6px 14px; font-size: 0.75rem; font-weight: 800; cursor: pointer; }
    .btn-exit-run:hover { border-color: var(--accent-pink); color: var(--accent-pink); }
    .run-progress-bar { height: 5px; background: rgba(255,255,255,0.08); border-radius: 3px; margin-top: 12px; overflow: hidden; flex-shrink: 0; }
    .run-progress-fill { height: 100%; background: var(--accent-gold); width: 0%; transition: width 0.35s ease; }
    /* justify-content: center, not plain center. .run-card sits
       inside #dailyRunOverlay's overflow-y: auto, and plain "center" on a
       flex item taller than its box centers by pushing the excess equally
       above AND below - the part pushed above the container's scrollTop:0
       line becomes permanently unreachable, since scroll position can't go
       negative. That's exactly what happened on a long catalog note: the
       avatar/name/badges/redeem/balance block (everything before the
       notes) got shoved out of scroll range, leaving only notes + buttons
       visible with no way to see which platform the card was even for.
       "safe" falls back to start-alignment - reachable by scrolling from
       the top - whenever the content doesn't fit, and behaves exactly like
       plain "center" whenever it does. */
    .run-card { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: safe center; text-align: center; padding: 24px 18px; margin: 18px 0; border-radius: 20px; min-height: 0; }
    .run-avatar { width: 84px; height: 84px; border-radius: 50%; border: 1px solid var(--accent-gold); background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center; font-family: "Courier New", Courier, monospace; font-weight: 900; font-size: 1.8rem; color: var(--accent-gold); margin-bottom: 16px; }
    .run-name { font-size: 1.5rem; font-weight: 900; color: var(--text-main); margin-bottom: 10px; }
    .run-badges { display: flex; gap: 8px; justify-content: center; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
    .run-redeem { color: var(--accent-gold); font-weight: 800; font-size: 0.9rem; margin-bottom: 10px; }
    /* Capped and independently scrollable on purpose. Some catalog notes
       run to several paragraphs (see data/catalog.js) - uncapped, this
       block could grow taller than .run-card's own flex-allocated height,
       and since .run-card has no overflow control of its own, that excess
       just paints past the box into whatever sits below it in the
       column - the undo bar, the balance bar, the collect button - which
       is exactly what made them "impossible to press" on a long-note
       platform. A left-aligned, bounded, scrollable block can't grow past
       its own box no matter how long the note is, so nothing below it can
       ever be covered again. Left-aligned rather than inheriting
       .run-card's centered text too - centered long-form paragraphs are
       hard to track line to line; this reads like actual prose. */
    .run-notes { opacity: 0.85; font-size: 0.88rem; line-height: 1.5; max-width: 460px; max-height: 30vh; overflow-y: auto; text-align: left; scrollbar-width: thin; }
    .run-bestgames { margin-top: 18px; text-align: left; width: 100%; max-width: 460px; border-top: 1px solid var(--glass-border); padding-top: 14px; font-size: 0.75rem; }
    /* position:relative here (and on .run-balance-bar / .run-actions
       below) is defensive, not decorative. .run-card carries .glass-panel,
       and at least one theme (Amped) gives .glass-panel position:relative
       for its own reasons (an ::before sweep needs a positioned ancestor
       to clip against). A positioned element paints ABOVE its later,
       non-positioned static siblings regardless of DOM order - so without
       this, .run-card would paint over these three buttons on any theme
       that ever makes it positioned, independent of whatever content-
       overflow fix .run-notes above has. Making these three positioned
       too puts everyone back in the same stacking bucket, where normal DOM
       order (all three come after .run-card) decides the paint order
       again - the buttons stay on top the way a reader would expect. */
    .run-undo-bar, .run-balance-bar, .run-actions { position: relative; }
    /* Persistent undo, not a toast - hidden by default via [hidden];
       showRunUndoBar()/hideRunUndoBar() in the main script toggle it.
       Sits right above .run-actions (same width/centering) so it reads
       as "attached to" the collect button below it. */
    .run-undo-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; max-width: 460px; align-self: center; flex-shrink: 0; margin-bottom: 10px; padding: 10px 14px; border-radius: 12px; background: rgba(0,0,0,0.5); border: 1px solid var(--glass-border); font-size: 0.82rem; color: var(--text-muted); }
    /* [hidden] is a UA default of display:none, and the display:flex
       above outranks it - so without this the bar stayed on screen for
       the whole run with empty text and a dead UNDO button, which is
       exactly what it looked like in practice. Same fix (and same
       cause) as .redeem-editor[hidden] further down. */
    .run-undo-bar[hidden] { display: none; }
    .run-undo-btn { flex-shrink: 0; background: transparent; border: 1px solid var(--accent-cyan); color: var(--accent-cyan); border-radius: 8px; padding: 6px 12px; font-size: 0.75rem; font-weight: 800; letter-spacing: 0.05em; cursor: pointer; }
    .run-undo-btn:active { transform: scale(0.95); }
    /* Wallet balance entry. Two placements, one visual language: a
       compact block on the run card, and a sibling of the undo bar
       (same width/centering, so the pair reads as one unit sitting
       above the collect button). */
    .run-balance-bar { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 460px; align-self: center; flex-shrink: 0; margin-bottom: 10px; padding: 10px 14px; border-radius: 12px; background: rgba(0,0,0,0.5); border: 1px solid var(--glass-border); }
    .run-balance-bar[hidden] { display: none; }
    .run-balance-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 0.78rem; font-weight: 800; color: var(--accent-cyan); letter-spacing: 0.03em; }
    .run-balance-hint { font-size: 0.65rem; font-weight: 600; letter-spacing: 0.04em; color: var(--text-muted); text-transform: uppercase; }
    .run-balance { width: 100%; max-width: 460px; margin-bottom: 10px; }
    .run-balance-row { display: flex; align-items: center; gap: 8px; }
    .run-balance-label { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); flex-shrink: 0; }
    .run-balance-input { flex: 1; min-width: 0; background: rgba(0,0,0,0.5); border: 1px solid var(--glass-border); color: var(--text-main); padding: 8px 10px; border-radius: 8px; font-family: "Courier New", monospace; font-size: 0.85rem; }
    .run-balance-input:focus { outline: none; border-color: var(--accent-gold); }
    .run-balance-btn { flex-shrink: 0; background: transparent; border: 1px solid var(--accent-green); color: var(--accent-green); border-radius: 8px; padding: 8px 14px; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.05em; cursor: pointer; }
    .run-balance-btn:active { transform: scale(0.95); }
    .run-actions { display: flex; flex-direction: column; gap: 10px; width: 100%; max-width: 460px; align-self: center; flex-shrink: 0; }
    .btn-run-collect { padding: 18px; font-size: 1.15rem; font-weight: 900; border: none; border-radius: 14px; cursor: pointer; background: var(--accent-gold); color: #0a0a0a; box-shadow: 0 6px 24px rgba(0,0,0,0.5); }
    .btn-run-collect:active { transform: scale(0.98); }
    .btn-skip { background: transparent; color: var(--text-muted); border: none; padding: 12px; font-size: 0.9rem; font-weight: 700; cursor: pointer; text-transform: uppercase; letter-spacing: 0.08em; }
    .btn-skip:hover { color: var(--text-main); }
    .btn-start-run { width: 100%; padding: 14px; margin-bottom: 14px; border-radius: 12px; font-size: 0.95rem; font-weight: 900; cursor: pointer; background: rgba(0,0,0,0.5); border: 1px solid var(--accent-green); color: var(--accent-green); letter-spacing: 0.05em; }
    .btn-start-run:hover:not(:disabled) { background: var(--accent-green-dim); }
    .btn-start-run:disabled { border-color: var(--glass-border); color: var(--text-dim); text-shadow: none; box-shadow: none; cursor: default; }
    .empty-state { margin: 10px 0; padding: 28px 16px; border-radius: 16px; text-align: center; color: var(--text-muted); }
    .empty-state-title { margin-bottom: 6px; color: var(--text-main); font-size: 1.05rem; font-weight: 900; }
    .empty-state p:not(.empty-state-title) { font-size: 0.8rem; line-height: 1.45; }
    .empty-state-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 18px; }
    .empty-state-actions button { flex: 1 1 140px; min-width: 0; }

    /* Backup & restore */
    .backup-controls { display: flex; gap: 10px; margin-top: 16px; }
    .backup-controls .btn-dock { flex: 1; max-width: 100%; padding: 12px 8px; font-size: 0.8rem; }
    .backup-helper { color: var(--text-muted); font-size: 0.72rem; text-align: center; margin-top: 10px; line-height: 1.5; }

    /* Stats modal */
    .stats-section { margin-bottom: 22px; }
    .stats-section h4 { color: var(--accent-gold); border-bottom: 1px solid var(--glass-border); padding-bottom: 6px; margin-bottom: 12px; font-size: 0.8rem; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 800; }
    .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 10px; }
    .stat-box { background: rgba(0,0,0,0.35); border: 1px solid var(--glass-border); border-radius: 10px; padding: 14px 8px; text-align: center; }
    .stat-value { font-size: 1.5rem; font-weight: 900; margin-bottom: 4px; font-family: "Courier New", Courier, monospace; }
    .stat-label { font-size: 0.65rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; }
    .drops-note { font-size:0.72rem; line-height:1.5; color:var(--text-muted); background:rgba(201,162,39,0.07); border:1px solid rgba(201,162,39,0.3); border-left:3px solid var(--accent-gold); padding:11px 12px; border-radius:4px; margin-bottom:14px; }
    .drops-toggle { display:flex; align-items:center; gap:8px; font-size:0.74rem; color:var(--text-muted); cursor:pointer; }
    .drops-toggle input { width:16px; height:16px; accent-color:var(--accent-gold); }
    .drop-row { display:flex; align-items:center; gap:10px; padding:10px 0; border-bottom:1px solid var(--glass-border); }
    .drop-main { flex:1; min-width:0; }
    .drop-name { font-size:0.84rem; font-weight:700; color:var(--text-main); margin-bottom:2px; }
    .drop-url { font-size:0.66rem; color:var(--text-dim); font-family:monospace; overflow:hidden; text-overflow:ellipsis; }
    .drop-tag { font-size:0.58rem; font-weight:700; padding:1px 6px; border-radius:3px; background:rgba(255,255,255,0.06); border:1px solid var(--glass-border); color:var(--text-muted); letter-spacing:0.04em; }
    .drop-tag.unknown { color:var(--accent-pink); border-color:var(--accent-pink); }
    .drops-hidden { font-size:0.72rem; color:var(--text-dim); text-align:center; padding:14px 8px 4px; line-height:1.5; }
    .ledger-note { font-size:0.72rem; line-height:1.5; color:var(--text-muted); background:rgba(61,135,103,0.07); border:1px solid rgba(61,135,103,0.3); border-left:3px solid var(--accent-green); padding:11px 12px; border-radius:4px; margin-bottom:16px; }
    .ledger-ytd { font-size:0.72rem; color:var(--text-muted); text-align:center; font-family:"Courier New",monospace; margin-bottom:16px; }
    .ledger-add { background:rgba(0,0,0,0.3); border:1px solid var(--glass-border); border-radius:8px; padding:13px; margin-bottom:16px; }
    .ledger-add-head, .ledger-list-head { font-size:0.62rem; font-weight:800; letter-spacing:0.18em; text-transform:uppercase; color:var(--accent-gold); margin-bottom:10px; }
    .ledger-row { display:flex; flex-wrap:wrap; align-items:center; gap:10px; padding:9px 0; border-bottom:1px solid var(--glass-border); }
    .ledger-row-main { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
    .ledger-plat { font-size:0.82rem; font-weight:700; color:var(--text-main); }
    .ledger-meta { font-size:0.68rem; color:var(--text-dim); }
    .ledger-amt { font-family:"Courier New",monospace; font-weight:800; font-size:0.84rem; flex-shrink:0; }
    .ledger-amt.purchase { color:var(--accent-pink); } .ledger-amt.redemption { color:var(--accent-green); }
    /* Shared look for every control in the add-entry form. Was repeated
       inline on each one; it needs to be a class now that fields swap in
       and out by entry type. */
    .led-field { background:rgba(0,0,0,0.5); border:1px solid var(--glass-border); color:var(--text-main); padding:9px; border-radius:8px; font-family:inherit; font-size:0.82rem; min-width:0; }
    .led-row { display:flex; gap:8px; margin-bottom:10px; }
    .led-hint { font-size:0.68rem; line-height:1.45; color:var(--text-dim); margin:-2px 0 10px; }
    /* Which routes the money actually came back through. */
    .payout-breakdown { margin:-6px 0 16px; }
    .payout-breakdown-head { font-size:0.6rem; font-weight:800; letter-spacing:0.16em; text-transform:uppercase; color:var(--text-dim); text-align:center; margin-bottom:7px; }
    .payout-chips { display:flex; flex-wrap:wrap; gap:6px; justify-content:center; }
    .payout-chip { font-size:0.68rem; color:var(--text-muted); background:rgba(0,0,0,0.35); border:1px solid var(--glass-border); border-radius:999px; padding:4px 10px; font-family:"Courier New",monospace; }
    .payout-chip strong { color:var(--text-main); font-weight:700; }
    .led-date { display:flex; flex-direction:column; gap:4px; flex:1; min-width:0; }
    .led-date > span { font-size:0.6rem; font-weight:800; letter-spacing:0.14em; text-transform:uppercase; color:var(--text-dim); }
    .led-date-note { flex:1; align-self:flex-end; font-size:0.64rem; line-height:1.35; color:var(--text-dim); padding-bottom:9px; }
    /* Request -> approved -> paid, tracked per redemption. The chip both
       reports where it sits and opens the dates for editing, since the
       money almost always lands days after the row was created. */
    .ledger-track { flex-basis:100%; display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:7px; }
    .track-chip { font-family:inherit; font-size:0.64rem; font-weight:700; letter-spacing:0.04em; border-radius:999px; padding:3px 10px; cursor:pointer; background:rgba(0,0,0,0.35); }
    .track-chip.pending { border:1px solid rgba(255,193,7,0.5); color:var(--accent-gold); }
    .track-chip.approved { border:1px solid color-mix(in srgb, var(--accent-orange) 55%, transparent); color:var(--accent-orange); }
    .track-chip.paid { border:1px solid rgba(61,135,103,0.5); color:var(--accent-green); }
    .track-quick { font-family:inherit; font-size:0.64rem; font-weight:700; background:none; border:none; color:var(--text-dim); text-decoration:underline; cursor:pointer; padding:3px 2px; }
    .track-quick:hover { color:var(--accent-green); }
    .redeem-editor[hidden] { display:none; }
    .redeem-editor { flex-basis:100%; display:flex; align-items:flex-end; gap:8px; background:rgba(0,0,0,0.3); border:1px solid var(--glass-border); border-radius:8px; padding:10px; margin-top:4px; }
    .redeem-editor .led-field { padding:7px; font-size:0.76rem; }
    .track-save { font-family:inherit; font-size:0.64rem; font-weight:800; letter-spacing:0.1em; background:var(--accent-green); border:none; color:#0B0B0B; border-radius:6px; padding:8px 11px; cursor:pointer; flex-shrink:0; }
    /* Payout speed: the point of collecting those dates. */
    .payout-speed { margin:0 0 16px; }
    .speed-empty { font-size:0.68rem; line-height:1.45; color:var(--text-dim); text-align:center; }
    .speed-headline { text-align:center; font-size:0.76rem; color:var(--text-muted); margin-bottom:9px; }
    .speed-headline strong { color:var(--accent-green); font-family:"Courier New",monospace; font-size:0.92rem; }
    .speed-sub { display:block; font-size:0.64rem; color:var(--text-dim); margin-top:3px; }
    .speed-rows { display:flex; flex-direction:column; gap:4px; }
    .speed-row { display:flex; align-items:center; gap:8px; font-size:0.7rem; padding:3px 2px; border-bottom:1px solid rgba(255,255,255,0.04); }
    .speed-plat { flex:1; min-width:0; color:var(--text-main); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
    .speed-days { font-family:"Courier New",monospace; font-weight:800; color:var(--accent-green); }
    .speed-n { font-size:0.6rem; color:var(--text-dim); min-width:46px; text-align:right; }
    .speed-n.thin { color:var(--accent-gold); opacity:0.75; }
    .payout-chip em { font-style:normal; color:var(--accent-green); }
    /* Ledger, promoted: top of settings rather than buried in the button
       stack, and carrying its own net so it reads as a figure you have
       rather than another place to go. */
    .settings-ledger-card { width:100%; display:flex; align-items:center; gap:12px; text-align:left; background:rgba(61,135,103,0.08); border:1px solid rgba(61,135,103,0.45); border-left:3px solid var(--accent-green); border-radius:8px; padding:12px 13px; margin-bottom:16px; cursor:pointer; font-family:inherit; transition:background 0.2s, border-color 0.2s; }
    .settings-ledger-card:hover { background:rgba(61,135,103,0.16); border-color:var(--accent-green); }
    .slc-icon { display:inline-flex; align-items:center; justify-content:center; width:22px; height:22px; border:1px solid currentColor; border-radius:4px; font-size:0.9rem; font-weight:800; line-height:1; color:var(--accent-green); flex-shrink:0; }
    .slc-text { flex:1; min-width:0; display:flex; flex-direction:column; gap:3px; }
    .slc-text strong { font-size:0.8rem; font-weight:800; letter-spacing:0.12em; color:var(--accent-green); }
    .slc-sub { font-size:0.68rem; line-height:1.4; color:var(--text-muted); }
    .slc-net { font-family:"Courier New",monospace; font-weight:800; font-size:0.88rem; flex-shrink:0; }
    /* Permanent seat next to the gear, on every tab. */
    .top-bar-actions { display:flex; align-items:center; gap:8px; }
    .btn-ledger-quick { display:flex; align-items:center; gap:6px; background:transparent; border:none; color:var(--text-muted); font-family:inherit; cursor:pointer; padding:4px; transition:all 0.2s; }
    .btn-ledger-quick:hover { color:var(--accent-green); }
    .ledger-quick-mark { display:inline-flex; align-items:center; justify-content:center; width:19px; height:19px; border:1px solid currentColor; border-radius:4px; font-size:0.76rem; font-weight:800; line-height:1; }
    .ledger-quick-net { font-family:"Courier New",monospace; font-weight:800; font-size:0.72rem; }
    .icon-x { background:none; border:none; color:var(--text-dim); cursor:pointer; font-size:0.8rem; padding:2px 4px; flex-shrink:0; }
    .icon-x:hover { color:var(--accent-pink); }
    .guide-sec { border:1px solid var(--glass-border); border-radius:8px; margin-bottom:9px; overflow:hidden; }
    .guide-head { width:100%; background:transparent; border:none; padding:13px 12px; display:flex; align-items:center; gap:11px; cursor:pointer; color:var(--text-main); font-family:inherit; text-align:left; }
    .guide-num { font-family:"Courier New",monospace; font-size:0.68rem; color:var(--accent-gold); flex-shrink:0; }
    .guide-title { flex:1; font-size:0.86rem; font-weight:800; }
    .guide-chev { color:var(--text-dim); font-size:0.8rem; transition:transform .22s; flex-shrink:0; }
    .guide-sec.open .guide-chev { transform:rotate(180deg); }
    .guide-body { display:none; padding:0 12px 12px; }
    .guide-sec.open .guide-body { display:block; animation:fadeIn .2s ease-in-out; }
    .guide-item { padding:10px 0; border-top:1px solid var(--glass-border); }
    .guide-item-h { font-size:0.8rem; font-weight:800; color:var(--accent-gold); margin-bottom:4px; }
    .guide-item-b { font-size:0.78rem; line-height:1.55; color:var(--text-muted); }
    .guide-item-b b { color:var(--text-main); }
    .guide-item-b code { background:rgba(0,0,0,0.45); padding:1px 5px; border-radius:3px; font-size:0.72rem; color:var(--accent-cyan); }
    .calc-warn { font-size:0.72rem; line-height:1.5; color:var(--text-muted); background:rgba(255,138,31,0.07); border:1px solid rgba(255,138,31,0.3); border-left:3px solid var(--accent-orange); padding:11px 12px; border-radius:4px; margin-bottom:16px; }
    .calc-warn strong { color: var(--accent-orange); }
    .calc-note { font-size:0.7rem; color:var(--text-dim); line-height:1.5; margin-top:14px; padding-top:12px; border-top:1px solid var(--glass-border); }
    .heat-grid { display:flex; gap:3px; justify-content:space-between; }
    .heat-col { display:flex; flex-direction:column; gap:3px; flex:1; }
    .heat-cell { width:100%; aspect-ratio:1; border-radius:2px; background:rgba(255,255,255,0.05); }
    .heat-cell.l1 { background:rgba(255,138,31,0.28); } .heat-cell.l2 { background:rgba(255,138,31,0.5); }
    .heat-cell.l3 { background:rgba(255,180,60,0.72); } .heat-cell.l4 { background:var(--accent-gold); }
    .heat-cell.lf { background:transparent; }
    .heat-legend { display:flex; align-items:center; justify-content:space-between; margin-top:8px; font-size:0.62rem; color:var(--text-dim); }
    .heat-key { display:flex; gap:3px; }
    .heat-key .heat-cell { width:9px; height:9px; aspect-ratio:auto; }
    .stats-list { list-style: none; padding: 0; margin: 0; }
    .stats-list-item { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 9px 0; border-bottom: 1px dashed var(--glass-border); font-size: 0.85rem; }
    .stats-list-item:last-child { border-bottom: none; }
    .stale-name { color: var(--text-main); font-weight: 700; }
    .stale-warning { color: var(--accent-pink); font-size: 0.78rem; white-space: nowrap; }
    .btn-close-x { background: transparent; border: 1px solid var(--glass-border); color: var(--text-muted); border-radius: 50%; width: 32px; height: 32px; flex: 0 0 auto; cursor: pointer; font-size: 0.9rem; font-weight: 800; padding: 0; }
    .btn-close-x:hover { border-color: var(--accent-pink); color: var(--accent-pink); }

    /* PWA install */
    .pwa-install-container { margin-top: 18px; border-top: 1px solid var(--glass-border); padding-top: 14px; }

    /* Referral manager */
    .btn-share { background: transparent; border: 1px solid var(--accent-cyan); color: var(--accent-cyan); padding: 6px 10px; border-radius: 8px; font-size: 0.68rem; font-weight: 800; text-transform: uppercase; cursor: pointer; flex-shrink: 0; }
    .btn-share:hover { background: var(--accent-gold-dim); color: var(--accent-gold); }

    /* Quick cooldown editing */
    .cooldown-chip { display: inline-flex; align-items: center; justify-content: center; font-size: 0.68rem; font-weight: 700; color: var(--text-muted); background: transparent; border: 1px solid var(--glass-border); border-radius: 12px; padding: 1px 7px; margin-left: 6px; cursor: pointer; user-select: none; transition: all 0.2s; vertical-align: middle; font-family: "Courier New", Courier, monospace; }
    .cooldown-chip:hover { border-color: var(--accent-gold); color: var(--accent-gold); }
    .cooldown-chip:active { transform: scale(0.92); }
    .cooldown-chip.flash { border-color: var(--accent-gold); color: var(--accent-gold); background: var(--accent-gold-dim); }
    .run-cooldown-row { display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 0.78rem; color: var(--text-muted); margin-bottom: 10px; }

    /* Notifications */
    .notify-settings { margin-top: 18px; border-top: 1px solid var(--glass-border); padding-top: 14px; }
    .notify-settings h4 { margin: 0 0 10px; font-size: 0.8rem; color: var(--accent-gold); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 800; }
    .notify-message { font-size: 0.72rem; margin-bottom: 10px; line-height: 1.5; color: var(--text-muted); }
    .notify-error { color: var(--accent-pink); font-weight: 700; }
    .time-inputs { display: flex; gap: 12px; margin-top: 12px; }
    .time-inputs label { display: flex; flex-direction: column; font-size: 0.68rem; color: var(--text-muted); gap: 5px; flex: 1; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; }
    .time-inputs input[type="time"] { background: rgba(0,0,0,0.5); border: 1px solid var(--glass-border); color: var(--text-main); padding: 9px; border-radius: 8px; font-family: inherit; font-size: 0.85rem; }
    .time-inputs input[type="time"]:focus { outline: none; border-color: var(--accent-cyan); }

    /* Review & prune */
    .prune-card { background: rgba(0,0,0,0.35); border: 1px solid var(--glass-border); border-radius: 12px; padding: 16px; }
    .prune-title { font-size: 1.15rem; font-weight: 900; color: var(--text-main); margin: 0 0 4px; }
    .prune-flagged-label { font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent-orange); font-weight: 800; margin: 12px 0 8px; }
    .prune-reasons { margin: 0; padding: 0; list-style: none; }
    .prune-reasons li { font-size: 0.85rem; color: var(--text-main); margin-bottom: 7px; display: flex; align-items: flex-start; line-height: 1.4; }
    .prune-reasons li::before { content: '\2022'; color: var(--accent-orange); margin-right: 8px; font-weight: 900; flex-shrink: 0; }
    .prune-warning { color: var(--accent-pink); font-size: 0.78rem; margin-top: 14px; padding: 11px; background: var(--accent-pink-dim); border: 1px solid var(--accent-pink); border-radius: 8px; line-height: 1.45; }
    .prune-summary-grid { display: flex; justify-content: center; gap: 10px; margin-top: 20px; }
    .prune-summary-item { padding: 16px 10px; text-align: center; flex: 1; border-radius: 10px; background: rgba(0,0,0,0.35); border: 1px solid var(--glass-border); }
    .prune-summary-item .val { font-size: 1.7rem; font-weight: 900; margin-bottom: 4px; font-family: "Courier New", Courier, monospace; }
    .prune-note { font-size: 0.72rem; color: var(--text-muted); line-height: 1.5; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--glass-border); }

    /* Theme picker */
    .theme-settings { margin-top: 18px; border-top: 1px solid var(--glass-border); padding-top: 14px; }
    .theme-settings h4 { margin: 0 0 10px; font-size: 0.8rem; color: var(--accent-cyan); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 800; }
    .theme-grid { display: flex; flex-direction: column; gap: 10px; }
    .theme-card { background: rgba(0,0,0,0.35); border: 1px solid var(--glass-border); border-radius: 12px; padding: 12px 14px; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 12px; transition: border-color .2s, background .2s; }
    .theme-card.active { border-color: var(--accent-green); background: rgba(0,0,0,0.5); }
    .theme-info { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
    .theme-name { font-size: 0.9rem; color: var(--text-main); font-weight: 800; }
    .theme-name .active-tag { font-size: 0.6rem; color: var(--accent-green); margin-left: 8px; letter-spacing: 0.08em; }
    .theme-desc { font-size: 0.72rem; color: var(--text-muted); line-height: 1.4; }
    .theme-swatches { display: flex; gap: 4px; flex-shrink: 0; }
    /* ---------- Refinement layer (applies to every theme) ---------- */

    /* Theme switches crossfade instead of snapping. Scoped to color-ish
       properties so layout changes stay instant. */
    body, .glass-panel, .ledger-card, .catalog-item-row, .sheet-modal,
    .nav-tab, .filter-btn, .btn-open, .btn-primary, .btn-dock, .tier-badge,
    .casino-avatar, .res-brief, .res-ext-link, .hero-ring-circle, .docked-footer {
      transition: background-color .45s ease, background-image .45s ease,
                  border-color .45s ease, color .45s ease, box-shadow .45s ease;
    }

    /* Cards arrive with a subtle stagger rather than appearing all at once. */
      .ledger-card-wrapper { animation: card-rise .34s cubic-bezier(.22,1,.36,1) backwards; }
      .ledger-card-wrapper:nth-child(1) { animation-delay: .01s; }
      .ledger-card-wrapper:nth-child(2) { animation-delay: .04s; }
      .ledger-card-wrapper:nth-child(3) { animation-delay: .07s; }
      .ledger-card-wrapper:nth-child(4) { animation-delay: .10s; }
      .ledger-card-wrapper:nth-child(5) { animation-delay: .13s; }
      .ledger-card-wrapper:nth-child(6) { animation-delay: .16s; }
      .ledger-card-wrapper:nth-child(n+7) { animation-delay: .18s; }
      @keyframes card-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

      /* Modals rise into place. */
      .sheet-backdrop.open .sheet-modal { animation: sheet-rise .3s cubic-bezier(.22,1,.36,1); }
      @keyframes sheet-rise { from { opacity: 0; transform: translateY(18px) scale(.985); } to { opacity: 1; transform: none; } }

      /* Full-screen run overlay. */
      #dailyRunOverlay.open .run-card { animation: card-rise .32s cubic-bezier(.22,1,.36,1); }

    /* Springy press feedback on every primary control. */
    .btn-open, .btn-primary, .btn-dock, .btn-cancel, .btn-danger,
    .nav-tab, .filter-btn, .sort-trigger-btn, .btn-share, .theme-card,
    .res-ext-link, .btn-run-collect, .btn-start-run, .sort-option-btn {
      transition: transform .13s cubic-bezier(.34,1.56,.64,1),
                  background-color .25s ease, border-color .25s ease,
                  box-shadow .25s ease, color .25s ease;
    }
    .btn-open:active, .btn-primary:active, .btn-dock:active, .btn-cancel:active,
    .btn-danger:active, .nav-tab:active, .filter-btn:active, .sort-trigger-btn:active,
    .btn-share:active, .theme-card:active, .res-ext-link:active,
    .btn-run-collect:active, .btn-start-run:active, .sort-option-btn:active {
      transform: scale(.965);
    }

    /* Tighter, more deliberate typography. */
    .casino-name { letter-spacing: -0.01em; }
    .hero-details h2 { letter-spacing: -0.015em; }
    .sheet-modal h3 { letter-spacing: 0.02em; }

    /* Scrollbars in modals: thin and unobtrusive rather than default chrome. */
    .sheet-modal ::-webkit-scrollbar, .sheet-modal *::-webkit-scrollbar { width: 3px; }
    .sheet-modal *::-webkit-scrollbar-track { background: transparent; }
    .sheet-modal *::-webkit-scrollbar-thumb { background: var(--glass-border); border-radius: 3px; }

    /* Motion control. Animations now run by default; this switch turns them
       off. JS sets data-motion="off" when the OS asks for reduced motion,
       unless the user has explicitly overridden that in Settings. */
    html[data-motion="off"] *,
    html[data-motion="off"] *::before,
    html[data-motion="off"] *::after {
      animation: none !important;
      transition: none !important;
    }

    /* Compact view: strips the list down for large decks */
    body.dense .ledger-card { padding: 7px 10px; }
    body.dense .casino-avatar { width: 26px; height: 26px; font-size: 0.62rem; }
    body.dense .card-left { gap: 9px; }
    body.dense .casino-name { font-size: 0.86rem; }
    body.dense .tier-badge, body.dense .type-badge { font-size: 0.55rem; padding: 1px 5px; }
    body.dense .card-status { font-size: 0.68rem; }
    body.dense .btn-open { padding: 5px 12px; font-size: 0.72rem; }
    body.dense .btn-check, body.dense .btn-share { padding: 4px 8px; font-size: 0.68rem; }
    body.dense .btn-dots { font-size: 0.95rem; padding: 2px 5px; }
    body.dense .game-list { gap: 6px; }
    body.dense .ready-at { display: none; }
    body.dense .cooldown-chip { font-size: 0.6rem; padding: 0 5px; }
    #btnDense.on { border-color: var(--accent-gold); color: var(--accent-gold); }

    .next-batch { color: var(--accent-gold); font-size: 0.72rem; margin-top: 5px; font-family: "Courier New", monospace; letter-spacing: 0.02em; }
    .ledger-card.swipe-collect { box-shadow: inset 4px 0 0 var(--accent-green); }
    .ledger-card.swipe-snooze { box-shadow: inset -4px 0 0 var(--accent-orange); }
    .cash-wrap { margin-bottom: 9px; }
    .cash-head { display:flex; justify-content:space-between; font-size:0.7rem; color:var(--text-muted); margin-bottom:4px; font-family:"Courier New",monospace; }
    .cash-ready { color: var(--accent-green); font-weight:800; }
    .cash-bar { height:5px; background:rgba(0,0,0,0.45); border:1px solid var(--glass-border); border-radius:3px; overflow:hidden; }
    .cash-fill { height:100%; background:linear-gradient(90deg,var(--accent-orange),var(--accent-gold)); transition:width .4s ease; }
    .cash-fill.done { background:linear-gradient(90deg,var(--accent-green),#9dffd4); }
    /* A bar along the bottom edge rather than a tint filling part of the
       card. As a full-height wash it read as a rendering fault - every
       card looked like it had a lighter rectangle stopping at a random
       point, and no two stopped in the same place. Same information,
       now clearly a progress bar. */
    .cd-fill { position:absolute; left:0; bottom:0; height:3px; pointer-events:none; z-index:0;
      background: linear-gradient(90deg, rgba(255,138,31,0.5), rgba(255,138,31,0.9));
      transition: width .6s linear; }
    .ledger-card.is-ready .cd-fill { display:none; }
    .card-left, .card-actions { position: relative; z-index: 1; }
    .user-note { background: rgba(255,138,31,0.10); border-left: 2px solid var(--accent-orange); padding: 7px 10px; border-radius: 4px; margin-bottom: 8px; font-size: 0.78rem; }
    .user-note strong { color: var(--accent-orange); }
    .tag-pill { display:inline-block; font-size:0.62rem; font-weight:700; padding:2px 7px; margin-right:4px; border-radius:3px; background:rgba(255,255,255,0.06); border:1px solid var(--glass-border); color:var(--text-muted); }
    .tag-chip.active { border-color: var(--accent-orange); color: var(--accent-orange); background: rgba(255,138,31,0.12); }
    /* Pinned to the avatar's corner rather than sitting inline in the
       title row - inline, it was one more item for that flex-wrap row
       to fit, so a platform with a streak silently got a taller card
       than one without (wrapped to a second line once name+tier+LIVE+
       streak didn't fit one line). A corner badge can't affect row
       height at all, so every card in the list stays the same size
       whether or not it happens to be showing a streak. */
    .avatar-wrap { position: relative; flex-shrink: 0; }
    .streak-badge {
      position: absolute; top: -5px; right: -7px; z-index: 2;
      font-size: 0.6rem; font-weight: 800; padding: 1px 5px; border-radius: 8px;
      background: var(--accent-orange); color: #1a0f00;
      border: 1px solid rgba(0,0,0,0.4);
      box-shadow: 0 1px 4px rgba(0,0,0,0.5);
      letter-spacing: 0.02em; line-height: 1.4;
    }
    /* "Zz" instead of the alarm-clock emoji that used to sit here: that
       glyph has no text presentation, so it rendered in full colour next
       to the plain checkmark and dots beside it and read as a sticker on
       the card. Letters need a touch more tracking and a slightly
       smaller size than the single glyph did. */
    .btn-snooze { font-weight: 800; letter-spacing: 0.04em; }
    .btn-snooze:hover { border-color: var(--accent-orange); color: var(--accent-orange); }
    body.dense .streak-badge { font-size: 0.5rem; padding: 0 4px; top: -3px; right: -4px; }
    .ready-at { color: var(--text-dim); font-size: 0.7rem; font-family: "Courier New", monospace; }
    .btn-check { background: transparent; border: 1px solid var(--glass-border); color: var(--text-muted); border-radius: 8px; padding: 7px 10px; font-size: 0.9rem; cursor: pointer; flex-shrink: 0; line-height: 1; transition: all 0.2s ease; }
    .btn-check:hover { border-color: var(--accent-green); color: var(--accent-green); }
    #toast { position: fixed; left: 50%; bottom: 96px; transform: translateX(-50%) translateY(220%); opacity: 0; pointer-events: none; background: rgba(20,22,18,0.97); border: 1px solid var(--glass-border); color: var(--text-main); padding: 12px 14px; border-radius: 10px; z-index: 400; display: flex; align-items: center; gap: 14px; font-size: 0.85rem; box-shadow: 0 10px 30px rgba(0,0,0,0.7); transition: transform .28s cubic-bezier(.22,1,.36,1), opacity .2s ease; max-width: calc(100% - 32px); }
    #toast.show { transform: translateX(-50%) translateY(0); opacity: 1; pointer-events: auto; }
    #toast .undo { background: transparent; border: 1px solid var(--accent-gold); color: var(--accent-gold); border-radius: 6px; padding: 6px 12px; font-weight: 800; font-size: 0.75rem; cursor: pointer; letter-spacing: 0.06em; flex-shrink: 0; }

    .theme-swatch { width: 15px; height: 15px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.25); }

    /* Resources - three cards with one job each: a read-first cheat
       sheet, a separate UI-icon glossary, and outbound links grouped by
       kind (a section label above each group, not a repeated badge
       inside every identical-looking tile). */
    .res-brief { border-radius: 14px; padding: 18px; margin-bottom: 16px; }
    .res-brief-label { font-size: 0.62rem; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: var(--accent-gold); margin-bottom: 10px; }
    .res-brief-lead { font-size: 0.88rem; line-height: 1.55; color: var(--text-main); margin-bottom: 14px; }
    .tactic-list { display: flex; flex-direction: column; }
    .tactic-row { display: grid; grid-template-columns: 26px 1fr; grid-template-rows: auto auto; gap: 0 12px; padding: 11px 0; border-top: 1px solid var(--glass-border); }
    .tactic-k { grid-row: 1 / 3; font-family: "Courier New", monospace; font-size: 0.7rem; color: var(--text-dim); padding-top: 2px; }
    .tactic-name { font-size: 0.92rem; font-weight: 700; color: var(--text-main); }
    .tactic-set { font-size: 0.74rem; color: var(--text-muted); margin-top: 3px; }
    .tactic-full-guide {
      display: block; margin-top: 14px; padding-top: 14px;
      border-top: 1px solid var(--glass-border);
      font-size: 0.78rem; font-weight: 700; color: var(--accent-gold);
      text-decoration: none;
    }
    .tactic-full-guide:active { opacity: 0.7; }
    .res-legend-card { margin-bottom: 22px; }
    .res-legend-intro { font-size: 0.78rem; color: var(--text-muted); line-height: 1.5; margin: 0 0 12px; }
    .res-legend-intro b { color: var(--accent-gold); font-weight: 700; }
    .res-legend-list { display: grid; grid-template-columns: 28px 1fr; gap: 8px 12px; margin: 0; }
    .res-legend-list dt { font-weight: 800; color: var(--accent-gold); }
    .res-legend-list dd { margin: 0; font-size: 0.76rem; color: var(--text-muted); line-height: 1.5; }
    /* The fixed 28px first column above fits a single glyph ("★", "BB")
       but clips and overlaps a tier badge - "Not Rankable" is nowhere close
       to 28px wide. This modifier sizes the column to its content instead,
       for any legend list whose dt holds a real .tier-badge rather than a
       short symbol. */
    .res-legend-list.tier-legend { grid-template-columns: auto 1fr; align-items: start; }
    .res-legend-list.tier-legend dt { display: flex; align-items: center; padding-top: 1px; }
    .res-links-label { font-size: 0.62rem; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: var(--text-dim); margin: 0 0 10px 2px; }
    .res-ext-group { margin-bottom: 14px; }
    .res-ext-group:last-child { margin-bottom: 0; }
    .res-ext-kind { font-size: 0.6rem; font-weight: 800; letter-spacing: 0.2em; text-transform: uppercase; color: var(--text-dim); margin: 0 0 6px 2px; }
    .res-ext-link { display: grid; grid-template-columns: 1fr auto; gap: 3px 12px; padding: 16px; border-radius: 14px; text-decoration: none; }
    .res-ext-title { grid-column: 1; font-size: 1rem; font-weight: 800; color: #fff; }
    .res-ext-sub { grid-column: 1; font-size: 0.75rem; color: var(--text-muted); }
    .res-ext-go { grid-column: 2; grid-row: 1 / 3; align-self: center; font-size: 0.7rem; font-weight: 800; color: var(--text-dim); letter-spacing: 0.06em; white-space: nowrap; }
    .res-ext-link:active { transform: scale(.99); }

    /*
     * OBSIDIAN LEDGER structural overrides.
     * Scoped to the theme attribute rather than applied globally: this file has
     * ~64 hardcoded rgba glows that CSS variables can't reach, plus tier badge
     * backgrounds baked in as literal rgba. These rules neutralise the neon
     * lighting and restate those backgrounds so the theme reads as genuinely
     * different rather than a hue swap. The default theme is untouched.
     */
    [data-theme="obsidian"] * { text-shadow: none !important; }
    [data-theme="obsidian"] .glass-panel { background: rgba(30,28,26,0.72); box-shadow: 0 2px 10px rgba(0,0,0,0.55); border-top-color: rgba(255,255,255,0.06); border-left-color: rgba(255,255,255,0.04); }
    [data-theme="obsidian"] body, [data-theme="obsidian"] { background: #161514; }
    [data-theme="obsidian"] .app-title { -webkit-text-stroke: 0; color: var(--text-main); font-family: Georgia, "Times New Roman", serif; letter-spacing: 0.02em; text-transform: none; font-weight: 700; }
    [data-theme="obsidian"] .app-title span { -webkit-text-stroke: 0; color: var(--accent-gold); }
    [data-theme="obsidian"] .landing-title { -webkit-text-stroke: 0; color: var(--text-main); font-family: Georgia, "Times New Roman", serif; text-transform: none; }
    [data-theme="obsidian"] .landing-title span { -webkit-text-stroke: 0; color: var(--accent-gold); }
    [data-theme="obsidian"] .hero-ring-circle { box-shadow: none; background: rgba(0,0,0,0.35); border-width: 2px; }
    [data-theme="obsidian"] .casino-avatar { box-shadow: none; border-width: 1px; }
    [data-theme="obsidian"] .status-dot { box-shadow: none; }
    [data-theme="obsidian"] .tier-badge { box-shadow: none; }
    [data-theme="obsidian"] .tier-S { background: rgba(176,141,87,0.16); }
    [data-theme="obsidian"] .tier-A { background: rgba(160,116,80,0.16); }
    [data-theme="obsidian"] .tier-B { background: rgba(94,124,110,0.16); }
    [data-theme="obsidian"] .tier-C { background: rgba(122,110,140,0.16); }
    [data-theme="obsidian"] .tier-D { background: rgba(110,110,110,0.14); }
    [data-theme="obsidian"] .btn-open { background: var(--accent-gold); color: #201c14; box-shadow: none; }
    [data-theme="obsidian"] .btn-open:hover { box-shadow: none; transform: none; }
    [data-theme="obsidian"] .btn-open.cooldown { background: rgba(0,0,0,0.35); color: var(--text-dim); border: 1px solid var(--glass-border); }
    [data-theme="obsidian"] .docked-footer { background: rgba(18,17,16,0.88); box-shadow: 0 -6px 20px rgba(0,0,0,0.6); border-top-color: var(--glass-border); }
    [data-theme="obsidian"] .btn-start-run { box-shadow: none; background: rgba(0,0,0,0.35); }
    [data-theme="obsidian"] .btn-start-run:hover:not(:disabled) { box-shadow: none; background: rgba(125,155,122,0.12); }
    [data-theme="obsidian"] .landing-screen { background: radial-gradient(circle at center, #1e1b18 0%, #121110 100%); }
    [data-theme="obsidian"] .hero-stat-card { background: rgba(30,28,26,0.6); }
    [data-theme="obsidian"] .btn-primary { background: var(--accent-green); color: #14180f; box-shadow: none; }
    [data-theme="obsidian"] .btn-primary:hover { box-shadow: none; }
    [data-theme="obsidian"] .btn-run-collect { background: var(--accent-gold); color: #201c14; box-shadow: none; }
    [data-theme="obsidian"] .btn-dock { box-shadow: none; }
    [data-theme="obsidian"] .btn-dock:hover { box-shadow: none; }
    [data-theme="obsidian"] .nav-tab.active { background: rgba(176,141,87,0.14); border-color: var(--accent-gold); box-shadow: none; color: var(--text-main); }
    [data-theme="obsidian"] .filter-btn.active { background: rgba(94,124,110,0.18); border-color: var(--accent-cyan); box-shadow: none; }
    [data-theme="obsidian"] .sort-trigger-btn { box-shadow: none; }
    [data-theme="obsidian"] .sort-stack-chip { box-shadow: none; }
    [data-theme="obsidian"] .sort-priority-num { box-shadow: none; }
    [data-theme="obsidian"] .keen-info-popover { border-style: solid; border-color: var(--glass-border); box-shadow: 0 4px 16px rgba(0,0,0,0.5); }
    [data-theme="obsidian"] .catalog-item-row.tracked { box-shadow: none; }
    [data-theme="obsidian"] .landing-btn { background: transparent; box-shadow: none; border-color: var(--accent-gold); color: var(--accent-gold); }
    [data-theme="obsidian"] .landing-btn:hover { background: rgba(176,141,87,0.12); box-shadow: none; }
    [data-theme="obsidian"] .tour-tooltip-box { background: var(--accent-gold); box-shadow: 0 6px 24px rgba(0,0,0,0.6); }
    [data-theme="obsidian"] .tour-tooltip-box::before { border-color: transparent transparent var(--accent-gold) transparent; }
    [data-theme="obsidian"] .tour-tooltip-box.arrow-below::before { border-color: var(--accent-gold) transparent transparent transparent; }
    [data-theme="obsidian"] .tour-target-active { animation: none !important; box-shadow: 0 0 0 2px var(--accent-gold) !important; }
    [data-theme="obsidian"] .cooldown-chip.flash { box-shadow: none; }
    [data-theme="obsidian"] .btn-share:hover { box-shadow: none; }
    [data-theme="obsidian"] .type-badge { box-shadow: none; }

    /* =========================================================
       THEME: PRISM NOIR
       Restraint over spectacle. One metal (antique gold), deep emerald as
       secondary, hairline rules, serif display type, and a faint grain so
       surfaces read as printed stock rather than plastic.
       ========================================================= */

    /* Fine grain overlay - reads as texture, not noise */
    [data-theme="prism"] body::before {
      content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 1; opacity: 0.5;
      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.035'/%3E%3C/svg%3E");
    }
    [data-theme="prism"] .app-container, [data-theme="prism"] .docked-footer { position: relative; z-index: 2; }

    /* Fine horizontal scanlines - CRT texture at a whisper, not a gimmick */
    [data-theme="prism"] body::after {
      content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 1; opacity: 0.35;
      background: repeating-linear-gradient(to bottom, rgba(0,229,255,0.035) 0 1px, transparent 1px 3px);
    }

    /* Machined corner brackets on the hero - the tech tell */
    [data-theme="prism"] .hero-stat-card { position: relative; }
    [data-theme="prism"] .hero-stat-card::before,
    [data-theme="prism"] .hero-stat-card::after {
      content: ''; position: absolute; width: 14px; height: 14px; pointer-events: none;
      border-color: var(--accent-cyan); opacity: 0.55;
    }
    [data-theme="prism"] .hero-stat-card::before { top: 6px; left: 6px; border-top: 1px solid; border-left: 1px solid; }
    [data-theme="prism"] .hero-stat-card::after { bottom: 6px; right: 6px; border-bottom: 1px solid; border-right: 1px solid; }

    /* Monospace for all machine-read values: timers, counts, chips */
    [data-theme="prism"] .card-status,
    [data-theme="prism"] .cooldown-chip,
    [data-theme="prism"] .stat-value { font-family: "Courier New", Courier, monospace; letter-spacing: 0.04em; }
    [data-theme="prism"] .cooldown-chip { border-color: rgba(0,229,255,0.3); color: rgba(0,229,255,0.75); }
    [data-theme="prism"] .cooldown-chip:hover { border-color: var(--accent-cyan); color: var(--accent-cyan); }
    [data-theme="prism"] .status-dot { border-radius: 0; box-shadow: none; width: 5px; height: 9px; }
    [data-theme="prism"] .btn-share { border-radius: 1px; border-color: rgba(0,229,255,0.4); color: rgba(0,229,255,0.9); letter-spacing: 0.1em; }
    [data-theme="prism"] .sort-priority-num { border-radius: 0; background: var(--accent-cyan); color: #061014; }
    [data-theme="prism"] .sort-option-btn.active { border-color: var(--accent-cyan); color: var(--accent-cyan); background: rgba(0,229,255,0.06); text-shadow: none; box-shadow: none; }
    [data-theme="prism"] .sort-stack-chip { border-color: rgba(0,229,255,0.45); color: rgba(0,229,255,0.9); }

    /* Serif display, gold leaf */
    [data-theme="prism"] .app-title,
    [data-theme="prism"] .landing-title {
      font-family: Georgia, "Times New Roman", serif;
      text-transform: none; font-weight: 400; letter-spacing: -0.005em;
      -webkit-text-stroke: 0; text-shadow: none;
      background: linear-gradient(175deg, #f6e7b4 0%, #c9a227 42%, #8f6f18 70%, #e3cb7d 100%);
      -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
    }
    [data-theme="prism"] .app-title span,
    [data-theme="prism"] .landing-title span { -webkit-text-stroke: 0; -webkit-text-fill-color: transparent; }
    [data-theme="prism"] .landing-subtitle { color: var(--text-muted); letter-spacing: 0.35em; font-weight: 500; text-shadow: none; }
    [data-theme="prism"] .landing-screen { background: radial-gradient(120% 80% at 50% 40%, #15170f 0%, #0b0c09 50%, #050604 100%); }
    [data-theme="prism"] .landing-btn {
      border-radius: 1px; border: 1px solid rgba(201,162,39,0.55);
      background: transparent; color: var(--accent-gold);
      box-shadow: none; text-shadow: none; letter-spacing: 0.16em; font-weight: 600;
    }
    [data-theme="prism"] .landing-btn:hover { background: rgba(201,162,39,0.08); box-shadow: none; }
    [data-theme="prism"] .date-header { color: var(--accent-gold); text-shadow: none; letter-spacing: 0.22em; font-weight: 600; }

    /* Surfaces: near-black, hairline gold rule, one soft light source */
    [data-theme="prism"] .glass-panel,
    [data-theme="prism"] .ledger-card,
    [data-theme="prism"] .catalog-item-row,
    [data-theme="prism"] .sheet-modal,
    [data-theme="prism"] .hero-stat-card,
    [data-theme="prism"] .keen-info-popover,
    [data-theme="prism"] .res-brief,
    [data-theme="prism"] .res-ext-link {
      border-radius: 2px;
      background: linear-gradient(168deg, rgba(28,29,24,0.92) 0%, rgba(15,16,13,0.95) 100%);
      border: 1px solid rgba(201,162,39,0.16);
      border-top-color: rgba(233,214,150,0.30);
      box-shadow: 0 10px 30px rgba(0,0,0,0.65), inset 0 1px 0 rgba(255,248,225,0.06);
      backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    }
    [data-theme="prism"] .keen-info-popover { border-style: solid; }
    [data-theme="prism"] .ledger-card:active,
    [data-theme="prism"] .catalog-item-row:active { transform: scale(.99); }

    /* Monogram plates rather than gem shapes */
    [data-theme="prism"] .casino-avatar {
      border-radius: 1px; border: 1px solid rgba(201,162,39,0.45);
      background: linear-gradient(160deg, #23241d 0%, #121310 100%);
      color: var(--accent-gold); box-shadow: inset 0 1px 0 rgba(233,214,150,0.18);
      font-family: Georgia, serif; font-weight: 400; letter-spacing: 0.06em;
    }

    /* Tier marks: quiet, lettered, no fill */
    [data-theme="prism"] .tier-badge {
      border-radius: 1px; border: 1px solid currentColor; box-shadow: none;
      background: transparent; font-weight: 700; letter-spacing: 0.14em;
      padding: 2px 7px; font-size: 0.6rem;
    }
    [data-theme="prism"] .tier-S { color: var(--tier-s); }
    [data-theme="prism"] .tier-A { color: var(--tier-a); }
    [data-theme="prism"] .tier-B { color: var(--tier-b); }
    [data-theme="prism"] .tier-C { color: var(--tier-c); }
    [data-theme="prism"] .tier-D { color: var(--tier-d); }
    [data-theme="prism"] .type-badge { background: transparent; border-color: var(--accent-pink); color: var(--accent-pink); box-shadow: none; text-shadow: none; letter-spacing: 0.1em; }

    [data-theme="prism"] .hero-ring-circle {
      border: 1px solid var(--accent-gold); background: rgba(201,162,39,0.05);
      box-shadow: inset 0 0 24px rgba(201,162,39,0.12), 0 0 20px rgba(201,162,39,0.10);
      color: var(--text-main); font-family: Georgia, serif; font-weight: 400;
    }
    [data-theme="prism"] .hero-details h2 { text-shadow: none; font-weight: 600; }
    [data-theme="prism"] .hero-details p { color: var(--text-muted); text-shadow: none; }

    [data-theme="prism"] .docked-footer {
      background: linear-gradient(to top, rgba(7,8,7,0.98), rgba(13,14,11,0.9));
      border-top: 1px solid rgba(201,162,39,0.22); box-shadow: 0 -6px 26px rgba(0,0,0,0.8);
    }

    /* Navigation: an underline, not a pill */
    [data-theme="prism"] .nav-pill-group { border-radius: 2px; }
    [data-theme="prism"] .nav-tab { border-radius: 0; letter-spacing: 0.08em; }
    [data-theme="prism"] .nav-tab.active {
      background: transparent; border: none; border-bottom: 1px solid var(--accent-gold);
      color: var(--accent-gold); text-shadow: none; box-shadow: none;
    }
    [data-theme="prism"] .filter-btn { border-radius: 1px; letter-spacing: 0.04em; }
    [data-theme="prism"] .filter-btn.active {
      background: transparent; border-color: var(--accent-gold);
      color: var(--accent-gold); text-shadow: none; box-shadow: none;
    }
    [data-theme="prism"] .sort-trigger-btn { border-radius: 1px; box-shadow: none; text-shadow: none; }
    [data-theme="prism"] .sort-stack-chip { border-radius: 1px; box-shadow: none; }
    [data-theme="prism"] .sort-priority-num { box-shadow: none; }
    [data-theme="prism"] .cooldown-chip { border-radius: 1px; }

    /* Buttons: flat, precise, hairline. The collect action is the only
       filled gold element on the screen - that is what makes it read as
       valuable rather than decorative. */
    [data-theme="prism"] .btn-primary,
    [data-theme="prism"] .btn-start-run,
    [data-theme="prism"] .btn-dock,
    [data-theme="prism"] .btn-open,
    [data-theme="prism"] .btn-cancel,
    [data-theme="prism"] .btn-danger,
    [data-theme="prism"] .btn-run-collect {
      border-radius: 1px; letter-spacing: 0.08em; text-shadow: none;
      box-shadow: none; position: relative; overflow: hidden;
    }
    [data-theme="prism"] .btn-dock { background: transparent; border: 1px solid rgba(201,162,39,0.3); color: var(--text-main); letter-spacing: 0.04em; font-size: 0.82rem; white-space: nowrap; }
    [data-theme="prism"] .btn-dock:hover { background: rgba(201,162,39,0.08); box-shadow: none; }
    [data-theme="prism"] .btn-primary { background: linear-gradient(175deg, #e9d492 0%, #c9a227 45%, #a8851c 100%); color: #17130a; border: none; font-weight: 700; }
    [data-theme="prism"] .btn-open:not(.cooldown),
    [data-theme="prism"] .btn-run-collect {
      background: linear-gradient(175deg, #f0dda3 0%, #c9a227 45%, #9d7c17 100%);
      color: #17130a; border: none; font-weight: 700;
      box-shadow: 0 2px 10px rgba(201,162,39,0.28);
    }
    [data-theme="prism"] .btn-open.cooldown {
      background: linear-gradient(168deg, #1b1c17, #101109);
      border: 1px solid rgba(201,162,39,0.22);
      color: var(--text-dim); opacity: 1;
    }
    [data-theme="prism"] .btn-start-run {
      background: transparent; border: 1px solid rgba(201,162,39,0.4);
      color: var(--accent-gold); box-shadow: none;
    }
    [data-theme="prism"] .btn-start-run:hover:not(:disabled) { background: rgba(201,162,39,0.07); box-shadow: none; }

    /* Tooltip: engraved plate. Dark ink on gold leaf. */
    [data-theme="prism"] .tour-tooltip-box {
      border-radius: 1px;
      background: linear-gradient(172deg, #f4e6b6 0%, #d9b53c 40%, #c9a227 68%, #e6d295 100%);
      border: 1px solid rgba(120,92,20,0.5);
      color: #191308;
      box-shadow: 0 16px 44px rgba(0,0,0,0.7), inset 0 1px 0 rgba(255,252,240,0.55);
    }
    [data-theme="prism"] .tour-tooltip-box::before { border-color: transparent transparent #f4e6b6 transparent; }
    [data-theme="prism"] .tour-tooltip-box.arrow-below::before { border-color: #e6d295 transparent transparent transparent; }
    [data-theme="prism"] .tour-advance-subtext { color: rgba(25,19,8,0.68); border-top-color: rgba(80,60,10,0.28); letter-spacing: 0.1em; }
    [data-theme="prism"] .tour-target-active { animation: none !important; box-shadow: 0 0 0 1px var(--accent-gold) !important; }

    /* Layered gold leaf + sheen band. The gradient applies unconditionally so
       the button always looks right; only the motion is conditional. */
    [data-theme="prism"] .btn-open:not(.cooldown),
    [data-theme="prism"] .btn-run-collect {
      background-image: linear-gradient(175deg, #f7e7ae 0%, #d4ad2c 42%, #9d7c17 100%),
                        linear-gradient(105deg, transparent 38%, rgba(255,253,242,0.95) 50%, transparent 62%);
      background-size: 100% 100%, 240% 100%;
      background-position: 0 0, 200% 0;
      background-repeat: no-repeat;
    }
    @keyframes prism-leaf-sheen {
      0%, 45% { background-position: 0 0, 200% 0; }
      100%    { background-position: 0 0, -130% 0; }
    }
      [data-theme="prism"] .btn-open:not(.cooldown),
      [data-theme="prism"] .btn-run-collect {
        animation: prism-leaf-sheen 3.4s ease-in-out infinite;
      }
      /* A slow electric pulse along the hero ring - the one piece of
         circuitry in an otherwise still interface. */
      [data-theme="prism"] .hero-ring-wrapper::after {
        content: ''; position: absolute; inset: -3px; border-radius: 50%;
        background: conic-gradient(from 0deg, transparent 0deg, rgba(0,229,255,0.5) 14deg, rgba(201,162,39,0.35) 26deg, transparent 42deg);
        animation: prism-ring-trace 4.5s linear infinite; pointer-events: none;
        mask: radial-gradient(circle, transparent 62%, #000 64%);
        -webkit-mask: radial-gradient(circle, transparent 62%, #000 64%);
      }
      @keyframes prism-ring-trace { to { transform: rotate(360deg); } }
      /* Hairline scan travelling down the top rule of each card. */
      [data-theme="prism"] .ledger-card::before {
        content: ''; position: absolute; top: 0; left: 0; right: 0; height: 1px;
        background: linear-gradient(90deg, transparent, rgba(0,229,255,0.7), transparent);
        background-size: 40% 100%; background-repeat: no-repeat;
        animation: prism-scan 5.5s linear infinite; opacity: 0.55; pointer-events: none;
      }
      @keyframes prism-scan { 0% { background-position: -60% 0; } 100% { background-position: 160% 0; } }

    /* ==========================================================
       PRISM NOIR - WALLET TREATMENT
       Gold bezel, stitched inner seam, carbon weave, etched traces.
       Every panel reads as a machined object rather than a rectangle.
       ========================================================== */

    /* Carbon-fibre weave + warm leather base under every surface */
    [data-theme="prism"] .glass-panel,
    [data-theme="prism"] .ledger-card,
    [data-theme="prism"] .catalog-item-row,
    [data-theme="prism"] .sheet-modal,
    [data-theme="prism"] .hero-stat-card,
    [data-theme="prism"] .res-brief,
    [data-theme="prism"] .res-ext-link,
    [data-theme="prism"] .keen-info-popover {
      background-color: #121310;
      background-image:
        repeating-linear-gradient(45deg,  rgba(255,255,255,0.022) 0 2px, transparent 2px 4px),
        repeating-linear-gradient(-45deg, rgba(0,0,0,0.30)        0 2px, transparent 2px 4px),
        linear-gradient(168deg, rgba(38,39,32,0.9) 0%, rgba(14,15,12,0.96) 100%);
      border: 1px solid #6d5719;
      border-radius: 3px;
      box-shadow:
        inset 0 0 0 1px rgba(233,214,150,0.14),
        inset 0 1px 0 rgba(255,246,214,0.16),
        0 10px 26px rgba(0,0,0,0.7);
      position: relative;
    }

    /* Stitched seam just inside the bezel, like the wallet edging */
    [data-theme="prism"] .ledger-card::before,
    [data-theme="prism"] .catalog-item-row::before,
    [data-theme="prism"] .hero-stat-card > .stitch,
    [data-theme="prism"] .res-ext-link::before,
    [data-theme="prism"] .res-brief::before {
      content: ''; position: absolute; inset: 4px; pointer-events: none;
      border: 1px dashed rgba(214,178,74,0.45); border-radius: 2px;
    }

    /* Etched gold trace work, branching off toward the right edge */
    [data-theme="prism"] .ledger-card,
    [data-theme="prism"] .res-ext-link {
      background-image:
        url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27120%27 height=%2780%27 viewBox=%270 0 120 80%27%3E%3Cg fill=%27none%27 stroke=%27%23c9a227%27 stroke-width=%271%27 opacity=%270.5%27 stroke-linecap=%27round%27%3E%3Cpath d=%27M0 40 L18 40 L30 28 L58 28 L70 16 L104 16%27/%3E%3Cpath d=%27M18 40 L30 52 L52 52 L62 62 L98 62%27/%3E%3Cpath d=%27M30 28 L30 20 L40 10 L74 10%27/%3E%3Cpath d=%27M52 52 L52 72 L60 72%27/%3E%3Cpath d=%27M70 16 L82 28 L110 28%27/%3E%3Cpath d=%27M62 62 L74 50 L96 50%27/%3E%3C/g%3E%3Cg fill=%27%23c9a227%27 opacity=%270.7%27%3E%3Crect x=%27102%27 y=%2714%27 width=%274%27 height=%274%27/%3E%3Crect x=%2796%27 y=%2760%27 width=%274%27 height=%274%27/%3E%3Crect x=%2772%27 y=%278%27 width=%274%27 height=%274%27/%3E%3Crect x=%27108%27 y=%2726%27 width=%274%27 height=%274%27/%3E%3Ccircle cx=%2730%27 cy=%2728%27 r=%272%27/%3E%3Ccircle cx=%2718%27 cy=%2740%27 r=%272%27/%3E%3Ccircle cx=%2752%27 cy=%2752%27 r=%272%27/%3E%3Ccircle cx=%2770%27 cy=%2716%27 r=%272%27/%3E%3C/g%3E%3C/svg%3E"),
        repeating-linear-gradient(45deg,  rgba(255,255,255,0.022) 0 2px, transparent 2px 4px),
        repeating-linear-gradient(-45deg, rgba(0,0,0,0.30)        0 2px, transparent 2px 4px),
        linear-gradient(168deg, rgba(38,39,32,0.9) 0%, rgba(14,15,12,0.96) 100%);
      background-repeat: no-repeat, repeat, repeat, no-repeat;
      background-position: right 4px bottom 2px, 0 0, 0 0, 0 0;
      background-size: 86px 56px, auto, auto, auto;
    }

    /* Machined gold corner hardware on every panel */
    [data-theme="prism"] .ledger-card::after,
    [data-theme="prism"] .catalog-item-row::after,
    [data-theme="prism"] .res-ext-link::after {
      content: ''; position: absolute; top: -1px; left: -1px;
      width: 15px; height: 15px; pointer-events: none;
      border-top: 2px solid var(--accent-gold); border-left: 2px solid var(--accent-gold);
      border-top-left-radius: 3px;
      background: none; margin: 0;
    }

    /* The monogram plate: neon glyph on carbon, the wallet's focal point */
    [data-theme="prism"] .casino-avatar {
      border-radius: 2px; border: 1px solid rgba(201,162,39,0.55);
      background-color: #0d0e0b;
      background-image:
        repeating-linear-gradient(45deg,  rgba(255,255,255,0.03) 0 2px, transparent 2px 4px),
        repeating-linear-gradient(-45deg, rgba(0,0,0,0.35)       0 2px, transparent 2px 4px);
      color: #d9a8ff;
      text-shadow: 0 0 6px rgba(190,120,255,0.9), 0 0 16px rgba(160,80,255,0.55);
      box-shadow: inset 0 1px 0 rgba(255,246,214,0.18), 0 0 14px rgba(150,70,255,0.18);
      font-family: Georgia, serif; font-weight: 400; letter-spacing: 0.06em;
    }

    /* Tabs as embossed gold plaques rather than flat text */
    [data-theme="prism"] .nav-pill-group {
      border: 1px solid #6d5719; border-radius: 3px;
      background: linear-gradient(168deg, rgba(34,35,28,0.9), rgba(12,13,10,0.96));
      box-shadow: inset 0 0 0 1px rgba(233,214,150,0.12), inset 0 1px 0 rgba(255,246,214,0.14);
    }
    [data-theme="prism"] .nav-tab {
      border-radius: 2px; letter-spacing: 0.1em; border: 1px solid transparent;
    }
    [data-theme="prism"] .nav-tab.active {
      color: #17130a; border: 1px solid #8a6c1d;
      background: linear-gradient(175deg, #f0dda3 0%, #c9a227 45%, #9d7c17 100%);
      box-shadow: inset 0 1px 0 rgba(255,252,238,0.6), 0 2px 8px rgba(201,162,39,0.3);
      text-shadow: none; font-weight: 800;
    }

    /* Filter chips as small stamped tags */
    [data-theme="prism"] .filter-btn { border-radius: 2px; border-color: rgba(201,162,39,0.22); }
    [data-theme="prism"] .filter-btn.active {
      background: rgba(201,162,39,0.14); border-color: var(--accent-gold);
      color: var(--accent-gold); box-shadow: inset 0 1px 0 rgba(255,246,214,0.2);
    }

    [data-theme="prism"] .ledger-card { position: relative; }
    [data-theme="prism"] .card-actions { position: relative; z-index: 2; }
    [data-theme="prism"] .card-left { position: relative; z-index: 2; }

    /* ---- Circuit threading: cyberpunk stitched through the noir table ---- */
      /* Slow breathing pulse used by several nodes below */
      @keyframes prism-node-pulse {
        0%, 100% { opacity: 0.25; box-shadow: 0 0 0 0 rgba(0,229,255,0); }
        50%      { opacity: 1;    box-shadow: 0 0 6px 1px rgba(0,229,255,0.55); }
      }
      @keyframes prism-trace-run {
        0%   { background-position: -40% 0; }
        100% { background-position: 140% 0; }
      }
      @keyframes prism-seam-breathe {
        0%, 100% { opacity: 0.18; }
        50%      { opacity: 0.5; }
      }

      /* Node on the leading edge of every card - a lit solder point.
         Colour cycles per card so the board reads as multi-rail wiring
         rather than one repeated LED. */
      [data-theme="prism"] .ledger-card::after,
      [data-theme="prism"] .catalog-item-row::after {
        content: ''; position: absolute; left: 0; top: 50%;
        width: 3px; height: 3px; margin-top: -1.5px;
        background: var(--wire-cyan);
        animation: prism-node-pulse 3.6s ease-in-out infinite;
        pointer-events: none;
      }
      [data-theme="prism"] .catalog-item-row { position: relative; }
      [data-theme="prism"] .ledger-card-wrapper:nth-child(4n+1) .ledger-card::after { background: var(--wire-cyan); }
      [data-theme="prism"] .ledger-card-wrapper:nth-child(4n+2) .ledger-card::after { background: var(--wire-magenta); animation-delay: .9s; }
      [data-theme="prism"] .ledger-card-wrapper:nth-child(4n+3) .ledger-card::after { background: var(--wire-amber); animation-delay: 1.8s; }
      [data-theme="prism"] .ledger-card-wrapper:nth-child(4n+4) .ledger-card::after { background: var(--wire-violet); animation-delay: 2.7s; }
      [data-theme="prism"] .catalog-item-row:nth-child(even)::after { animation-delay: 1.8s; background: var(--wire-magenta); }

      /* Bus line down the left gutter of each card, feeding the node */
      [data-theme="prism"] .ledger-card { border-left: 1px solid rgba(0,229,255,0.16); }
      [data-theme="prism"] .ledger-card-wrapper:nth-child(4n+2) .ledger-card { border-left-color: rgba(255,47,176,0.16); }
      [data-theme="prism"] .ledger-card-wrapper:nth-child(4n+3) .ledger-card { border-left-color: rgba(255,138,31,0.16); }
      [data-theme="prism"] .ledger-card-wrapper:nth-child(4n+4) .ledger-card { border-left-color: rgba(164,92,255,0.16); }

      /* Circuit trace along the nav rail */
      [data-theme="prism"] .nav-pill-group { position: relative; overflow: hidden; }
      [data-theme="prism"] .nav-pill-group::after {
        content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
        background: linear-gradient(90deg, transparent, var(--wire-cyan) 40%, var(--wire-magenta) 60%, transparent);
        background-size: 45% 100%; background-repeat: no-repeat;
        animation: prism-trace-run 7s linear infinite; pointer-events: none;
      }

      /* Seam above the docked footer, breathing rather than static */
      [data-theme="prism"] .docked-footer::before {
        content: ''; position: absolute; top: -1px; left: 0; right: 0; height: 1px;
        background: linear-gradient(90deg, transparent 4%, var(--wire-amber) 28%, var(--accent-gold) 50%, var(--wire-magenta) 72%, transparent 96%);
        animation: prism-seam-breathe 4.2s ease-in-out infinite; pointer-events: none;
      }
      [data-theme="prism"] .docked-footer { position: relative; }

      /* Filter rail: a thread running under the chips */
      [data-theme="prism"] .filter-sort-row { position: relative; }
      [data-theme="prism"] .filter-sort-row::after {
        content: ''; position: absolute; left: 0; right: 0; bottom: -3px; height: 1px;
        background: linear-gradient(90deg, transparent, var(--wire-violet), transparent);
        background-size: 45% 100%; background-repeat: no-repeat;
        animation: prism-trace-run 9s linear infinite; pointer-events: none; opacity: 0.75;
      }

      /* Avatar plates get a lit corner notch */
      [data-theme="prism"] .casino-avatar { position: relative; }
      [data-theme="prism"] .casino-avatar::after {
        content: ''; position: absolute; top: -1px; right: -1px; width: 5px; height: 5px;
        border-top: 1px solid var(--wire-cyan); border-right: 1px solid var(--wire-cyan);
        animation: prism-node-pulse 4.4s ease-in-out infinite;
      }

      @keyframes prism-bracket-pulse {
        0%, 100% { opacity: 0.25; }
        50%      { opacity: 0.85; }
      }
      [data-theme="prism"] .hero-stat-card::before,
      [data-theme="prism"] .hero-stat-card::after { animation: prism-bracket-pulse 5s ease-in-out infinite; }
      [data-theme="prism"] .hero-stat-card::after { animation-delay: 2.5s; border-color: var(--wire-magenta); }

      /* READY is a live rail: the whole row runs warm. This is the
         "winning" tell - only rows you can actually collect from glow. */
      @keyframes prism-live-glow {
        0%, 100% { box-shadow: 0 10px 30px rgba(0,0,0,0.65), inset 0 1px 0 rgba(255,248,225,0.06), inset 3px 0 0 -1px rgba(255,138,31,0.35); }
        50%      { box-shadow: 0 10px 30px rgba(0,0,0,0.65), inset 0 1px 0 rgba(255,248,225,0.06), inset 3px 0 0 -1px rgba(255,180,60,0.95); }
      }
      [data-theme="prism"] .ledger-card.is-ready {
        animation: prism-live-glow 3s ease-in-out infinite;
        border-left-color: rgba(255,138,31,0.5);
      }

      /* Ready status tick pulses; cooldown stays dead */
      @keyframes prism-tick { 0%,100% { opacity: .45; } 50% { opacity: 1; } }
      [data-theme="prism"] .status-dot:not(.cooldown) {
        background: var(--wire-amber); animation: prism-tick 2.2s ease-in-out infinite;
      }

      /* Hero ring: three rails chasing each other */
      [data-theme="prism"] .hero-ring-wrapper::after {
        background: conic-gradient(from 0deg,
          transparent 0deg, rgba(0,229,255,0.55) 10deg, transparent 24deg,
          transparent 120deg, rgba(255,47,176,0.5) 130deg, transparent 144deg,
          transparent 240deg, rgba(255,138,31,0.5) 250deg, transparent 264deg);
        animation: prism-ring-trace 6s linear infinite;
      }
      /* Counter-rotating inner rail */
      [data-theme="prism"] .hero-ring-wrapper::before {
        content: ''; position: absolute; inset: 5px; border-radius: 50%;
        background: conic-gradient(from 180deg, transparent 0deg, rgba(164,92,255,0.4) 16deg, transparent 34deg);
        animation: prism-ring-trace 9s linear infinite reverse; pointer-events: none;
        mask: radial-gradient(circle, transparent 70%, #000 72%);
        -webkit-mask: radial-gradient(circle, transparent 70%, #000 72%);
      }
      [data-theme="prism"] .hero-ring-wrapper { position: relative; }

      /* Tier marks carry their own faint charge */
      [data-theme="prism"] .tier-badge { box-shadow: 0 0 7px -1px currentColor; }
      [data-theme="prism"] .type-badge { box-shadow: 0 0 8px -2px var(--wire-magenta); }

    [data-theme="prism"] .res-brief, [data-theme="prism"] .res-ext-link { border-radius: 2px; }
    [data-theme="prism"] .res-ext-kind, [data-theme="prism"] .res-brief-label { color: var(--accent-gold); letter-spacing: 0.24em; }
    [data-theme="prism"] .tactic-k { color: rgba(0,229,255,0.6); }
    [data-theme="prism"] .res-ext-go { color: rgba(0,229,255,0.75); font-family: "Courier New", monospace; }
    [data-theme="prism"] .theme-card { border-radius: 2px; }
    [data-theme="prism"] .theme-card.active { border-color: var(--accent-gold); }
    [data-theme="prism"] .stat-box, [data-theme="prism"] .prune-card,
    [data-theme="prism"] .prune-summary-item { border-radius: 2px; background: rgba(255,250,235,0.03); }
    [data-theme="prism"] .sheet-modal h3 { color: var(--accent-gold); font-family: Georgia, serif; text-transform: none; font-weight: 400; letter-spacing: 0.02em; text-shadow: none; }
    [data-theme="prism"] .form-group label,
    [data-theme="prism"] .stats-section h4,
    [data-theme="prism"] .theme-settings h4,
    [data-theme="prism"] .notify-settings h4 { color: var(--accent-gold); text-shadow: none; letter-spacing: 0.14em; }
    [data-theme="prism"] .form-group input,
    [data-theme="prism"] .form-group textarea,
    [data-theme="prism"] .catalog-search { border-radius: 1px; }

/* =========================================================
   THEME: Western ("Boot Hill")
   Gritty graphic novel / spaghetti western macabre. Deep blood
   red, pitch black, distressed grey, high-voltage gold, bone
   white. Neo-brutalist: flat, sharp 90deg corners, thick black
   borders, hard offset shadows - no blur/glow anywhere, the
   opposite of neon/prism's soft light sources. Buttons get a
   CSS-only spring "overshoot" press: a back-out cubic-bezier on
   the release transition does the compress-then-snap-past-100%
   bounce with no JS or keyframes needed for that part.
   ========================================================= */

/* Grain (same feTurbulence trick as prism's body::before) plus a
   harder vignette - "darkening significantly around the edges"
   per the brief - as body::after. */
[data-theme="western"] body::before {
  content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 1; opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
}
[data-theme="western"] body::after {
  content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 1;
  background: radial-gradient(120% 90% at 50% 40%, transparent 40%, rgba(0,0,0,0.55) 100%);
}
[data-theme="western"] .app-container, [data-theme="western"] .docked-footer { position: relative; z-index: 2; }

/* Typography: typewriter/wood-block headings, condensed mechanical body */
[data-theme="western"] .app-title,
[data-theme="western"] .landing-title {
  font-family: 'Special Elite', 'Courier New', monospace;
  text-transform: uppercase; font-weight: 400; letter-spacing: 0;
  -webkit-text-stroke: 0; color: var(--text-main);
  text-shadow: 2px 2px 0 var(--accent-pink);
}
[data-theme="western"] .app-title span,
[data-theme="western"] .landing-title span {
  color: var(--accent-gold); -webkit-text-fill-color: currentColor;
  -webkit-text-stroke: 0; text-shadow: none;
}
[data-theme="western"] body { font-family: 'Oswald', 'Arial Narrow', Arial, sans-serif; }

/* Landing screen: wanted-poster card on a blood-vignette backdrop */
[data-theme="western"] .landing-screen {
  background: radial-gradient(140% 100% at 50% 30%, #810000 0%, #3a0000 45%, #0B0B0B 90%);
}
[data-theme="western"] .landing-inner::before {
  /* Base rule paints a dark glow-well *above* .landing-inner's own
     background (negative z-index sits behind in-flow content, not behind
     the parent's own background box) - built for the other themes' dark/
     translucent cards. This theme's card is solid bone white, so the well
     has to go rather than get overridden to match. */
  display: none;
}
[data-theme="western"] .landing-inner {
  background: var(--text-main);
  border: 4px solid #0B0B0B;
  box-shadow: 8px 8px 0 #0B0B0B;
  transform: rotate(-0.6deg);
  padding: 34px 26px 30px;
}
[data-theme="western"] .landing-title { color: #0B0B0B; text-shadow: 2px 2px 0 var(--accent-gold); }
[data-theme="western"] .landing-title span { color: #810000; -webkit-text-stroke: 0; text-shadow: none; }
[data-theme="western"] .landing-subtitle {
  color: #2E2E2E; font-family: 'Oswald', sans-serif; font-weight: 700;
  letter-spacing: 0.2em; text-shadow: none;
}

/* Buttons: neo-brutalist, flat, thick black border, hard offset shadow,
   CSS-only spring overshoot on release via a back-out easing curve.
   Primary/active = gold (the CTA color); everything else = distressed
   grey (per the brief's "inactive state" role for that color). */
[data-theme="western"] .landing-btn,
[data-theme="western"] .btn-primary,
[data-theme="western"] .btn-start-run,
[data-theme="western"] .sort-trigger-btn,
[data-theme="western"] .filter-btn.active,
[data-theme="western"] .nav-tab.active {
  border-radius: 0; border: 3px solid #0B0B0B;
  background: var(--accent-gold); color: #0B0B0B;
  box-shadow: 4px 4px 0 #0B0B0B; text-shadow: none;
  transition: transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.12s ease;
}
[data-theme="western"] .landing-btn:active,
[data-theme="western"] .btn-primary:active,
[data-theme="western"] .btn-start-run:active,
[data-theme="western"] .sort-trigger-btn:active,
[data-theme="western"] .filter-btn.active:active,
[data-theme="western"] .nav-tab.active:active {
  transform: translate(3px, 3px) scale(0.85);
  box-shadow: 1px 1px 0 #0B0B0B;
}
[data-theme="western"] .filter-btn,
[data-theme="western"] .btn-cancel,
[data-theme="western"] .btn-check,
[data-theme="western"] .btn-open,
[data-theme="western"] .nav-tab,
[data-theme="western"] .btn-share,
[data-theme="western"] .cooldown-chip {
  border-radius: 0; border: 2px solid #0B0B0B;
  /* One step up from the card beneath them so a button still reads as
     a raised control on the darkened surface, not a hole in it. */
  background: #1E2126; color: var(--text-main);
  box-shadow: 3px 3px 0 #0B0B0B; text-shadow: none;
  transition: transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.12s ease;
}
[data-theme="western"] .filter-btn:active,
[data-theme="western"] .btn-cancel:active,
[data-theme="western"] .btn-check:active,
[data-theme="western"] .btn-open:active,
[data-theme="western"] .nav-tab:active,
[data-theme="western"] .btn-share:active,
[data-theme="western"] .cooldown-chip:active {
  transform: translate(2px, 2px) scale(0.88);
  box-shadow: 1px 1px 0 #0B0B0B;
}
[data-theme="western"] .btn-settings-gear { color: var(--text-main); }
/* Same square-plate language as the tier badges and avatars. */
[data-theme="western"] .btn-ledger-quick { color: var(--text-main); }
[data-theme="western"] .ledger-quick-mark,
[data-theme="western"] .slc-icon {
  border-radius: 0; border: 1px solid #0B0B0B; box-shadow: 2px 2px 0 #0B0B0B;
  background: var(--accent-gold); color: #0B0B0B;
  font-family: 'Special Elite', monospace;
}

/* Cards & containers: solid, flat, grain-textured, hard-edged */
[data-theme="western"] .glass-panel,
[data-theme="western"] .ledger-card,
[data-theme="western"] .catalog-item-row,
[data-theme="western"] .sheet-modal,
[data-theme="western"] .hero-stat-card,
[data-theme="western"] .keen-info-popover,
[data-theme="western"] .res-brief,
[data-theme="western"] .res-ext-link,
[data-theme="western"] .strategy-row,
[data-theme="western"] .tier-action-card {
  border-radius: 0;
  /* Darker gunmetal than the #22252A this started at: every glow in
     this theme - the ring pulse, the campfire flicker, the ember
     sparks - is light thrown onto these surfaces, and the lighter the
     surface the less of that light actually registers. */
  background: #16181C;
  border: 2px solid #0B0B0B;
  box-shadow: 4px 4px 0 rgba(11,11,11,0.7), inset 0 0 0 1px rgba(234,234,234,0.06);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
[data-theme="western"] .keen-info-popover { border-style: solid; background: #E3DAC9; color: #0B0B0B; }
[data-theme="western"] .ledger-card:active,
[data-theme="western"] .catalog-item-row:active { transform: scale(0.98) translate(1px, 1px); }

/* Gore fest: torn edges, ambient splatter, and a rougher, stuttering entry
   than the smooth cubic-bezier every other theme rises with. */

/* Jagged clip-path instead of a straight rectangle. Small, irregular teeth
   along every edge - big enough to read as torn at card size, subtle enough
   that the 137-row catalogue list doesn't turn into visual noise. clip-path
   crops box-shadow too, which is why these two get their shadow restated as
   a drop-shadow() filter instead (it isn't clipped the way box-shadow is). */
[data-theme="western"] .ledger-card,
[data-theme="western"] .sheet-modal {
  clip-path: polygon(
    0% 2%, 4% 0%, 11% 1.5%, 18% 0%, 27% 1%, 35% 0%, 44% 1.5%, 52% 0%,
    61% 1%, 69% 0%, 78% 1.5%, 86% 0%, 94% 1%, 100% 0%,
    100% 97%, 96% 100%, 89% 98.5%, 82% 100%, 73% 99%, 65% 100%,
    56% 98.5%, 48% 100%, 39% 99%, 31% 100%, 22% 98.5%, 14% 100%,
    6% 99%, 0% 100%
  );
  box-shadow: none;
  filter: drop-shadow(4px 4px 0 rgba(11,11,11,0.7));
}

/* Ambient splatter, always present rather than only on collect - a handful
   of dark marks fixed in the upper corners, reusing splatter-burst so a
   fresh set punches in and settles every time it loops instead of a static
   decal. .app-container::before is already spoken for by the collect-flash
   burst above, hence ::after here. */
[data-theme="western"] .app-container::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.5;
  background:
    radial-gradient(circle 5px at 6% 4%, #6b0000 99%, transparent 100%),
    radial-gradient(circle 3px at 14% 9%, #4a0000 99%, transparent 100%),
    radial-gradient(circle 8px at 92% 3%, #810000 99%, transparent 100%),
    radial-gradient(circle 4px at 85% 11%, #6b0000 99%, transparent 100%),
    radial-gradient(circle 2px at 97% 14%, #5a0000 99%, transparent 100%);
  animation: splatter-burst 14s ease-in-out infinite;
}
[data-motion="off"] [data-theme="western"] .app-container::after { animation: none; opacity: 0.35; }

/* Cards don't glide in, they stutter in - hard-eased steps() rather than a
   smooth curve, so the motion reads as something being torn into place
   instead of gliding. Small rotation jitter per step sells the same idea
   run-card gets on Daily Run open. */
[data-theme="western"] .ledger-card-wrapper {
  animation: rip-in 0.36s steps(4, end) both;
}
@keyframes rip-in {
  0%   { opacity: 0; transform: translateY(14px) rotate(-2deg) scale(0.94); }
  35%  { opacity: 1; transform: translateY(3px) rotate(1.5deg) scale(1.02); }
  70%  { transform: translateY(-1px) rotate(-0.5deg) scale(0.99); }
  100% { opacity: 1; transform: none; }
}
[data-theme="western"] #dailyRunOverlay.open .run-card {
  animation: rip-in 0.4s steps(5, end);
}
[data-motion="off"] [data-theme="western"] .ledger-card-wrapper,
[data-motion="off"] [data-theme="western"] #dailyRunOverlay.open .run-card { animation: none; }

/* Avatars & badges: square plates and filled tags, not glowing gems */
[data-theme="western"] .casino-avatar,
[data-theme="western"] .hero-ring-circle {
  border-radius: 0; border: 2px solid #0B0B0B;
  background: var(--accent-gold); color: #0B0B0B;
  box-shadow: 3px 3px 0 #0B0B0B; text-shadow: none;
  font-family: 'Special Elite', monospace;
}
[data-theme="western"] .status-dot { border-radius: 0; width: 9px; height: 9px; box-shadow: 1px 1px 0 #0B0B0B; }
[data-theme="western"] .tier-badge {
  border-radius: 0; border: 1px solid #0B0B0B; box-shadow: 2px 2px 0 #0B0B0B;
  color: #0B0B0B; text-shadow: none;
}
[data-theme="western"] .tier-S { background: var(--tier-s); }
[data-theme="western"] .tier-A { background: var(--tier-a); }
[data-theme="western"] .tier-B { background: var(--tier-b); }
[data-theme="western"] .tier-C { background: var(--tier-c); }
[data-theme="western"] .tier-D { background: var(--tier-d); }
[data-theme="western"] .type-badge {
  border-radius: 0; border: 1px solid #0B0B0B; box-shadow: 2px 2px 0 #0B0B0B;
  background: var(--accent-pink); color: var(--text-main); text-shadow: none;
}

[data-theme="western"] .date-header { color: var(--accent-gold); text-shadow: none; font-family: 'Oswald', sans-serif; font-weight: 700; letter-spacing: 0.14em; }
[data-theme="western"] .hero-details h2 { text-shadow: none; }
[data-theme="western"] .hero-details p { color: var(--text-muted); text-shadow: none; }
[data-theme="western"] .nav-pill-group { border-radius: 0; border: 2px solid #0B0B0B; background: #0B0B0B; }
[data-theme="western"] .docked-footer {
  background: #0B0B0B; border-top: 3px solid #0B0B0B; backdrop-filter: none; -webkit-backdrop-filter: none;
  box-shadow: 0 -4px 0 rgba(11,11,11,0.7);
}

/* Screen shake for the daily-run-complete milestone hook in the main
   script (see screenShake() near applyTheme()). Body-scoped so toggling
   .screen-shake-active off-theme is a harmless no-op. */
[data-theme="western"] body.screen-shake-active { animation: western-screen-shake 0.4s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; }
@keyframes western-screen-shake {
  10%, 90% { transform: translate3d(-1px, 0, 0); }
  20%, 80% { transform: translate3d(2px, -1px, 0); }
  30%, 50%, 70% { transform: translate3d(-4px, 1px, 0); }
  40%, 60% { transform: translate3d(4px, -1px, 0); }
}

[data-theme="western"] .app-container {
  perspective: 900px;
}
[data-theme="western"] .hero-stat-card {
  /* Dark, same as every other card in this theme (the bone-white
     "wanted poster" treatment this had before reads as the wrong
     surface here - that look belongs to the landing card, not a card
     that sits on screen throughout the app). */
  position: relative;
  overflow: hidden;
  transform: rotate(-0.8deg);
}
[data-theme="western"] .hero-stat-card::before,
[data-theme="western"] .hero-stat-card::after {
  content: '';
  position: absolute;
  pointer-events: none;
  border: 2px solid rgba(129, 0, 0, 0.4);
  border-radius: 50%;
}
[data-theme="western"] .hero-stat-card::before { width: 210px; height: 210px; right: -90px; top: -80px; }
[data-theme="western"] .hero-stat-card::after { width: 145px; height: 145px; right: -56px; top: -48px; border-color: rgba(227, 218, 201, 0.18); }
[data-theme="western"] .hero-details h2 { color: var(--text-main); text-shadow: 1px 1px 0 #0B0B0B; }
[data-theme="western"] .hero-details p { color: var(--text-muted); }
[data-theme="western"] .hero-ring-circle {
  position: relative;
  z-index: 1;
  border-radius: 50%;
  background: #810000;
  color: var(--text-main);
  /* Gold, not black - a black ring edge all but disappeared against
     this card's own dark grey fill. Reads as a branding-iron/badge
     ring now instead of vanishing into the background. */
  border: 5px double var(--accent-gold);
  box-shadow: 4px 4px 0 #0B0B0B, inset 0 0 0 5px rgba(227, 218, 201, 0.18);
}
/* The red plank the three tabs are mounted on. It used to sit at a
   0.45deg tilt, which put the frame out of square with everything
   around it, and the tabs themselves overflowed it: three flex
   children at 118px plus two 6px gaps came to 368px inside a 366px
   box, so "Resources" hung over the right edge with its offset shadow
   clipped off. Padding now leaves room for those 3px drop shadows on
   the right and bottom, and the active tab no longer widens itself
   with a fatter border, so all three measure the same and fit. */
[data-theme="western"] .nav-pill-group {
  position: relative;
  border: 2px solid #0B0B0B;
  background: #810000;
  box-shadow: 5px 5px 0 #0B0B0B;
  padding: 8px;
  gap: 8px;
}
[data-theme="western"] .nav-tab { box-sizing: border-box; min-width: 0; }
/* Equal borders across all three - the active state reads through
   colour and shadow depth, it doesn't need an extra pixel of edge. */
/* 2px shadows here, not 3px: the plank's frame is even on all four
   sides now, and a 3px drop shadow on the last tab reached past the
   right edge of it. */
[data-theme="western"] .nav-pill-group .nav-tab { box-shadow: 2px 2px 0 #0B0B0B; }
[data-theme="western"] .nav-pill-group .nav-tab.active { border-width: 2px; box-shadow: 2px 2px 0 #0B0B0B; }
[data-theme="western"] .nav-tab { color: var(--text-main); }
[data-theme="western"] .nav-tab.active {
  background: var(--accent-gold);
  color: #0B0B0B;
  box-shadow: 3px 3px 0 #0B0B0B;
}
[data-theme="western"] .ledger-card:nth-child(odd) { transform: rotate(-0.35deg); }
[data-theme="western"] .ledger-card:nth-child(even) { transform: rotate(0.35deg); }
[data-theme="western"] .btn-open {
  background: var(--accent-gold);
  color: #0B0B0B;
  box-shadow: 3px 3px 0 #0B0B0B;
}
[data-theme="western"] .btn-open:hover { background: #FFD54F; box-shadow: 5px 5px 0 #0B0B0B; }
[data-theme="western"] .btn-start-run::before { content: '◉ '; }
[data-theme="western"] body.screen-shake-active::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 1000;
  pointer-events: none;
  background: radial-gradient(120% 100% at 50% 45%, #fff 0%, #FFC107 38%, #810000 78%, transparent 100%);
  animation: recoil-flash 0.4s steps(2, end) both;
}
@keyframes recoil-flash {
  0%, 12% { opacity: 0.92; }
  28% { opacity: 0; }
  100% { opacity: 0; }
}
[data-theme="western"] body.screen-shake-active .app-container {
  animation: chamber-recoil 0.4s cubic-bezier(0.2, 0.9, 0.3, 1) both;
}
@keyframes chamber-recoil {
  0% { transform: scale(1); }
  18% { transform: scale(0.94) rotateX(3deg); }
  52% { transform: scale(1.015) rotateX(-1deg); }
  100% { transform: scale(1); }
}
[data-motion="off"] body.screen-shake-active::after,
[data-motion="off"] body.screen-shake-active .app-container { animation: none; }

/* Ember field: ash/spark motes drifting up through the whole app, like
   embers rising off a burning wanted poster. Hard-edged squares (not soft
   neon dots) to stay in the brutalist/ransom-note family - each one gets a
   very small point-light blur since a flat, unblurred 3px square just
   reads as a bug rather than a spark. Ten static spans (same static-DOM
   approach as #circuitBg above) with nth-child driving the per-ember
   spread instead of per-element inline styles. */
[data-theme="western"] #emberField { opacity: 1; z-index: 1; }
[data-theme="western"] #emberField span {
  position: absolute;
  bottom: -5%;
  width: 3px; height: 3px;
  background: var(--accent-gold);
  box-shadow: 0 0 3px 1px rgba(255, 193, 7, 0.85);
  opacity: 0;
  animation: ember-rise 9s linear infinite;
}
[data-theme="western"] #emberField span:nth-child(1)  { left: 6%;  width: 2px; height: 2px; animation-duration: 7.5s; animation-delay: 0s; }
[data-theme="western"] #emberField span:nth-child(2)  { left: 16%; animation-duration: 9.5s; animation-delay: 1.1s; background: var(--accent-pink); box-shadow: 0 0 3px 1px rgba(129, 0, 0, 0.85); }
[data-theme="western"] #emberField span:nth-child(3)  { left: 27%; width: 2px; height: 2px; animation-duration: 8.2s; animation-delay: 2.4s; }
[data-theme="western"] #emberField span:nth-child(4)  { left: 38%; animation-duration: 10.5s; animation-delay: 0.6s; background: var(--accent-orange); box-shadow: 0 0 3px 1px rgba(193, 107, 44, 0.85); }
[data-theme="western"] #emberField span:nth-child(5)  { left: 49%; width: 2px; height: 2px; animation-duration: 7.8s; animation-delay: 3.5s; }
[data-theme="western"] #emberField span:nth-child(6)  { left: 60%; animation-duration: 9s;   animation-delay: 1.8s; background: var(--accent-pink); box-shadow: 0 0 3px 1px rgba(129, 0, 0, 0.85); }
[data-theme="western"] #emberField span:nth-child(7)  { left: 71%; width: 2px; height: 2px; animation-duration: 8.8s; animation-delay: 4.2s; }
[data-theme="western"] #emberField span:nth-child(8)  { left: 82%; animation-duration: 10s;  animation-delay: 0.2s; background: var(--accent-orange); box-shadow: 0 0 3px 1px rgba(193, 107, 44, 0.85); }
[data-theme="western"] #emberField span:nth-child(9)  { left: 91%; width: 2px; height: 2px; animation-duration: 7.2s; animation-delay: 2.9s; }
[data-theme="western"] #emberField span:nth-child(10) { left: 50%; animation-duration: 11s;  animation-delay: 5s; background: var(--accent-pink); box-shadow: 0 0 3px 1px rgba(129, 0, 0, 0.85); }
@keyframes ember-rise {
  0%   { transform: translate3d(0, 0, 0); opacity: 0; }
  8%   { opacity: 0.9; }
  55%  { opacity: 0.55; }
  92%  { transform: translate3d(14px, -92vh, 0); opacity: 0; }
  100% { transform: translate3d(14px, -92vh, 0); opacity: 0; }
}
/* A recoil burst speeds every ember through its rise in one sharp puff,
   the same "short and consequential over continuous" hit that the flash
   and chamber-recoil already lean on. */
[data-theme="western"] body.screen-shake-active #emberField span {
  animation-name: ember-burst;
  animation-duration: 0.6s;
  animation-delay: 0s;
  animation-timing-function: ease-out;
}
@keyframes ember-burst {
  0%   { transform: translate3d(0, 0, 0) scale(1); opacity: 0.95; }
  100% { transform: translate3d(14px, -18vh, 0) scale(0.6); opacity: 0; }
}

/* Torch-flicker: the vignette (body::after, set above) throbs irregularly
   like firelight instead of sitting flat - harsh stepped opacity jumps
   rather than a smooth glow pulse, to match the grindhouse/film-print
   aesthetic rather than a soft ambient light source. */
[data-theme="western"] body::after { animation: torch-flicker 5s steps(1, end) infinite; }
@keyframes torch-flicker {
  0%, 100% { opacity: 1; }
  8%  { opacity: 0.86; }
  17% { opacity: 1; }
  24% { opacity: 0.92; }
  40% { opacity: 1; }
  52% { opacity: 0.8; }
  61% { opacity: 1; }
  78% { opacity: 0.9; }
  86% { opacity: 1; }
}

/* Smolder: the top tier badge reads as "hot" - a slow, hard-edged (no
   blur radius change, just color) pulse between two embers of red. */
[data-theme="western"] .tier-S { animation: smolder 3.4s ease-in-out infinite; }
@keyframes smolder {
  0%, 100% { background: var(--tier-s); }
  50% { background: #C1121F; }
}

/* The hero run button's ::before/::after (chevron nudge, underline
   sweep - defined further down) are absolutely positioned, so this
   button still needs to stay a positioned ancestor even though the
   smoke-curl effect that used to live here (on a second, non-hero
   "start run" button in the Deck tab) is gone along with that button. */
[data-theme="western"] .btn-start-run { position: relative; overflow: visible; }
@keyframes smoke-curl {
  0% { transform: translate(-50%, 6px) scale(0.7); opacity: 0; }
  18% { opacity: 0.55; }
  55% { opacity: 0.32; }
  100% { transform: translate(-50%, -36px) scale(1.5); opacity: 0; }
}

/* Blood splatter burst: fires on body.collect-flash-active, set from
   collectFlash() - called from logCollection() itself, the one function
   EVERY collect path (a plain tap-to-collect, the OPEN button, a Daily
   Run step, a Discord drop) already funnels through. It was originally
   wired to body.screen-shake-active instead, which - it turns out -
   only ever gets set from the Daily Run flow (see screenShake()'s two
   call sites in the main script); a plain single-platform collect never
   triggered it at all, which is the actual reason it went unseen, not a
   quality problem with the effect itself. Circular splatter dots via
   radial-gradient, not a soft splash - flat-edged like every other mark
   in this theme - scattered across the upper screen, quick punch in and
   slow fade-settle out. Uses .app-container::before, the pseudo-slot
   not used elsewhere on this element. */
[data-theme="western"] .app-container::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 998;
  pointer-events: none;
  opacity: 0;
}
[data-theme="western"] body.collect-flash-active .app-container::before {
  opacity: 1;
  background:
    radial-gradient(circle 3px at 18% 24%, #810000 99%, transparent 100%),
    radial-gradient(circle 6px at 64% 14%, #6b0000 99%, transparent 100%),
    radial-gradient(circle 2px at 36% 9%, #810000 99%, transparent 100%),
    radial-gradient(circle 4px at 82% 28%, #6b0000 99%, transparent 100%),
    radial-gradient(circle 2px at 9% 36%, #810000 99%, transparent 100%),
    radial-gradient(circle 7px at 52% 19%, #4a0000 99%, transparent 100%),
    radial-gradient(circle 3px at 27% 41%, #6b0000 99%, transparent 100%),
    radial-gradient(circle 2px at 91% 12%, #810000 99%, transparent 100%),
    radial-gradient(circle 5px at 45% 33%, #5a0000 99%, transparent 100%),
    radial-gradient(circle 2px at 71% 38%, #810000 99%, transparent 100%);
  animation: splatter-burst 0.7s ease-out both;
}
@keyframes splatter-burst {
  0% { opacity: 0; transform: scale(0.25); }
  12% { opacity: 1; transform: scale(1.2); }
  30% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.35); }
}
[data-motion="off"] body.collect-flash-active .app-container::before { animation: none; opacity: 0; }

/* Heartbeat + attention ring: the ready-count medallion gets a lub-dub
   double-thump (pure scale) AND the pulsing hard-edged outline that
   originally sat on the Daily Run buttons - moved here per feedback,
   since a pulse meant to draw the eye reads better on the number that
   tells you there's something to do than on a button you're already
   looking at. Two separate animations (different properties, no
   conflict): heartbeat-pulse for scale, hero-number-pulse for the ring,
   which has to restate the base box-shadow every keyframe (box-shadow
   doesn't merge with an animation running - it's replaced wholesale)
   so the existing offset shadow/inset ring never drops out mid-pulse. */
[data-theme="western"] .hero-ring-circle {
  animation: heartbeat-pulse 2.4s ease-in-out infinite, hero-number-pulse 2.2s ease-in-out infinite;
}
/* Bigger badge, stronger pulse: this is now the only "run today" trigger
   in the app (the Deck tab used to have a second, identical button right
   below it competing for the same attention). With that duplicate gone,
   the ring carries the whole job of catching your eye on its own, so it
   gets more size and more glow than it needed while sharing the screen
   with a second CTA. */
[data-theme="western"] .hero-ring-wrapper { width: 92px; height: 92px; }
[data-theme="western"] .hero-ring-circle { font-size: 2rem; }
@keyframes heartbeat-pulse {
  0%, 100% { transform: scale(1); }
  14% { transform: scale(1.12); }
  28% { transform: scale(1); }
  42% { transform: scale(1.08); }
  56% { transform: scale(1); }
}
/* Three soft glow layers instead of hard-edged rings - dark red closest
   to the badge, brightening through ember-orange to gold at the outer
   edge, each layer both blurrier and more transparent than the last as
   it gets further out, so it reads as heat radiating outward rather
   than concentric outlines. Smooth ease-in-out breathing instead of the
   hard steps(2,end) on/off jump this had - a slower, softer pulse reads
   as more deliberate here than a flash would. Ties the ring to the same
   gold the CTA text gleams in, without forcing one flat color on both. */
@keyframes hero-number-pulse {
  0%, 100% {
    box-shadow: 4px 4px 0 #0B0B0B, inset 0 0 0 5px rgba(227, 218, 201, 0.18),
      0 0 3px 0px rgba(129, 0, 0, 0),
      0 0 8px 0px rgba(193, 18, 31, 0),
      0 0 14px 0px rgba(255, 193, 7, 0);
  }
  50% {
    box-shadow: 4px 4px 0 #0B0B0B, inset 0 0 0 5px rgba(227, 218, 201, 0.18),
      0 0 7px 4px rgba(129, 0, 0, 0.65),
      0 0 18px 9px rgba(193, 18, 31, 0.42),
      0 0 32px 15px rgba(255, 193, 7, 0.22);
  }
}
[data-motion="off"] [data-theme="western"] .hero-ring-circle { animation: none; }
/* Any tapped element keeps focus on mobile Chrome until something else
   takes it - accessibility.css's generic :focus/button:focus rules draw
   a desaturated cyan outline that has no business anywhere in this
   theme, and it was showing up wherever that happened to land (the hero
   ring, then .btn-run-collect staying focused for the rest of a run
   since that button element itself never gets re-created between
   steps). One global override instead of chasing it element by element -
   :focus here has higher specificity than accessibility.css's own
   :focus/button:focus/a:focus (attribute selector + pseudo-class beats
   a bare type-plus-pseudo-class) regardless of stylesheet load order.
   Recolors rather than removes it: still visible for keyboard/switch
   users, just gold instead of clashing neon. */
[data-theme="western"] :focus { outline-color: var(--accent-gold); }

/* Gold gleam text: the daily-run CTA sits inline in the details column,
   next to the ring's attention pulse - no box, no border, just the
   words themselves catching light, per feedback that the boxed bar
   fought with the ring instead of pairing with it. The slow box-shadow
   pulse this had is gone too (was reading as sluggish, not gleaming) -
   the gold text itself carries the attention now, via a tight, fast,
   continuously-looping light sweep (background-clip: text) rather than
   a periodic flash, so it reads as "gleaming metal" instead of "pulsing
   UI chrome". */
[data-theme="western"] .hero-run-btn {
  background-color: transparent;
  border: none;
  box-shadow: none;
  color: var(--accent-gold);
  /* Bigger than the base 0.85rem now that this is the app's only Daily
     Run trigger (the Deck tab's duplicate button is gone), but pulled
     back from an earlier, larger pass - the size itself doesn't need to
     carry the attention here, the motion/glow below does that job. */
  font-size: 0.92rem;
  padding: 8px 2px;
  /* Hard offset shadow, same as every other header/label in this theme -
     keeps the letters legible against the card behind them during the
     bright part of the gleam sweep - plus a warm double-layer glow under
     that (tight amber core + a wider, softer orange bloom), so the text
     pulls the eye on its own rather than needing a box. Always on,
     ready-to-collect or not: this is a "go do this" cue that should
     never read as inert, even when nothing's ready yet. */
  text-shadow: 1px 1px 0 #0B0B0B, 0 0 10px rgba(255, 193, 7, 0.8), 0 0 26px rgba(255, 140, 0, 0.5);
  background-image: linear-gradient(115deg,
    #FFC107 0%, #FFC107 34%,
    #FFF6D6 50%,
    #FFC107 66%, #FFC107 100%);
  background-repeat: no-repeat;
  background-size: 220% 100%;
  background-position: 160% 0;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: gold-text-gleam 1.3s linear infinite;
  padding-right: 20px;
}
@keyframes gold-text-gleam {
  0% { background-position: 160% 0; }
  100% { background-position: -60% 0; }
}

/* Gleaming text alone turned out not to be enough of a "press this" -
   someone using the app walked straight past it. So when there is
   actually something ready, the label picks up three cues that gold
   text on its own can't give: it breathes, it carries a chevron that
   nudges toward the tap, and a light runs along a rule beneath it, the
   way an underline marks something actionable. Still no box - the box
   is what made this read as UI chrome the first time round. All three
   are scoped to :not(:disabled), so "NOTHING READY YET" stays inert
   rather than inviting a tap that does nothing. */
[data-theme="western"] .hero-run-btn:not(:disabled) {
  /* Faster sweep, bigger breathe than the inert state gets - pulled back
     one notch from an earlier, more frantic pass per feedback. */
  animation: gold-text-gleam 1s linear infinite, run-btn-breathe 2.2s ease-in-out infinite;
  transform-origin: left center;
}
@keyframes run-btn-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.11); }
}
/* ::before and ::after have to opt out of the parent's background-clip:
   text / transparent fill, or they inherit it and paint nothing. */
[data-theme="western"] .hero-run-btn:not(:disabled)::after {
  content: '\00BB';
  position: absolute;
  right: 2px; top: 50%;
  background: none;
  -webkit-text-fill-color: var(--accent-gold);
  color: var(--accent-gold);
  font-weight: 900;
  text-shadow: 1px 1px 0 #0B0B0B, 0 0 14px rgba(255, 193, 7, 0.85);
  animation: run-chevron-nudge 1.3s ease-in-out infinite;
  pointer-events: none;
}
@keyframes run-chevron-nudge {
  0%, 100% { transform: translate(0, -50%) scale(1); opacity: 0.55; }
  50% { transform: translate(9px, -50%) scale(1.15); opacity: 1; }
}
[data-theme="western"] .hero-run-btn:not(:disabled)::before {
  content: '';
  position: absolute;
  left: 0; right: 16px; bottom: -1px; height: 3px;
  background: linear-gradient(90deg, rgba(255,193,7,0) 0%, rgba(255,193,7,0) 28%, #FFC107 50%, rgba(255,193,7,0) 72%, rgba(255,193,7,0) 100%);
  background-size: 220% 100%;
  box-shadow: 0 0 8px 1px rgba(255, 193, 7, 0.6);
  -webkit-text-fill-color: initial;
  animation: run-underline-sweep 1s linear infinite;
  pointer-events: none;
}
@keyframes run-underline-sweep {
  0% { background-position: 160% 0; }
  100% { background-position: -60% 0; }
}
[data-theme="western"] .hero-run-btn:active { box-shadow: none; }
[data-motion="off"] [data-theme="western"] .hero-run-btn,
[data-motion="off"] [data-theme="western"] .hero-run-btn:not(:disabled) {
  animation: none;
  background: none;
  transform: none;
  -webkit-text-fill-color: var(--accent-gold);
}
[data-motion="off"] [data-theme="western"] .hero-run-btn::before { animation: none; }
[data-motion="off"] [data-theme="western"] .hero-run-btn::after { animation: none; opacity: 1; transform: translate(0, -50%); }


/* Campfire flicker: the hero stat card - the single biggest visual
   block at the top of the app, on screen from the moment you land -
   gets an irregular brightness/saturation breathe, like firelight
   washing over it rather than a fixed light source. Multi-stop,
   uneven timing (not a clean sine wave) so it reads as flame, not a
   mechanical pulse. Filter-based, so it affects the whole card
   (background, text, the tier-circle decorations) as one lit surface. */
[data-theme="western"] .hero-stat-card { animation: campfire-flicker 3.6s ease-in-out infinite; }
@keyframes campfire-flicker {
  0%, 100% { filter: brightness(1) saturate(1); }
  7% { filter: brightness(1.1) saturate(1.12); }
  15% { filter: brightness(0.94) saturate(0.92); }
  26% { filter: brightness(1.14) saturate(1.18); }
  38% { filter: brightness(0.96) saturate(1); }
  47% { filter: brightness(1.08) saturate(1.08); }
  61% { filter: brightness(0.92) saturate(0.88); }
  74% { filter: brightness(1.16) saturate(1.2); }
  85% { filter: brightness(0.97) saturate(0.98); }
  93% { filter: brightness(1.05) saturate(1.04); }
}

/* Demonic smoke field: dark, soft-blurred tendrils drifting up behind
   the date/title block specifically - the "top section" - independent
   of every other effect here, so it's visible on every load, not
   contingent on an action or a state. Same static-DOM-spans approach as
   #emberField (see index.html), styled and positioned differently:
   fewer, bigger, darker, concentrated over the top ~260px instead of
   the full viewport, and blurred since smoke (unlike embers, blood,
   grain) genuinely needs softness to read as smoke. */
/* The merge filter lives on the field so it composites the plumes
   against each other; without it two overlapping plumes just stack
   their alpha and you can still read both outlines crossing. */
[data-theme="western"] #smokeField { opacity: 1; z-index: 1; filter: url(#smokeMerge); }
[data-theme="western"] #smokeField span {
  position: absolute;
  bottom: 60%;
  width: 70px; height: 100px;
  border-radius: 50%;
  /* The original colour curve, restored: the flattened, denser version
     that went with the hard threshold made these read as ink blots. The
     long transparent tail is what makes them look like smoke. Size and
     pace stay where they are - that part of the effect is right. */
  background: radial-gradient(circle, rgba(10, 9, 8, 0.85) 0%, rgba(10, 9, 8, 0.4) 45%, transparent 72%);
  filter: blur(10px);
  opacity: 0;
  animation: demon-smoke 17s ease-in infinite;
}
/* Roughly 1.7x the old durations. Smoke this size moving at the old
   pace read as drifting particles; at this speed it climbs the way
   heat actually carries it, and the slower crossings give two plumes
   time to visibly swell together before they part again. */
/* Delays are NEGATIVE: at this slower pace a positive delay means the
   field is empty for the first several seconds, which is exactly when
   someone is looking at it. A negative delay starts each plume part
   way through its own climb, so the smoke is already up and drifting
   on the first painted frame. */
[data-theme="western"] #smokeField span:nth-child(1) { left: 8%;  width: 88px;  height: 122px; animation-duration: 15s;   animation-delay: -2s; }
[data-theme="western"] #smokeField span:nth-child(2) { left: 26%; width: 70px;  height: 100px; animation-duration: 19s;   animation-delay: -9s; }
[data-theme="western"] #smokeField span:nth-child(3) { left: 46%; width: 96px;  height: 136px; animation-duration: 16.5s; animation-delay: -5s; }
[data-theme="western"] #smokeField span:nth-child(4) { left: 66%; width: 74px;  height: 104px; animation-duration: 20.5s; animation-delay: -13s; }
[data-theme="western"] #smokeField span:nth-child(5) { left: 36%; width: 62px;  height: 88px;  animation-duration: 13.5s; animation-delay: -7s; }
[data-theme="western"] #smokeField span:nth-child(6) { left: 82%; width: 84px;  height: 118px; animation-duration: 18s;   animation-delay: -16s; }
/* Grows harder on the way up (0.7 -> 2.15) so neighbouring plumes
   genuinely run into each other partway through the climb rather than
   passing as two separate columns. */
@keyframes demon-smoke {
  0% { transform: translate3d(0, 10%, 0) scale(0.7) rotate(0deg); opacity: 0; }
  16% { opacity: 0.95; }
  50% { opacity: 0.8; transform: translate3d(-12px, -55%, 0) scale(1.45) rotate(-4deg); }
  100% { transform: translate3d(18px, -140%, 0) scale(2.15) rotate(6deg); opacity: 0; }
}

/* The blood-splatter burst above uses .app-container::before - the
   full-viewport signal-corruption jolt that used to live here on
   .app-container::after ("hellscape-static") has moved to its own
   theme (Dead Channel, see the end of this file) since it's a
   different visual language from the rest of Boot Hill's smoke/ember
   palette and plenty of people never read it as an intentional
   effect in the first place. */

/* Landing-screen smoke: the same dark drifting plumes the app carries
   behind its top section (#smokeField, and the demon-smoke keyframe
   they share), but scoped to this screen and spread over its full
   height instead of a 280px band. The app's own layer sits at z-index 1
   and the landing screen at 200, so it could never have shown through
   here - this is its own element rather than a z-index fight. Sits
   under .landing-inner (z-index 2), above the screen's background. */
.landing-smoke { position: absolute; inset: 0; z-index: 1; overflow: hidden; pointer-events: none; opacity: 0; }
/* Same merge filter as #smokeField, so the landing screen's smoke
   behaves like the app's rather than being a separate-looking effect
   on the way in. */
[data-theme="western"] .landing-smoke { opacity: 1; filter: url(#smokeMerge); }
/* Denser core than #smokeField's: these plumes are bigger, and the same
   alpha spread over more area just reads as a gradient artifact against
   an already near-black backdrop rather than as smoke. */
[data-theme="western"] .landing-smoke span {
  position: absolute;
  bottom: 10%;
  width: 120px; height: 170px;
  border-radius: 50%;
  /* Same colour curve the app's plumes use, scaled for this screen. */
  background: radial-gradient(circle, rgba(6, 5, 5, 0.72) 0%, rgba(6, 5, 5, 0.36) 45%, transparent 74%);
  filter: blur(14px);
  opacity: 0;
  animation: demon-smoke 18s ease-in infinite;
}
/* Small negative delays only. The poster card covers the middle of this
   screen, so a plume more than a fifth of the way up its climb is
   hidden behind it - the smoke has to read in the band below the card,
   which means catching these early in the rise. */
[data-theme="western"] .landing-smoke span:nth-child(1) { left: 6%;  width: 140px; height: 195px; animation-duration: 17s;   animation-delay: -1s; }
[data-theme="western"] .landing-smoke span:nth-child(2) { left: 24%; width: 105px; height: 150px; animation-duration: 21s;   animation-delay: -3.4s; }
[data-theme="western"] .landing-smoke span:nth-child(3) { left: 46%; width: 150px; height: 205px; animation-duration: 18.5s; animation-delay: -2.2s; }
[data-theme="western"] .landing-smoke span:nth-child(4) { left: 68%; width: 125px; height: 175px; animation-duration: 22s;   animation-delay: -4.6s; }
[data-theme="western"] .landing-smoke span:nth-child(5) { left: 36%; width: 100px; height: 142px; animation-duration: 15s;   animation-delay: -2.8s; }
[data-theme="western"] .landing-smoke span:nth-child(6) { left: 84%; width: 135px; height: 188px; animation-duration: 19.5s; animation-delay: -5.6s; }
[data-motion="off"] [data-theme="western"] .landing-smoke span { animation: none; }

/* Burn transition: "Enter Deck" burns through with real holes, not an
   illusion - .landing-inner's mask references the SVG <mask> at
   #landingBurnMask (see index.html): a white rect for the surviving
   paper, with black circles painted over it. runBurnHoles() in the
   main script grows each circle's radius via requestAnimationFrame,
   staggered.

   Masks, not a clipPath: under both evenodd and nonzero winding a
   point inside two overlapping hole subpaths flips back to solid, so
   the clipPath version stalled around half-consumed and sprouted
   parchment islands wherever holes met. Mask circles simply paint over
   one another, so overlaps union. No smoke: an earlier heavy-smoke
   bridge into the app didn't read well and is gone entirely, along
   with the smoke plume this card itself used to give off - holes +
   char + glow carry the moment on their own now. Driven by .burning,
   added in dismissLanding() only when the theme is western and motion
   isn't off; .hidden (the existing fade) lands right after, once this
   has had time to play. */
[data-theme="western"] .landing-screen.burning {
  animation: landing-burn-glow 1.9s ease-out both;
  -webkit-mask-image: url(#landingScreenBurnMask);
  mask-image: url(#landingScreenBurnMask);
}
/* More stops than a plain fade needs, on purpose - firelight flickers
   irregularly rather than brightening on one smooth curve, echoing the
   torch-flicker hard-jolt language already used elsewhere in this
   theme instead of a clean glow ramp. */
@keyframes landing-burn-glow {
  0%   { background: radial-gradient(140% 100% at 50% 30%, #810000 0%, #3a0000 45%, #0B0B0B 90%); }
  12%  { background: radial-gradient(140% 100% at 50% 35%, #C1121F 0%, #5a0000 42%, #0B0B0B 90%); }
  22%  { background: radial-gradient(140% 100% at 50% 40%, #810000 0%, #3a0000 45%, #0B0B0B 90%); }
  34%  { background: radial-gradient(140% 100% at 50% 48%, #FF6600 0%, #810000 40%, #0B0B0B 90%); }
  46%  { background: radial-gradient(140% 100% at 50% 52%, #C1121F 0%, #5a0000 42%, #0B0B0B 90%); }
  58%  { background: radial-gradient(140% 100% at 50% 58%, #FF9500 0%, #810000 38%, #0B0B0B 88%); }
  72%  { background: radial-gradient(140% 100% at 50% 64%, #FF6600 0%, #6b0000 40%, #0B0B0B 87%); }
  86%  { background: radial-gradient(140% 100% at 50% 68%, #FF9500 0%, #810000 38%, #0B0B0B 86%); }
  100% { background: radial-gradient(140% 100% at 50% 70%, #FF6600 0%, #3a0000 40%, #0B0B0B 85%); }
}
[data-theme="western"] .landing-screen.burning .landing-inner {
  animation: landing-burn-card 1.9s ease-in forwards;
  -webkit-mask-image: url(#landingBurnMask);
  mask-image: url(#landingBurnMask);
}
/* Holds opacity almost to the end now - the holes are what should be
   taking the poster apart, so fading it out underneath them would just
   be doing the same job twice and hiding the effect that matters. It
   still chars (sepia/darken) the whole way through. */
@keyframes landing-burn-card {
  0% { filter: none; transform: rotate(-0.6deg) scale(1); opacity: 1; }
  15% { filter: sepia(0.45) brightness(1.06) contrast(1.06); }
  35% { filter: sepia(0.8) brightness(0.72) contrast(1.2); transform: rotate(-1deg) scale(0.99); }
  60% { filter: sepia(1) brightness(0.42) contrast(1.35); transform: rotate(-1.8deg) scale(0.97); }
  80% { filter: sepia(1) brightness(0.22) contrast(1.45); transform: rotate(-2.4deg) scale(0.95); }
  92% { filter: sepia(1) brightness(0.14) contrast(1.5); opacity: 1; }
  100% { filter: sepia(1) brightness(0.08) contrast(1.6) blur(2px); transform: rotate(-3deg) scale(0.92); opacity: 0; }
}
[data-theme="western"] .landing-screen.burning .landing-inner::after {
  content: '';
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 4;
  background:
    radial-gradient(circle 3px at 20% 85%, #FFC107 99%, transparent 100%),
    radial-gradient(circle 2px at 75% 90%, #810000 99%, transparent 100%),
    radial-gradient(circle 2px at 45% 95%, #FFC107 99%, transparent 100%),
    radial-gradient(circle 3px at 60% 80%, #C1121F 99%, transparent 100%),
    radial-gradient(circle 2px at 30% 92%, #FFC107 99%, transparent 100%),
    radial-gradient(circle 2px at 85% 78%, #810000 99%, transparent 100%),
    radial-gradient(circle 2px at 8% 70%, #FFC107 99%, transparent 100%),
    radial-gradient(circle 3px at 92% 62%, #FF9500 99%, transparent 100%),
    radial-gradient(circle 2px at 52% 68%, #810000 99%, transparent 100%),
    radial-gradient(circle 2px at 68% 40%, #FFC107 99%, transparent 100%),
    radial-gradient(circle 2px at 15% 45%, #C1121F 99%, transparent 100%),
    radial-gradient(circle 2px at 38% 30%, #FF9500 99%, transparent 100%);
  opacity: 0;
  animation: landing-burn-embers 1.9s ease-out forwards;
}
@keyframes landing-burn-embers {
  0%, 12% { opacity: 0; transform: translateY(0); }
  30% { opacity: 1; }
  55% { opacity: 0.75; }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-180%); }
}

/* ---------------------------------------------------------------
   Daily Run overlay: had ZERO Boot Hill treatment before this - it
   was still wearing the neon pink/cyan look built for Prism/Neon,
   the one full-screen surface this theme never touched. This is the
   "stepping into the ritual" moment (one platform at a time, full
   focus), so it gets the darkest, most macabre pass in the theme:
   near-black with an arterial-red portal vignette, a branding-iron
   avatar ring, and the collect button as the set-piece - a heavier
   echo of the smoke/ember motifs than the small nav button gets,
   since this is the one moment per run built for exactly that.
   --------------------------------------------------------------- */
[data-theme="western"] #dailyRunOverlay {
  background:
    radial-gradient(circle at 50% 8%, rgba(129, 0, 0, 0.45) 0%, transparent 45%),
    radial-gradient(circle at 50% 105%, rgba(80, 0, 0, 0.3) 0%, transparent 55%),
    #0B0B0B;
}
[data-theme="western"] .run-progress-text {
  font-family: 'Special Elite', 'Courier New', monospace;
  color: var(--accent-gold); text-shadow: 1px 1px 0 #0B0B0B; letter-spacing: 0.12em;
}
[data-theme="western"] .btn-exit-run {
  border-radius: 0; border: 2px solid #0B0B0B; background: #1E2126; color: var(--text-main);
  box-shadow: 3px 3px 0 #0B0B0B;
}
[data-theme="western"] .btn-exit-run:hover { border-color: #0B0B0B; color: var(--accent-pink); }
[data-theme="western"] .run-undo-bar {
  border-radius: 0; border: 2px solid #0B0B0B; background: #1E2126; color: var(--text-muted);
  box-shadow: 3px 3px 0 #0B0B0B;
}
[data-theme="western"] .run-undo-btn {
  border-radius: 0; border: 2px solid var(--accent-gold); color: var(--accent-gold);
}
[data-theme="western"] .run-undo-btn:active { color: #FFD54F; border-color: #FFD54F; }
[data-theme="western"] .run-balance-bar {
  border-radius: 0; border: 2px solid #0B0B0B; background: #1E2126;
  box-shadow: 3px 3px 0 #0B0B0B;
}
[data-theme="western"] .run-balance-input { border-radius: 0; border: 2px solid #0B0B0B; background: #14161A; }
[data-theme="western"] .run-balance-btn {
  border-radius: 0; border: 2px solid var(--accent-gold); color: var(--accent-gold);
}
[data-theme="western"] .run-balance-btn:active { color: #FFD54F; border-color: #FFD54F; }
[data-theme="western"] .run-progress-bar { background: #0B0B0B; border: 2px solid #0B0B0B; border-radius: 0; }
[data-theme="western"] .run-progress-fill {
  background: var(--accent-pink);
  box-shadow: none;
  animation: run-fill-pulse 1.8s ease-in-out infinite;
}
@keyframes run-fill-pulse {
  0%, 100% { background: var(--accent-pink); }
  50% { background: #C1121F; }
}
[data-theme="western"] .run-avatar {
  border-radius: 0; border: 3px double #0B0B0B;
  background: #810000; color: var(--text-main);
  font-family: 'Special Elite', monospace; text-shadow: none;
  box-shadow: 4px 4px 0 #0B0B0B, inset 0 0 0 4px rgba(227, 218, 201, 0.15);
  animation: heartbeat-pulse 2.4s ease-in-out infinite;
}
[data-theme="western"] .run-name {
  font-family: 'Special Elite', 'Courier New', monospace; text-transform: uppercase;
  color: var(--text-main); text-shadow: 2px 2px 0 var(--accent-pink);
}
[data-theme="western"] .run-redeem { color: var(--accent-gold); text-shadow: none; }
[data-theme="western"] .run-notes { color: var(--text-muted); }
[data-theme="western"] .run-cooldown-row span:first-child { color: var(--text-muted); }
[data-theme="western"] .run-bestgames { border-top: 2px solid #0B0B0B; }

/* The set-piece button: hard-edged blood-red/gold, a heavier smoke curl
   than the nav button's, and now a gleam sweep across the gold face
   itself - per feedback, this is the one button per run that most
   deserves the eye, more than the ring at the top of the screen (which
   keeps its own pulse independently). Same background-position sweep
   technique as the hero CTA's text gleam, just painted on a filled
   button face instead of clipped to text. */
[data-theme="western"] .btn-run-collect {
  border-radius: 0; border: 3px solid #0B0B0B;
  background-color: var(--accent-gold);
  background-image: linear-gradient(115deg,
    transparent 0%, transparent 38%,
    rgba(255, 255, 255, 0.9) 50%,
    transparent 62%, transparent 100%);
  background-repeat: no-repeat;
  background-size: 240% 100%;
  background-position: 160% 0;
  color: #0B0B0B;
  box-shadow: 4px 4px 0 #0B0B0B; text-shadow: none;
  position: relative; overflow: visible;
  animation: btn-collect-gleam 1.8s linear infinite;
}
@keyframes btn-collect-gleam {
  0% { background-position: 160% 0; }
  100% { background-position: -60% 0; }
}
[data-theme="western"] .btn-run-collect::after {
  content: '';
  position: absolute;
  left: 50%; top: -6px;
  width: 80%; height: 54px;
  transform: translate(-50%, 4px) scale(0.8);
  background:
    radial-gradient(circle at 25% 92%, rgba(35, 33, 30, 0.6) 0%, transparent 55%),
    radial-gradient(circle at 52% 88%, rgba(15, 13, 12, 0.55) 0%, transparent 50%),
    radial-gradient(circle at 78% 94%, rgba(50, 44, 38, 0.45) 0%, transparent 55%);
  filter: blur(6px);
  opacity: 0.4;
  pointer-events: none;
  animation: smoke-curl 4.5s ease-in infinite;
}
[data-theme="western"] .btn-skip { color: var(--text-dim); }
[data-theme="western"] .btn-skip:hover { color: var(--text-main); }
[data-motion="off"] [data-theme="western"] .run-avatar,
[data-motion="off"] [data-theme="western"] .run-progress-fill,
[data-motion="off"] [data-theme="western"] .btn-run-collect,
[data-motion="off"] [data-theme="western"] .btn-run-collect::after {
  animation: none; background-position: 0 0;
}

/* Resources tab: rebuilt as three single-purpose cards (cheat sheet /
   icon glossary / grouped outbound links) instead of one dense card -
   an information-architecture change, not a decorative one, so this
   pass is typography and hierarchy only: typewriter labels and hard
   offset text-shadow to match the rest of the theme, no card-rotation
   misregistration or ambient flicker piled on top of the restructure -
   those read as "more effects on the boxes" rather than a clearer read,
   which is exactly the note this replaces. */
[data-theme="western"] .res-brief-label,
[data-theme="western"] .res-links-label,
[data-theme="western"] .res-ext-kind {
  font-family: 'Special Elite', monospace; text-shadow: 1px 1px 0 #0B0B0B;
}
[data-theme="western"] .tactic-row { border-top-color: #0B0B0B; }
[data-theme="western"] .tactic-k { color: var(--accent-gold); font-family: 'Special Elite', monospace; }
[data-theme="western"] .tactic-full-guide { border-top-color: #0B0B0B; }
[data-theme="western"] .res-legend-list dt { color: var(--accent-gold); font-family: 'Special Elite', monospace; }
[data-theme="western"] .res-ext-title { color: var(--text-main); }
[data-theme="western"] .res-ext-go { color: var(--accent-gold); }
[data-theme="western"] .res-ext-link:hover .res-ext-go { color: #FFD54F; }

/* .strategy-row (the "Recommended Modules" expandable rows in a
   platform's detail panel and Daily Run card) never had a western
   override at all - it was leaking the hardcoded neon-cyan glow built
   for Prism/Neon into every theme that didn't explicitly override it. */
[data-theme="western"] .strategy-row-header { color: var(--accent-gold); text-shadow: none; }
[data-theme="western"] .strategy-row-body { background: rgba(11,11,11,0.5); border-top: 1px solid #0B0B0B; }


/* =========================================================
   THEME: Dead Channel ("glitch")
   Broken-CRT / signal-corruption aesthetic, built around the
   full-viewport static jolt that used to live exclusively in Boot
   Hill (as "hellscape-static") - pulled out of that theme because
   plenty of people never clocked it as an intentional effect there,
   and it deserved to be the headline of its own theme rather than a
   rare accent buried in a different one. Phosphor/acid green as the
   primary accent (the "gold" role), alarm red for tier-S and the
   danger/corruption palette, amber/cyan for A/B tiers. Sharp 4px
   corners everywhere (no pill shapes, no soft glow-only outlines
   pretending to be rounded) plus corner-bracket accents on cards,
   mimicking a terminal readout rather than neon's soft light
   sources. Chromatic-aberration titles use layered text-shadow
   offsets, not a content:attr() duplicate-layer trick - simpler,
   and it never risks the two copies of the text drifting out of
   sync with real page content changes. This is a first pass: the
   goal here is to get Dead Channel's identity right (the palette,
   the terminal shapes, and - above all - the signal-corruption
   jolt itself running more often since it's the reason this theme
   exists), not to match Boot Hill's much more heavily-iterated
   depth on day one.
   ========================================================= */

[data-theme="glitch"] body, [data-theme="glitch"] { background: #060806; }

/* Ambient scanline sweep - a single soft highlight band drifting
   down the screen on a slow loop, on top of the baked-in scanline
   texture in the theme's bodyBg. Cheap, always-on CRT-refresh cue
   that reads as "this is a screen" even in the long stretches
   between corruption jolts. */
[data-theme="glitch"] body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg, transparent 0%, rgba(57, 255, 20, 0.05) 48%, transparent 100%);
  background-size: 100% 220%;
  animation: scanline-sweep 7s linear infinite;
}
@keyframes scanline-sweep {
  0% { background-position: 0 -120%; }
  100% { background-position: 0 120%; }
}
[data-theme="glitch"] .app-container, [data-theme="glitch"] .docked-footer { position: relative; z-index: 2; }
[data-motion="off"] [data-theme="glitch"] body::after { animation: none; background-position: 0 0; }

/* Typography: solid phosphor-green fill with a hard red/cyan
   chromatic-aberration fringe instead of neon's outline-only
   text-stroke look - reads as a mis-converged CRT signal rather
   than a glow. */
[data-theme="glitch"] .app-title,
[data-theme="glitch"] .landing-title {
  font-family: 'VT323', 'Courier New', monospace;
  -webkit-text-stroke: 0;
  color: var(--accent-gold);
  text-shadow: -2px 0 0 rgba(255, 42, 42, 0.75), 2px 0 0 rgba(0, 229, 255, 0.6), 0 0 14px rgba(57, 255, 20, 0.5);
  letter-spacing: 0.02em;
}
[data-theme="glitch"] .app-title span,
[data-theme="glitch"] .landing-title span {
  -webkit-text-stroke: 0;
  color: var(--accent-pink);
  text-shadow: -2px 0 0 rgba(0, 229, 255, 0.6), 2px 0 0 rgba(57, 255, 20, 0.6), 0 0 14px rgba(255, 42, 42, 0.55);
}

/* Cards: flat terminal-window panels with hairline green edges and
   bracket accents at two opposite corners, standing in for a proper
   CRT-bezel frame without needing four extra elements per panel. */
[data-theme="glitch"] .glass-panel {
  position: relative;
  background: rgba(4, 10, 6, 0.72);
  border: 1px solid var(--glass-border);
  border-top-color: var(--glass-border);
  border-left-color: var(--glass-border);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
[data-theme="glitch"] .glass-panel::before,
[data-theme="glitch"] .glass-panel::after {
  content: '';
  position: absolute;
  width: 10px;
  height: 10px;
  pointer-events: none;
  opacity: 0.85;
}
[data-theme="glitch"] .glass-panel::before {
  top: -1px; left: -1px;
  border-top: 2px solid var(--accent-gold);
  border-left: 2px solid var(--accent-gold);
}
[data-theme="glitch"] .glass-panel::after {
  bottom: -1px; right: -1px;
  border-bottom: 2px solid var(--accent-gold);
  border-right: 2px solid var(--accent-gold);
}

/* Hero ring + Daily Run CTA: square terminal readout instead of a
   soft radial glow circle. */
[data-theme="glitch"] .hero-ring-circle {
  border-radius: 4px;
  border: 2px solid var(--accent-gold);
  background: rgba(0, 0, 0, 0.55);
  font-family: 'VT323', monospace;
  font-size: 1.9rem;
  color: var(--accent-gold);
  text-shadow: 0 0 8px rgba(57, 255, 20, 0.75);
  box-shadow: 0 0 14px rgba(57, 255, 20, 0.3), inset 0 0 10px rgba(57, 255, 20, 0.22);
}
[data-theme="glitch"] .hero-stat-card { border-radius: 4px; }
[data-theme="glitch"] .btn-start-run {
  border-radius: 4px;
  font-family: 'VT323', monospace;
  letter-spacing: 0.08em;
  font-size: 1.05rem;
}

/* Nav / filter chips: hard corners, "channel select" underline glow
   instead of a filled pill. */
[data-theme="glitch"] .nav-tab,
[data-theme="glitch"] .filter-btn,
[data-theme="glitch"] .sort-trigger-btn {
  border-radius: 4px;
}
[data-theme="glitch"] .nav-tab.active {
  background: rgba(57, 255, 20, 0.12);
  border-color: var(--accent-gold);
  color: var(--text-main);
  text-shadow: 0 0 8px var(--accent-gold);
  box-shadow: inset 0 -2px 0 var(--accent-gold);
}
[data-theme="glitch"] .filter-btn.active {
  background: var(--accent-cyan-dim);
  border-color: var(--accent-cyan);
  color: var(--text-main);
  text-shadow: 0 0 8px var(--accent-cyan);
  box-shadow: inset 0 -2px 0 var(--accent-cyan);
}

/* General buttons: black terminal fields, hairline border, no
   gradient fills - hover inverts to filled instead of just glowing
   harder, the classic "select this line" terminal cue. */
[data-theme="glitch"] .btn-open {
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--accent-pink);
  color: var(--accent-pink);
  border-radius: 4px;
  text-shadow: 0 0 6px var(--accent-pink);
  box-shadow: none;
}
[data-theme="glitch"] .btn-open:hover {
  background: var(--accent-pink);
  color: #060806;
  text-shadow: none;
  box-shadow: 0 0 18px rgba(255, 42, 42, 0.5);
  transform: none;
}
[data-theme="glitch"] .btn-open.cooldown { background: rgba(0,0,0,0.4); border-color: var(--glass-border); color: var(--text-dim); }
[data-theme="glitch"] .btn-primary {
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--accent-gold);
  color: var(--accent-gold);
  border-radius: 4px;
  text-shadow: 0 0 6px var(--accent-gold);
  box-shadow: none;
}
[data-theme="glitch"] .btn-primary:hover { background: var(--accent-gold); color: #060806; text-shadow: none; box-shadow: 0 0 18px rgba(57, 255, 20, 0.5); }
[data-theme="glitch"] .btn-run-collect {
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--accent-pink);
  color: var(--accent-pink);
  border-radius: 4px;
  text-shadow: 0 0 6px var(--accent-pink);
  box-shadow: none;
}
[data-theme="glitch"] .btn-dock {
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--accent-gold);
  color: var(--accent-gold);
  border-radius: 4px;
  text-shadow: 0 0 6px var(--accent-gold);
  box-shadow: none;
}
[data-theme="glitch"] .btn-dock:hover { background: var(--accent-gold-dim); box-shadow: 0 0 14px rgba(57, 255, 20, 0.35); }
[data-theme="glitch"] .btn-cancel { border-radius: 4px; }
[data-theme="glitch"] .btn-danger { border-radius: 4px; }
[data-theme="glitch"] .landing-btn {
  background: transparent;
  border-radius: 4px;
  border: 2px solid var(--accent-gold);
  color: var(--accent-gold);
  box-shadow: none;
  text-shadow: 0 0 8px var(--accent-gold);
}
[data-theme="glitch"] .landing-btn:hover { background: var(--accent-gold-dim); box-shadow: 0 0 18px rgba(57, 255, 20, 0.35); }

/* Avatars + tier badges: square, monospace, no soft glow ring. */
[data-theme="glitch"] .casino-avatar {
  border-radius: 4px;
  border: 2px solid var(--accent-gold);
  background: rgba(0, 0, 0, 0.6);
  font-family: 'VT323', 'Courier New', monospace;
  text-shadow: 0 0 5px var(--accent-gold);
  box-shadow: inset 0 0 10px rgba(57, 255, 20, 0.25);
}
[data-theme="glitch"] .tier-badge { border-radius: 2px; font-family: 'VT323', monospace; letter-spacing: 0.06em; box-shadow: none; }
[data-theme="glitch"] .tier-S { background: rgba(255, 42, 42, 0.18); }
[data-theme="glitch"] .tier-A { background: rgba(255, 176, 0, 0.16); }
[data-theme="glitch"] .tier-B { background: rgba(0, 229, 255, 0.16); }
[data-theme="glitch"] .tier-C { background: rgba(63, 92, 63, 0.3); }
[data-theme="glitch"] .tier-D { background: rgba(70, 70, 70, 0.3); }
[data-theme="glitch"] .status-dot { border-radius: 2px; }

[data-theme="glitch"] .docked-footer {
  background: rgba(2, 4, 2, 0.82);
  border-top: 1px solid var(--glass-border);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* Landing screen: a plain "dead air" backdrop instead of Boot
   Hill's bespoke burn-through - dismissLanding() already falls back
   to a straight .hidden toggle for every non-western theme, so all
   this theme needs is its own look for that toggle. A hard, stepped
   cut instead of the default smooth fade sells "the channel just
   changed" without any extra JS. */
[data-theme="glitch"] .landing-screen {
  background: repeating-linear-gradient(0deg, rgba(57,255,20,0.05) 0px, rgba(57,255,20,0.05) 1px, transparent 1px, transparent 3px), radial-gradient(circle at center, #0a120a 0%, #020302 100%);
  transition: opacity 0.12s steps(4, end), visibility 0.12s;
}
[data-motion="off"] [data-theme="glitch"] .landing-screen { transition: opacity 0.3s ease, visibility 0.3s; }

/* Signal corruption: the star effect this whole theme is built
   around. Same full-viewport hard-cut jolt mechanism the Boot Hill
   theme used to carry as "hellscape-static" (a repeating-gradient
   layer slammed on/off via steps(1,end), with blown-out
   brightness/contrast spikes at the peak of the jolt) - recolored to
   an alternating red/green corrupted-signal band instead of pure
   red, given a touch of hue-rotate on the hottest frames for a more
   chromatic "wrong colors" read, and - since this is now the
   headline effect instead of a rare accent - cut from a 13s cycle
   down to 6s so it fires roughly twice as often. Applied twice, same
   as before: once on .app-container::after for the main app, and
   again on .landing-screen::after so the landing screen carries the
   same atmosphere from first paint. */
[data-theme="glitch"] .app-container::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  background: repeating-linear-gradient(
    0deg,
    rgba(255, 42, 42, 0.36) 0px, rgba(255, 42, 42, 0.36) 2px,
    transparent 2px, transparent 3px,
    rgba(57, 255, 20, 0.22) 3px, rgba(57, 255, 20, 0.22) 4px,
    transparent 4px, transparent 6px
  );
  mix-blend-mode: screen;
  opacity: 0;
  animation: signal-corruption 6s steps(1, end) infinite;
}
[data-theme="glitch"] .landing-screen::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 201;
  pointer-events: none;
  background: repeating-linear-gradient(
    0deg,
    rgba(255, 42, 42, 0.36) 0px, rgba(255, 42, 42, 0.36) 2px,
    transparent 2px, transparent 3px,
    rgba(57, 255, 20, 0.22) 3px, rgba(57, 255, 20, 0.22) 4px,
    transparent 4px, transparent 6px
  );
  mix-blend-mode: screen;
  opacity: 0;
  animation: signal-corruption 6s steps(1, end) infinite;
}
@keyframes signal-corruption {
  0%, 90% { opacity: 0; transform: translate3d(0, 0, 0) skewX(0deg); filter: brightness(1); }
  90.2% { opacity: 0.6; transform: translate3d(-14px, 0, 0) skewX(0deg); filter: brightness(1); }
  90.35% { opacity: 0.1; transform: translate3d(10px, 0, 0) skewX(0deg); filter: brightness(1); }
  90.5% { opacity: 1; transform: translate3d(0, -4px, 0) skewX(-3deg); filter: brightness(2.6) contrast(1.6) hue-rotate(15deg); }
  90.65% { opacity: 0.15; transform: translate3d(-8px, 0, 0) skewX(0deg); filter: brightness(1); }
  90.85% { opacity: 0.75; transform: translate3d(7px, 3px, 0) skewX(2deg); filter: brightness(1); }
  91% { opacity: 0.1; transform: translate3d(0, 0, 0) skewX(0deg); filter: brightness(1); }
  91.2% { opacity: 1; transform: translate3d(-6px, 2px, 0) skewX(0deg); filter: brightness(2.4) contrast(1.6) hue-rotate(-10deg); }
  91.35% { opacity: 0.3; transform: translate3d(9px, -3px, 0) skewX(1deg); filter: brightness(1); }
  91.55% { opacity: 0.65; transform: translate3d(-3px, 0, 0) skewX(0deg); filter: brightness(1); }
  91.75% { opacity: 0.15; transform: translate3d(0, 0, 0) skewX(0deg); filter: brightness(1); }
  92%, 100% { opacity: 0; transform: translate3d(0, 0, 0) skewX(0deg); filter: brightness(1); }
}
[data-motion="off"] [data-theme="glitch"] .app-container::after { animation: none; opacity: 0; }
[data-motion="off"] [data-theme="glitch"] .landing-screen::after { animation: none; opacity: 0; }

/* ==========================================================================
   Tabular figures on every ticking or tabulated number
   --------------------------------------------------------------------------
   These elements re-render on a timer (the per-card countdown, the next-batch
   line, the ready ring, the ledger net) and are the only places in the app
   where a digit changing width moves the layout around it. Proportional
   figures make "9h 59m" narrower than "10h 00m", which nudges the whole
   .card-bottom-row a pixel left and right once a minute; tabular-nums locks
   every digit to one advance width so the row is dead still while the number
   changes underneath it. `slashed-zero` is along for the ride because these
   are monospace-ish readouts where 0/O ambiguity is worth removing.

   Theme-agnostic on purpose - this is a correctness property of a countdown,
   not a look, so it applies under all six themes rather than only Executive
   Lounge, which is simply the theme that made the jitter obvious.
   ========================================================================== */
.status-time,
.ready-at,
.cooldown-chip,
.next-batch,
.hero-ring-circle,
.ledger-quick-net,
.exec-countdown {
  font-variant-numeric: tabular-nums slashed-zero;
  font-feature-settings: "tnum" 1, "zero" 1;
}

/* ==========================================================================
   Neon Grid
   --------------------------------------------------------------------------
   Until this rebase the base stylesheet WAS this theme - hence 0 rules here
   before now. Restraint became the default (see BASE = EXECUTIVE LOUNGE at
   the top of this file), so what used to be baked into every selector for
   free has to be restated here to keep Neon Grid's cyberpunk identity: heavy
   glow, hollow gradient wordmark, 0.35-opacity glass at a 16px blur, and
   colour-coded box-shadows on badges and buttons. Every value below is
   exactly what the base used to render for these selectors - built with this
   theme's own tokens rather than restated literals, so it can't drift from
   [data-theme="neon"]'s vars block above if those are ever retuned. */

[data-theme="neon"] .app-title,
[data-theme="neon"] .landing-title {
  color: transparent;
  -webkit-text-stroke: 1.5px var(--accent-cyan);
  text-shadow: 0 0 15px rgba(0,229,255,0.5);
}
[data-theme="neon"] .landing-title { text-shadow: 0 0 20px var(--accent-cyan); }
[data-theme="neon"] .app-title span,
[data-theme="neon"] .landing-title span {
  color: transparent;
  -webkit-text-stroke: 1.5px var(--accent-pink);
  text-shadow: 0 0 15px rgba(255,0,127,0.5);
}
[data-theme="neon"] .landing-title span { text-shadow: 0 0 20px var(--accent-pink); }
[data-theme="neon"] .landing-subtitle { color: var(--text-main); text-shadow: 0 0 10px rgba(255,255,255,0.8); }
[data-theme="neon"] .landing-screen,
[data-theme="neon"] .landing-screen.hidden { background: radial-gradient(circle at center, #10061a 0%, #05070d 100%); }

/* Glass surfaces: brighter, more transparent, more blur than the restrained
   default - this is what "glass" meant before Executive Lounge's opaque,
   barely-blurred take. One shared declaration, same as the base gives every
   .glass-panel-family selector its look in one place. */
[data-theme="neon"] .glass-panel,
[data-theme="neon"] .hero-stat-card,
[data-theme="neon"] .catalog-search,
[data-theme="neon"] .nav-pill-group,
[data-theme="neon"] .res-brief,
[data-theme="neon"] .res-ext-link,
[data-theme="neon"] .res-legend-card,
[data-theme="neon"] .run-card,
[data-theme="neon"] .sheet-modal,
[data-theme="neon"] .sort-drawer,
[data-theme="neon"] .ledger-card {
  background: rgba(16, 22, 32, 0.35);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-top-color: var(--glass-highlight);
  border-left-color: rgba(255, 255, 255, 0.1);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
}
[data-theme="neon"] .sort-trigger-btn,
[data-theme="neon"] .sort-trigger-btn.secondary { backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); }

[data-theme="neon"] .date-header { color: var(--accent-pink); text-shadow: 0 0 10px var(--accent-pink); }
[data-theme="neon"] .form-group label { color: var(--accent-cyan); text-shadow: 0 0 5px rgba(0,229,255,0.5); }
[data-theme="neon"] .hero-details p,
[data-theme="neon"] .next-batch { color: var(--accent-cyan); text-shadow: 0 0 8px rgba(0,229,255,0.5); }
[data-theme="neon"] .strategy-row-header { color: var(--accent-cyan); text-shadow: 0 0 5px rgba(0,229,255,0.4); }
[data-theme="neon"] .sort-drawer-header,
[data-theme="neon"] .run-progress-text { color: var(--accent-cyan); text-shadow: 0 0 8px rgba(0,229,255,0.5); }
[data-theme="neon"] .notify-settings h4 { color: var(--accent-cyan); text-shadow: 0 0 8px rgba(0,229,255,0.4); }
[data-theme="neon"] .hero-details h2 { color: var(--text-main); text-shadow: 0 0 5px #fff, 0 0 15px var(--accent-orange); }
[data-theme="neon"] .keen-title { text-shadow: 0 0 8px rgba(255,0,127,0.5); }
[data-theme="neon"] .keen-info-popover { box-shadow: 0 8px 32px rgba(0,0,0,0.5), inset 0 0 20px rgba(255,0,127,0.05); }
[data-theme="neon"] .strategy-row-body { border-top-color: rgba(0,229,255,0.3); }
[data-theme="neon"] .casino-name,
[data-theme="neon"] .card-title-row .casino-name { text-shadow: 0 1px 3px rgba(0,0,0,0.8); }

[data-theme="neon"] .casino-avatar {
  border-color: var(--accent-cyan);
  box-shadow: inset 0 0 15px rgba(0,229,255,0.4), 0 0 10px rgba(0,229,255,0.3);
  text-shadow: 0 0 5px var(--accent-cyan);
}
[data-theme="neon"] .casino-avatar:active { box-shadow: inset 0 0 20px rgba(0,229,255,0.8), 0 0 15px rgba(0,229,255,0.6); }
[data-theme="neon"] .run-avatar { border-color: var(--accent-cyan); box-shadow: inset 0 0 25px rgba(0,229,255,0.4), 0 0 20px rgba(0,229,255,0.35); text-shadow: 0 0 8px var(--accent-cyan); }

[data-theme="neon"] .hero-ring-circle {
  box-shadow: 0 0 20px rgba(0,255,102,0.4), inset 0 0 15px rgba(0,255,102,0.3);
  text-shadow: 0 0 10px rgba(0,255,102,0.8);
}
[data-theme="neon"] .status-dot { box-shadow: 0 0 8px var(--accent-green), 0 0 12px var(--accent-green); }
[data-theme="neon"] .btn-start-run,
[data-theme="neon"] .btn-start-run.hero-run-btn { box-shadow: inset 0 0 15px rgba(0,255,102,0.15); text-shadow: 0 0 8px var(--accent-green); }
[data-theme="neon"] .btn-start-run:hover:not(:disabled) { box-shadow: 0 0 20px rgba(0,255,102,0.35), inset 0 0 20px rgba(0,255,102,0.3); }
[data-theme="neon"] .run-progress-fill { background: linear-gradient(90deg, var(--accent-cyan), var(--accent-green)); box-shadow: 0 0 12px rgba(0,255,102,0.6); }

/* Badges glow their own colour via currentColor, same trick the pre-rebase
   base used - one rule covers every tier without repeating five colours. */
[data-theme="neon"] .tier-badge { box-shadow: 0 0 8px currentColor; }
[data-theme="neon"] .tier-S { text-shadow: 0 0 5px var(--tier-s); }
[data-theme="neon"] .tier-A { text-shadow: 0 0 5px var(--tier-a); }
[data-theme="neon"] .tier-B { text-shadow: 0 0 5px var(--tier-b); }
[data-theme="neon"] .tier-C { text-shadow: 0 0 5px var(--tier-c); }
[data-theme="neon"] .tier-D { box-shadow: none; }
[data-theme="neon"] .tier-Unranked { box-shadow: 0 0 8px var(--text-main); }
[data-theme="neon"] .type-badge { color: var(--text-main); text-shadow: 0 0 5px var(--accent-orange); box-shadow: 0 0 8px rgba(255,102,0,0.4); }

/* Nav tabs and the sort/filter chips light up their active state instead of
   just tinting it. */
[data-theme="neon"] .nav-tab.active {
  background: rgba(255,0,127,0.15);
  color: var(--text-main);
  border-color: var(--accent-pink);
  text-shadow: 0 0 8px var(--accent-pink);
  box-shadow: 0 0 15px rgba(255,0,127,0.3), inset 0 0 10px rgba(255,0,127,0.2);
}
[data-theme="neon"] .filter-btn.active {
  background: var(--accent-cyan-dim);
  color: var(--text-main);
  border-color: var(--accent-cyan);
  text-shadow: 0 0 8px var(--accent-cyan);
  box-shadow: 0 0 12px rgba(0,229,255,0.3);
}
[data-theme="neon"] .sort-stack-chip { box-shadow: 0 0 8px rgba(255,102,0,0.2); }
[data-theme="neon"] .sort-priority-num { box-shadow: 0 0 8px var(--accent-orange); }
[data-theme="neon"] .sort-option-btn.active { text-shadow: 0 0 5px var(--accent-orange); box-shadow: inset 0 0 10px rgba(255,102,0,0.2); }
[data-theme="neon"] .btn-dock { border-color: var(--accent-cyan); color: var(--text-main); text-shadow: 0 0 5px var(--accent-cyan); box-shadow: inset 0 0 10px rgba(0,229,255,0.2); }
[data-theme="neon"] .btn-dock:hover { background: var(--accent-cyan-dim); box-shadow: 0 0 15px rgba(0,229,255,0.4), inset 0 0 15px rgba(0,229,255,0.4); }

/* Gold-flat everywhere else in the base becomes each surface's original
   lit gradient here - the CTA is the single most "neon" control in the app. */
[data-theme="neon"] .btn-open,
[data-theme="neon"] .btn-open:not(.cooldown) {
  background: linear-gradient(90deg, var(--accent-pink), var(--accent-orange));
  color: var(--text-main);
  text-shadow: 0 1px 2px rgba(0,0,0,0.5);
  box-shadow: 0 4px 15px rgba(255,0,127,0.4);
}
[data-theme="neon"] .btn-open:hover { box-shadow: 0 4px 25px rgba(255,102,0,0.6); }
[data-theme="neon"] .btn-run-collect {
  background: linear-gradient(90deg, var(--accent-pink), var(--accent-orange));
  color: var(--text-main);
  text-shadow: 0 1px 3px rgba(0,0,0,0.5);
  box-shadow: 0 6px 24px rgba(255,0,127,0.45);
}
[data-theme="neon"] .btn-primary {
  background: linear-gradient(90deg, var(--accent-cyan), var(--accent-green));
  color: #000;
  box-shadow: 0 0 20px rgba(0,255,102,0.4);
}
[data-theme="neon"] .btn-primary:hover { box-shadow: 0 0 30px rgba(0,255,102,0.6); }
[data-theme="neon"] .btn-danger { background: rgba(255,0,85,0.15); text-shadow: 0 0 5px var(--accent-pink); }
[data-theme="neon"] .btn-cancel { color: var(--text-main); }
[data-theme="neon"] .landing-btn {
  background: transparent;
  color: var(--text-main);
  border-color: var(--accent-green);
  text-shadow: 0 0 8px var(--accent-green);
  box-shadow: 0 0 20px rgba(0,255,102,0.3), inset 0 0 15px rgba(0,255,102,0.2);
}
[data-theme="neon"] .landing-btn:hover { box-shadow: 0 0 30px rgba(0,255,102,0.6), inset 0 0 20px rgba(0,255,102,0.4); }

[data-theme="neon"] .tour-tooltip-box {
  background: rgba(0,229,255,0.95);
  color: #000;
  box-shadow: 0 10px 40px rgba(0,229,255,0.5), inset 0 0 10px rgba(255,255,255,0.6);
}
[data-theme="neon"] .tour-tooltip-box::before { border-color: transparent transparent rgba(0,229,255,0.95) transparent; }
[data-theme="neon"] .tour-tooltip-box.arrow-below::before { border-color: rgba(0,229,255,0.95) transparent transparent transparent; }
[data-theme="neon"] .tour-target-active { box-shadow: 0 0 0 0 rgba(0,229,255,0.9); }
[data-theme="neon"] .tour-popover-highlight { border-color: var(--accent-cyan) !important; box-shadow: 0 0 0 3px rgba(0,229,255,0.35), 0 0 20px rgba(0,229,255,0.4) !important; }

[data-theme="neon"] .backup-controls .btn-dock { box-shadow: inset 0 0 10px rgba(0,229,255,0.2); }
/* These three also carry the shared .glass-panel class in markup (see
   index.html), which the grouped glow-restoration rule above matches with
   equal specificity - as an attribute selector it now ties .glass-panel's
   own single-class specificity, and being later in this file it would win
   that tie by source order, silently erasing each control's distinct look.
   Restated explicitly here (after that rule) to win back on purpose. */
[data-theme="neon"] .catalog-item-row.tracked {
  border-color: var(--accent-green);
  background: var(--accent-green-dim);
  box-shadow: inset 0 0 15px rgba(0,255,102,0.1);
}
[data-theme="neon"] .sort-trigger-btn { background: rgba(0,0,0,0.4); border-color: var(--accent-gold); box-shadow: none; }
[data-theme="neon"] .sort-trigger-btn.secondary { background: rgba(0,0,0,0.4); border-color: var(--glass-highlight); box-shadow: none; }
[data-theme="neon"] #dailyRunOverlay {
  background-image: radial-gradient(circle at 30% 10%, rgba(255,0,127,0.15), transparent 50%),
                     radial-gradient(circle at 70% 80%, rgba(0,229,255,0.15), transparent 50%);
}

/* ==========================================================================
   Executive Lounge
   --------------------------------------------------------------------------
   Same override strategy the Obsidian Ledger block above uses, and for the
   same reason: the base rules bake neon glow and literal rgba backgrounds in
   at the component level, so a variable swap alone can't produce a restrained
   theme. These rules strip the lighting and restate the surfaces.

   Panels are rgba(22,24,29,0.75) with backdrop-filter: blur(12px), both
   straight from the brief. An earlier pass used 0.85/6px on frame-budget
   grounds - backdrop-filter is priced per pixel per frame and this app
   scrolls a long column of panels - but at 0.75 the blur is genuinely
   visible rather than decorative, so it earns its cost. If this ever needs
   clawing back on low-end hardware, lower the radius here; don't raise the
   opacity, which is what makes the glass read as glass.
   ========================================================================== */
/* Everything this block used to restate for glass panels, the wordmark, and
   text-shadow suppression is now simply what the base looks like (Executive
   Lounge IS the base - see BASE = EXECUTIVE LOUNGE at the top of this file).
   What remains below is what's genuinely still distinct about this theme:
   choices other themes rely on the base NOT making (hero-ring-circle stays
   green in the base because Neon Grid needs it green), plus decoration the
   base was never going to carry for everyone (the metallic button gradient,
   the recessed cooldown well, the segmented filter-chip shape). */

/* Wordmark, upgraded from flat gold to a poured-metal gradient clipped to
   the text itself, plus a short gold rule underneath - the signature mark a
   private-bank logotype gets, not just a colored word. */
[data-theme="executive"] .app-title,
[data-theme="executive"] .landing-title {
  position: relative;
  padding-bottom: 16px;
}
[data-theme="executive"] .app-title span,
[data-theme="executive"] .landing-title span {
  background: var(--gold-metal);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
[data-theme="executive"] .app-title::after,
[data-theme="executive"] .landing-title::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  height: 2px;
  background: var(--gold-metal);
}
[data-theme="executive"] .app-title::after { width: 52px; }
[data-theme="executive"] .landing-title::after { width: 72px; }

/* Real glass, not a dark rounded rectangle: the base .glass-panel (0.75
   opacity, 12px blur, flat fill) reads as a solid card because it basically
   is one - at that opacity there's nothing behind it left to see, and
   nothing for backdrop-filter to actually do. Executive Lounge is the one
   theme with real light to catch (the gold + emerald glow bodyBg now
   carries), so it's the one that can afford to actually be translucent:
   - opacity down to ~0.5 and a diagonal gradient fill rather than flat,
     so the panel has its own subtle depth even before anything sits on it
   - blur nearly doubled, plus saturate() - the actual glassmorphism trick.
     A blurred, desaturated backdrop reads as a dirty smear; saturating
     what shows through first is what makes it read as glass instead
   - a brighter top/left edge and a matching dark inset on the opposite
     corner, so the card has one consistent light source rather than a
     border that's the same shade on all four sides
   - a soft gold-tinted outer glow alongside the drop shadow, so cards read
     as sitting IN the ambient light rather than punched into flat black */
[data-theme="executive"] .glass-panel {
  background: linear-gradient(160deg, rgba(36,39,47,0.58) 0%, rgba(18,20,25,0.44) 100%);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255,255,255,0.09);
  border-top: 1px solid rgba(255,255,255,0.20);
  border-left: 1px solid rgba(255,255,255,0.13);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.07) inset,
    0 -12px 20px -14px rgba(0,0,0,0.5) inset,
    0 14px 36px rgba(0,0,0,0.5),
    0 0 24px rgba(212,175,55,0.06);
}

[data-theme="executive"] .hero-ring-circle {
  border: 2px solid var(--accent-gold);
  background: rgba(0,0,0,0.38);
  /* A ready count is the clearest "money waiting" signal on the whole
     screen - the glow now scales with --ready-ratio (0-1, set in JS from
     ready/total tracked) so the ring itself carries the urgency instead of
     needing a separate label to say "this matters". */
  box-shadow:
    0 0 calc(10px + 22px * var(--ready-ratio, 0)) rgba(212, 175, 55, calc(0.14 + 0.34 * var(--ready-ratio, 0))),
    inset 0 0 10px rgba(212,175,55,0.10);
  color: var(--text-main);
  transition: box-shadow 0.6s ease;
}
[data-theme="executive"] .casino-avatar {
  border: 1px solid hsl(var(--avatar-hue, 45) 55% 58% / 0.32);
  background: radial-gradient(circle at 32% 28%, hsl(var(--avatar-hue, 45) 45% 24% / 0.6) 0%, rgba(0,0,0,0.55) 72%);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.5);
  color: var(--text-main);
}

/* Tier reads as a quiet left-edge rule, not a glowing pill - the letter is
   derived arithmetic (see data/catalog.js), so it should look like a rating,
   not an advertisement. S is the one exception: it's the tier that is
   actually worth the most, so it gets a whisper of the same warm halo the
   ready-count ring carries - still a whisper, never a neon pill. */
[data-theme="executive"] .tier-badge {
  box-shadow: none;
  border-radius: 3px;
  background: transparent;
  border: 1px solid currentColor;
  font-weight: 700;
}
[data-theme="executive"] .tier-S { color: var(--tier-s); background: rgba(212,175,55,0.10); box-shadow: 0 0 8px rgba(212,175,55,0.28); }
[data-theme="executive"] .tier-A { color: var(--tier-a); background: rgba(227,228,229,0.10); }
[data-theme="executive"] .tier-B { color: var(--tier-b); background: rgba(205,127,50,0.12); }
[data-theme="executive"] .tier-C { color: var(--tier-c); background: rgba(138,141,147,0.10); }
[data-theme="executive"] .tier-D { color: var(--tier-d); background: transparent; border-style: dashed; }

/* Gold is reserved for the one thing on a card you can actually act on -
   and now it's poured metal, not a flat swatch, with a slow specular sweep
   so the surface actually catches light instead of just sitting there gold.
   overflow:hidden clips the sweep to the button's own rounded corners. */
[data-theme="executive"] .btn-open,
[data-theme="executive"] .btn-primary,
[data-theme="executive"] .btn-run-collect {
  position: relative;
  overflow: hidden;
  background: var(--gold-metal);
  color: #14151A;
  /* The outer term is what the reference fintech screenshots actually have
     that a flat metallic fill doesn't: the button casts its own light onto
     the glass around it, instead of just sitting on top of it. */
  box-shadow: 0 1px 0 rgba(255,255,255,0.28) inset, 0 3px 10px rgba(0,0,0,0.5), 0 6px 24px rgba(212,175,55,0.28);
}
[data-theme="executive"] .btn-open { border: 1px solid rgba(255,255,255,0.18); font-weight: 800; }
[data-theme="executive"] .btn-open:hover,
[data-theme="executive"] .btn-primary:hover { box-shadow: 0 1px 0 rgba(255,255,255,0.35) inset, 0 5px 16px rgba(0,0,0,0.6), 0 8px 30px rgba(212,175,55,0.4); }
[data-theme="executive"] .btn-open::after,
[data-theme="executive"] .btn-primary::after,
[data-theme="executive"] .btn-run-collect::after {
  content: '';
  position: absolute;
  top: 0; left: -60%;
  width: 34%; height: 100%;
  background: linear-gradient(115deg, transparent 0%, rgba(255,255,255,0.55) 50%, transparent 100%);
  transform: skewX(-20deg);
  animation: gold-sheen 4.5s linear infinite;
  pointer-events: none;
}
[data-theme="executive"] .btn-primary::after { animation-delay: 1.5s; }
[data-theme="executive"] .btn-run-collect::after { animation-delay: 3s; }
/* A straight 0%->100% sweep, no repeated keyframe value anywhere in
   between. The previous version held the streak still at each end (0-8%
   and 38-100% both pinned to the same `left`), which reads as exactly what
   it was: motion that stops and waits rather than one continuous pass -
   the "barely appears, pauses, then catches up" effect. linear timing
   keeps the speed constant through the loop point too, so the seam where
   one pass ends and the next begins doesn't have a visible flicker of
   acceleration the way ease-in-out would give it. */
@keyframes gold-sheen {
  0% { left: -60%; }
  100% { left: 130%; }
}
/* Global animation kill switch (html[data-motion="off"] *) already covers
   this - restated per the pattern the rest of this file follows, so an
   audit of "what does motion-off actually silence" doesn't have to trust
   an ancestor rule it can't see from here. */
[data-motion="off"] [data-theme="executive"] .btn-open::after,
[data-motion="off"] [data-theme="executive"] .btn-primary::after,
[data-motion="off"] [data-theme="executive"] .btn-run-collect::after { animation: none; opacity: 0; }

/* A platform on cooldown gets the recessed well instead: inset shadow, no
   fill, muted text. Not-yet-actionable should look pressed into the card. */
[data-theme="executive"] .btn-open.cooldown {
  background: rgba(0,0,0,0.42);
  border: 1px solid rgba(0,0,0,0.6);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.75), 0 1px 0 rgba(255,255,255,0.04);
  color: var(--text-muted);
}
[data-theme="executive"] .btn-open.cooldown::after { display: none; }

/* .btn-check (Zz snooze, checkmark mark-collected) never had an executive
   override - it was inheriting the theme-agnostic base rule verbatim:
   transparent fill, --text-muted glyph, a hairline border at 0.08 alpha.
   That was already low-contrast against the old flat-black card; against
   the new translucent, gradient-filled glass card it's worse; a grey glyph
   on a semi-transparent backdrop over more glass has nothing to separate
   it from what's behind it. Same recessed-well language as
   .btn-open.cooldown above (this theme already has that vocabulary), but
   with a bright glyph rather than a muted one - these are always tappable,
   never a "not yet available" state, so they shouldn't read as dimmed. */
[data-theme="executive"] .btn-check {
  background: rgba(0,0,0,0.4);
  border: 1px solid rgba(0,0,0,0.55);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.7), 0 1px 0 rgba(255,255,255,0.05);
  color: var(--text-main);
}
[data-theme="executive"] .btn-check:hover {
  border-color: var(--accent-gold);
  color: var(--accent-gold);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.7), 0 0 0 1px rgba(212,175,55,0.15);
}

/* Cooldown fill bar: money accruing toward ready, not a generic orange
   loading bar - it counts up in the same metal as everything else worth
   having. */
[data-theme="executive"] .cd-fill { background: var(--gold-metal); opacity: 0.85; }

/* Segmented control: the sort/filter chips read as one connected switch
   rather than six separate buttons. */
[data-theme="executive"] .filter-btn {
  background: rgba(0,0,0,0.35);
  border-radius: 8px;
  border-color: var(--glass-border);
}
[data-theme="executive"] .cooldown-chip { border-radius: 4px; }

[data-theme="executive"] .hero-stat-card { background: linear-gradient(160deg, rgba(36,39,47,0.5) 0%, rgba(18,20,25,0.38) 100%); }

[data-theme="executive"] .docked-footer {
  background: rgba(11,12,16,0.92);
  border-top-color: var(--glass-border);
  box-shadow: 0 -6px 20px rgba(0,0,0,0.6);
}

/* .landing-screen is position:fixed; inset:0 - a full-viewport layer that
   sits on top of and completely hides whatever body carries underneath it.
   The old flat, colorless radial here meant the landing screen stayed pure
   black no matter what the gold/emerald ambient glow in bodyBg was doing -
   this is the surface a first-time visitor sees before anything else, so
   it gets the same two-tone glow rather than its own disconnected one. */
/* Two soft glows fading straight into --bg-base, no separate vignette
   shape in between - the same recipe THEMES.executive.bodyBg already uses
   successfully for the app itself (see index.html). The vignette that used
   to sit here (radial-gradient(circle at 50% 35%, #101218 0%, #050507 65%,
   #030304 100%)) was a third, independently-edged shape UNDER the two
   glows - close, low-contrast colour stops that band on a real display,
   and a boundary that doesn't line up with either glow's own falloff, so
   it read as a stacked layer rather than one light source. Sizing in
   vmin/px rather than the glows' old %-of-box units too: percentages
   stretch a shape tuned for a ~390px phone into something enormous and
   misshapen on a desktop-width window, which is the other half of "not
   so nice on computer" - vmin keeps the glow's actual size consistent
   regardless of viewport width. */
[data-theme="executive"] .landing-screen {
  background:
    radial-gradient(min(70vmin, 620px) min(50vmin, 460px) at 12% 0%, rgba(212,175,55,0.26) 0%, transparent 72%),
    radial-gradient(min(65vmin, 560px) min(48vmin, 420px) at 100% 100%, rgba(63,191,143,0.19) 0%, transparent 74%),
    var(--bg-base);
}
/* base's own .landing-btn is a filled gold button (see the base rule up top) -
   Executive Lounge's is the outline/ghost version instead, so background has
   to be reclaimed explicitly or gold text lands on a gold fill. */
[data-theme="executive"] .landing-btn { background: transparent; box-shadow: none; border-color: var(--accent-gold); color: var(--accent-gold); }
[data-theme="executive"] .landing-btn:hover { background: var(--accent-gold-dim); box-shadow: none; }

[data-theme="executive"] .keen-info-popover {
  border-style: solid;
  border-color: var(--glass-border);
  box-shadow: 0 4px 16px rgba(0,0,0,0.55);
}

/* The onboarding tour reads as a still gold callout rather than a pulsing
   cyan flare - restraint extends to motion, not just colour. */
[data-theme="executive"] .tour-target-active { animation: none !important; box-shadow: 0 0 0 2px var(--accent-gold) !important; }

/* ====================================================================
   EXECUTIVE LOUNGE: AMPED

   Same brief, same tokens (THEMES.amped.vars in index.html is
   byte-identical to executive's - tier colour still means the same thing
   in both), turned all the way up. Executive Lounge's argument for
   "expensive" is restraint; this is the other argument for it - motion
   and light everywhere the quiet version holds back. Every selector here
   is its own full rule rather than a delta on top of [data-theme=
   "executive"], because [data-theme="X"] and [data-theme="Y"] never
   cascade into each other - same reason every other theme block in this
   file is self-contained.

   html[data-motion="off"] * already kills every animation added here
   (see assets/app.css's global kill switch) - no per-rule guard needed,
   verified the same way the Chainsaw gore pass was.
   ==================================================================== */

/* Wordmark: same poured-metal gradient-clip as Executive, but the gradient
   itself now sweeps across the letters instead of sitting still. */
[data-theme="amped"] .app-title,
[data-theme="amped"] .landing-title {
  position: relative;
  padding-bottom: 16px;
}
[data-theme="amped"] .app-title span,
[data-theme="amped"] .landing-title span {
  background: linear-gradient(110deg, #A87A22 0%, #F3DA92 25%, #D4AF37 50%, #F3DA92 75%, #A87A22 100%);
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: amped-wordmark-shimmer 5s linear infinite;
}
@keyframes amped-wordmark-shimmer {
  0% { background-position: 0% 50%; }
  100% { background-position: -250% 50%; }
}
[data-theme="amped"] .app-title::after,
[data-theme="amped"] .landing-title::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  height: 2px;
  background: var(--gold-metal);
  box-shadow: 0 0 12px rgba(212,175,55,0.6);
}
[data-theme="amped"] .app-title::after { width: 52px; }
[data-theme="amped"] .landing-title::after { width: 72px; }

/* Glass panels: blur/saturate pushed further than Executive's own, plus a
   specular sweep that actually crosses the surface on a loop rather than
   sitting there as a static highlight - the "glass catches light" idea
   Executive only implies, made literal and continuous. */
[data-theme="amped"] .glass-panel {
  position: relative;
  overflow: hidden;
  background: linear-gradient(160deg, rgba(42,38,52,0.62) 0%, rgba(18,20,25,0.40) 100%);
  backdrop-filter: blur(28px) saturate(185%);
  -webkit-backdrop-filter: blur(28px) saturate(185%);
  border: 1px solid rgba(255,255,255,0.12);
  border-top: 1px solid rgba(255,255,255,0.28);
  border-left: 1px solid rgba(255,255,255,0.18);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.10) inset,
    0 -12px 20px -14px rgba(0,0,0,0.5) inset,
    0 16px 40px rgba(0,0,0,0.55),
    0 0 32px rgba(212,175,55,0.14);
}
/* Deliberately NOT the buttons' gold-sheen - a card is glass, a button is
   polished metal, and giving both the same tight bright streak made every
   translucent surface in the app read as the same material. Buttons keep
   the hard, fast, bright metallic glint (it's supposed to look like
   something you'd press). Cards get something a glass surface would
   actually do: a soft, blurred, low-contrast highlight that drifts slowly
   rather than sweeps - less "a light passed over this" and more "light is
   coming through this". Ping-pong (0%/100% share a value, 50% doesn't) is
   genuine continuous back-and-forth motion, not the held-still bug fixed
   above on gold-sheen - there's a distinct value at every point except the
   shared loop seam. */
[data-theme="amped"] .glass-panel::before {
  content: '';
  position: absolute;
  top: 5%; left: -20%;
  width: 55%; height: 90%;
  background: radial-gradient(ellipse at center, rgba(255,255,255,0.13) 0%, transparent 70%);
  filter: blur(10px);
  animation: amped-panel-drift 10s ease-in-out infinite;
  pointer-events: none;
}
/* A little stagger on the deck's own cards, so 137 of them don't drift in
   lockstep - reads as ambient light shifting across the room, not a wave. */
[data-theme="amped"] .ledger-card:nth-child(2n)::before { animation-delay: 3.3s; }
[data-theme="amped"] .ledger-card:nth-child(3n)::before { animation-delay: 6.6s; }
@keyframes amped-panel-drift {
  0%, 100% { transform: translate(0%, 0%); }
  50% { transform: translate(220%, 15%); }
}
[data-theme="amped"] .hero-stat-card { background: linear-gradient(160deg, rgba(42,38,52,0.54) 0%, rgba(18,20,25,0.34) 100%); }

/* Hero ring: a rotating gold halo behind it, a breathing pulse that quickens
   as more of the deck comes ready (same --ready-ratio Executive's glow
   scales off), and a one-shot burst (.ring-pulse, toggled from JS in
   updateHeroStats() whenever the ready count ticks up) for the moment
   something actually becomes collectible. */
[data-theme="amped"] .hero-ring-wrapper::before {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  background: conic-gradient(from 0deg, var(--accent-gold), transparent 30%, var(--accent-gold) 60%, transparent 90%, var(--accent-gold));
  filter: blur(3px);
  animation: amped-ring-spin 4s linear infinite;
  z-index: 0;
}
@keyframes amped-ring-spin { to { transform: rotate(360deg); } }
[data-theme="amped"] .hero-ring-circle {
  position: relative;
  z-index: 1;
  border: 2px solid var(--accent-gold);
  background: rgba(0,0,0,0.42);
  color: var(--text-main);
  box-shadow:
    0 0 calc(14px + 34px * var(--ready-ratio, 0)) rgba(212, 175, 55, calc(0.22 + 0.45 * var(--ready-ratio, 0))),
    inset 0 0 14px rgba(212,175,55,0.16);
  animation: amped-ring-breathe calc(3.2s - 1.4s * var(--ready-ratio, 0)) ease-in-out infinite;
}
@keyframes amped-ring-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.035); }
}
[data-theme="amped"] .hero-ring-circle.ring-pulse { animation: amped-ring-burst 0.8s ease-out; }
@keyframes amped-ring-burst {
  0% { box-shadow: 0 0 0 0 rgba(212,175,55,0.55), inset 0 0 14px rgba(212,175,55,0.16); }
  60% { box-shadow: 0 0 0 22px rgba(212,175,55,0), inset 0 0 14px rgba(212,175,55,0.16); }
  100% { box-shadow: 0 0 0 0 rgba(212,175,55,0), inset 0 0 14px rgba(212,175,55,0.16); }
}

/* Avatars: the hue border becomes a hue glow - same per-name colour as
   Executive, just lit rather than merely outlined. */
[data-theme="amped"] .casino-avatar {
  border: 1px solid hsl(var(--avatar-hue, 45) 70% 62% / 0.55);
  background: radial-gradient(circle at 32% 28%, hsl(var(--avatar-hue, 45) 55% 30% / 0.75) 0%, rgba(0,0,0,0.5) 72%);
  box-shadow: 0 0 14px hsl(var(--avatar-hue, 45) 70% 55% / 0.35), inset 0 1px 2px rgba(0,0,0,0.5);
  color: var(--text-main);
}

/* Tier: S keeps Executive's whisper-of-halo idea but lets it breathe -
   still the only tier that glows, still never a neon pill. */
[data-theme="amped"] .tier-badge {
  box-shadow: none;
  border-radius: 3px;
  background: transparent;
  border: 1px solid currentColor;
  font-weight: 700;
}
[data-theme="amped"] .tier-S {
  color: var(--tier-s);
  background: rgba(212,175,55,0.16);
  animation: amped-tier-s-pulse 2.4s ease-in-out infinite;
}
@keyframes amped-tier-s-pulse {
  0%, 100% { box-shadow: 0 0 10px rgba(212,175,55,0.4); }
  50% { box-shadow: 0 0 18px rgba(212,175,55,0.65); }
}
[data-theme="amped"] .tier-A { color: var(--tier-a); background: rgba(227,228,229,0.14); box-shadow: 0 0 8px rgba(227,228,229,0.25); }
[data-theme="amped"] .tier-B { color: var(--tier-b); background: rgba(205,127,50,0.16); box-shadow: 0 0 8px rgba(205,127,50,0.25); }
[data-theme="amped"] .tier-C { color: var(--tier-c); background: rgba(138,141,147,0.12); }
[data-theme="amped"] .tier-D { color: var(--tier-d); background: transparent; border-style: dashed; }

/* Primary buttons: the gold-sheen sweep runs more than twice as often as
   Executive's, plus a glow that breathes at rest instead of only lighting
   up on hover - the button never fully stops casting light. */
[data-theme="amped"] .btn-open,
[data-theme="amped"] .btn-primary,
[data-theme="amped"] .btn-run-collect {
  position: relative;
  overflow: hidden;
  background: var(--gold-metal);
  color: #14151A;
  animation: amped-btn-glow-pulse 2.6s ease-in-out infinite;
}
@keyframes amped-btn-glow-pulse {
  0%, 100% { box-shadow: 0 1px 0 rgba(255,255,255,0.32) inset, 0 3px 12px rgba(0,0,0,0.55), 0 8px 32px rgba(212,175,55,0.42); }
  50% { box-shadow: 0 1px 0 rgba(255,255,255,0.32) inset, 0 3px 12px rgba(0,0,0,0.55), 0 10px 40px rgba(212,175,55,0.68); }
}
[data-theme="amped"] .btn-open { border: 1px solid rgba(255,255,255,0.22); font-weight: 800; }
[data-theme="amped"] .btn-open:hover,
[data-theme="amped"] .btn-primary:hover { box-shadow: 0 1px 0 rgba(255,255,255,0.4) inset, 0 5px 18px rgba(0,0,0,0.6), 0 10px 40px rgba(212,175,55,0.55); }
[data-theme="amped"] .btn-open::after,
[data-theme="amped"] .btn-primary::after,
[data-theme="amped"] .btn-run-collect::after {
  content: '';
  position: absolute;
  top: 0; left: -60%;
  width: 34%; height: 100%;
  background: linear-gradient(115deg, transparent 0%, rgba(255,255,255,0.75) 50%, transparent 100%);
  transform: skewX(-20deg);
  animation: gold-sheen 2s linear infinite;
  pointer-events: none;
}
[data-theme="amped"] .btn-primary::after { animation-delay: 0.67s; }
[data-theme="amped"] .btn-run-collect::after { animation-delay: 1.33s; }
[data-motion="off"] [data-theme="amped"] .btn-open::after,
[data-motion="off"] [data-theme="amped"] .btn-primary::after,
[data-motion="off"] [data-theme="amped"] .btn-run-collect::after { animation: none; opacity: 0; }

[data-theme="amped"] .btn-open.cooldown {
  background: rgba(0,0,0,0.42);
  border: 1px solid rgba(0,0,0,0.6);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.75), 0 1px 0 rgba(255,255,255,0.04);
  color: var(--text-muted);
}
[data-theme="amped"] .btn-open.cooldown::after { display: none; }

[data-theme="amped"] .btn-check {
  background: rgba(0,0,0,0.42);
  border: 1px solid rgba(0,0,0,0.6);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.75), 0 1px 0 rgba(255,255,255,0.06);
  color: var(--text-main);
}
[data-theme="amped"] .btn-check:hover {
  border-color: var(--accent-gold);
  color: var(--accent-gold);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.75), 0 0 10px rgba(212,175,55,0.35);
}

[data-theme="amped"] .cd-fill { background: var(--gold-metal); opacity: 0.9; }

[data-theme="amped"] .filter-btn {
  background: rgba(0,0,0,0.35);
  border-radius: 8px;
  border-color: var(--glass-border);
}
[data-theme="amped"] .cooldown-chip { border-radius: 4px; }

[data-theme="amped"] .docked-footer {
  background: rgba(11,12,16,0.92);
  border-top-color: var(--glass-border);
  box-shadow: 0 -6px 24px rgba(212,175,55,0.15), 0 -6px 20px rgba(0,0,0,0.6);
}

/* Landing, and the daily-run overlay: both position:fixed;inset:0, both
   fully occlude body - same lesson from Executive's own landing-screen fix
   (see assets/app.css history), so each gets its own copy of the ambient
   mesh below rather than relying on whatever body is doing underneath. */
/* Same fix as Executive's own landing-screen (see its comment above): two
   glows straight into --bg-base, vmin/px-capped sizing instead of
   %-of-box, no separate vignette shape fighting them for an edge. Amped
   still gets the extra animated mesh on ::before on top of this. */
[data-theme="amped"] .landing-screen {
  background:
    radial-gradient(min(72vmin, 640px) min(52vmin, 480px) at 12% 0%, rgba(212,175,55,0.34) 0%, transparent 74%),
    radial-gradient(min(68vmin, 580px) min(50vmin, 440px) at 100% 100%, rgba(63,191,143,0.27) 0%, transparent 76%),
    var(--bg-base);
}
[data-theme="amped"] .landing-btn { background: transparent; box-shadow: 0 0 0 1px rgba(212,175,55,0.15); border-color: var(--accent-gold); color: var(--accent-gold); }
[data-theme="amped"] .landing-btn:hover { background: var(--accent-gold-dim); box-shadow: 0 0 16px rgba(212,175,55,0.35); }

[data-theme="amped"] .keen-info-popover {
  border-style: solid;
  border-color: var(--glass-border);
  box-shadow: 0 4px 16px rgba(0,0,0,0.55);
}

/* Tour stays still even here - a pulsing highlight fighting a pulsing S-tier
   badge for attention would defeat the tour's own job of pointing at one
   thing, so restraint applies to this one surface regardless of theme. */
[data-theme="amped"] .tour-target-active { animation: none !important; box-shadow: 0 0 0 2px var(--accent-gold) !important; }

/* Ambient mesh: a three-colour glow behind everything that actually drifts
   and shifts hue, on its own ::before rather than folded into body's
   background, because applyTheme() writes body.style.background as an
   inline SHORTHAND (documented on THEMES.executive.bodyBg above) - any
   animation on a CSS background property there would be inline-overridden
   the instant the theme applies, silently. A pseudo-element has no inline
   style for JS to ever touch, so it's the only surface here JS can't stomp
   on. z-index:-1 keeps it under each layer's own real content while still
   painting above that layer's own background (negative z-index paints
   above a stacking context's own background, below its normal-flow
   content - not "the very bottom of the page"). Same three inset:0 layers
   Executive's own landing-screen fix had to account for: body, the landing
   screen, and the daily-run overlay each occlude whatever is under them,
   so each needs its own copy.

   position differs by layer on purpose. body itself is the outermost
   element on the page, so body::before as position:fixed has no ancestor
   that's also fixed - no ambiguity there. .landing-screen and
   #dailyRunOverlay are ALREADY position:fixed;inset:0 themselves, so their
   ::before uses position:absolute instead: it resolves against that
   already-fixed parent and covers it exactly the same, but sidesteps a
   real class of mobile WebKit bug where a fixed-position element nested
   inside another fixed-position element can fail to paint at all - which
   is the likely reason this mesh was invisible on a real phone even though
   headless Chromium (used for this file's own verification) rendered it
   fine; headless Chromium doesn't reproduce that bug. */
[data-theme="amped"] body::before,
[data-theme="amped"] .landing-screen::before,
[data-theme="amped"] #dailyRunOverlay::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(55% 48% at 18% 18%, rgba(212,175,55,0.42) 0%, transparent 65%),
    radial-gradient(52% 45% at 85% 78%, rgba(63,191,143,0.34) 0%, transparent 66%),
    radial-gradient(48% 40% at 88% 12%, rgba(79,216,232,0.26) 0%, transparent 64%);
  background-size: 220% 220%;
  animation: amped-mesh-drift 14s ease-in-out infinite, amped-mesh-hue 19s linear infinite;
}
[data-theme="amped"] .landing-screen::before,
[data-theme="amped"] #dailyRunOverlay::before {
  position: absolute;
}
/* A real sweep across a much wider range than before (the previous version
   moved each blob by ~15-20 percentage points over 22s, which is well
   below what a glance can register as motion rather than a static image) -
   this one visibly relocates each glow across a third of the screen and
   completes a pass in 14s. Distinct start/mid/end values throughout, so
   there's no flat hold anywhere in the loop either. */
@keyframes amped-mesh-drift {
  0% { background-position: 5% 10%, 95% 90%, 92% 8%; }
  50% { background-position: 45% 55%, 55% 40%, 40% 60%; }
  100% { background-position: 5% 10%, 95% 90%, 92% 8%; }
}
/* Layered on top of the position drift - the three glows also slowly cycle
   hue, which reads as actual colour "swirl" rather than just three fixed
   colours sliding around. Cheap (one filter on one fullscreen layer). */
@keyframes amped-mesh-hue {
  0% { filter: hue-rotate(0deg); }
  100% { filter: hue-rotate(360deg); }
}

/* Nav-tab glyphs. Stacked above the label rather than beside it: an inline
   icon adds ~20px per tab, which four tabs cannot afford at 320px, while a
   stacked one costs no horizontal space at all.

   fill="currentColor" is the whole point - the glyph inherits whatever the
   active theme has set on .nav-tab, so Executive Lounge renders it gold,
   Boot Hill blood red and Dead Channel acid green with no per-theme rule. */
.tab-ico { flex-shrink: 0; display: block; }
.nav-tab > span { line-height: 1.1; }
