:root{
    --bg:#070912;
    --bg2:#0c1024;
    --cyan:#3ff0ff;
    --cyan-dim:#1a6b78;
    --magenta:#ff3fb0;
    --gold:#ffd23f;
    --red:#ff4757;
    --green:#3fff9e;
    --panel:#0e1330;
    --panel-line:#2a3570;
    --text:#dfe6ff;
    --text-dim:#7d88b8;
    /* ---- In-gameplay HUD only (topBar, weapon/ability tray, boss bars, mode badge) ----
       A distinct palette from the cyan/magenta "ship computer" look the menus/overlays use —
       cold gunmetal panels with a warm amber glow, angular cut-corner shapes, and thin scanline
       texture, closer to Dead Space's RIG display than this game's usual neon menu chrome. */
    --ds-amber:#ff9142;
    --ds-amber-dim:#b8621f;
    --ds-panel:rgba(11,9,7,0.82);
    --ds-panel-line:rgba(255,145,66,0.4);
    --ds-glow:rgba(255,145,66,0.35);
  }
  *{box-sizing:border-box; -webkit-tap-highlight-color:transparent;}
  html,body{
    margin:0; padding:0; width:100%; height:100%; overflow:hidden;
    background:var(--bg);
    font-family:'Segoe UI', 'Trebuchet MS', Arial, sans-serif;
    color:var(--text);
    user-select:none;
    touch-action:none;
    overscroll-behavior:none;
  }
  #gameContainer{
    position:relative; width:100vw; height:100vh;
    display:flex; align-items:center; justify-content:center;
    background:
      radial-gradient(ellipse at 30% 20%, rgba(63,240,255,0.06), transparent 55%),
      radial-gradient(ellipse at 80% 80%, rgba(255,63,176,0.05), transparent 55%),
      var(--bg);
  }
  canvas{display:block; background:transparent; touch-action:none;}
  /* Colorblind assist: not clinical correction (that needs real per-pixel processing), just a
     deliberate hue-separation + contrast/saturation boost so commonly-confused hues in this
     game's palette (reds/purples/pinks, cyans/whites) sit further apart perceptually. */
  #game.cvd-protanopia{filter:hue-rotate(18deg) saturate(1.45) contrast(1.12);}
  #game.cvd-deuteranopia{filter:hue-rotate(-16deg) saturate(1.45) contrast(1.12);}
  #game.cvd-tritanopia{filter:hue-rotate(48deg) saturate(1.3) contrast(1.1);}

  .hud{
    position:absolute; top:0; left:0; width:100%; height:100%;
    pointer-events:none; z-index:10;
  }
  .hud > *{pointer-events:auto;}

  /* Top bar — right inset leaves room for #pauseBtn, which is no longer part of this flex row
     (see .hud markup): it used to be the row's last flex child and could get squeezed off-screen
     entirely on narrow phones once the row ran out of space (see the old comment in the mobile
     media query below), which was silently making it untappable there. Positioning it independently
     means it's always exactly where a player expects a pause button to be and can never be pushed
     out of reach by however much other HUD content is in this row. */
  #topBar{
    position:absolute; top:14px; left:14px; right:68px;
    display:flex; align-items:center; gap:16px;
    pointer-events:none;
  }
  /* Dead-Space-style RIG panel: angular cut corners instead of rounded ones, a dark gunmetal
     body, amber edge glow, and a faint scanline texture — the look every gameplay HUD element
     below shares, standing apart from the cyan "ship computer" look of the menus/overlays. */
  .barWrap{
    flex:1; height:20px; background:var(--ds-panel);
    border:1px solid var(--ds-panel-line); overflow:hidden;
    position:relative; box-shadow:0 0 10px var(--ds-glow) inset;
    clip-path:polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px);
    background-image:repeating-linear-gradient(0deg, rgba(255,255,255,0.05) 0px, rgba(255,255,255,0.05) 1px, transparent 1px, transparent 4px);
  }
  .barFill{height:100%; width:50%; transition:width 0.15s ease-out; position:relative;}
  #hpFill{background:linear-gradient(90deg, #b8250f, var(--ds-amber)); box-shadow:0 0 10px #c9491f;}
  #xpFill{background:linear-gradient(90deg, var(--ds-amber-dim), var(--ds-amber)); box-shadow:0 0 10px var(--ds-amber);}
  /* Segmented tick marks over the fill — the RIG bar reads as discrete armor segments depleting,
     not a smooth gradient wipe. A repeating dark stripe every few px sells that with zero markup. */
  .barFill::after{
    content:''; position:absolute; inset:0;
    background-image:repeating-linear-gradient(90deg, transparent 0px, transparent 9px, rgba(0,0,0,0.55) 9px, rgba(0,0,0,0.55) 11px);
  }
  .barLabel{
    position:absolute; top:50%; left:8px; transform:translateY(-50%);
    font-size:11px; font-weight:700; letter-spacing:1px; color:#fff;
    text-shadow:0 1px 3px rgba(0,0,0,0.8); z-index:2;
  }
  .statCluster{display:flex; flex-direction:column; gap:6px; min-width:150px;}
  #levelBadge{
    display:flex; align-items:center; gap:8px; font-size:13px; font-weight:700;
    color:var(--ds-amber); text-shadow:0 0 8px var(--ds-glow);
  }
  #timerDisplay{font-size:20px; font-weight:800; letter-spacing:2px; text-align:right; color:#fff; text-shadow:0 0 10px var(--ds-glow);}
  #killCount{font-size:12px; color:var(--text-dim); text-align:right;}

  #pauseBtn{
    position:absolute; top:14px; right:14px; z-index:12; pointer-events:auto;
    width:44px; height:44px; border:1px solid var(--ds-panel-line);
    background:var(--ds-panel); color:var(--ds-amber); font-size:17px; cursor:pointer;
    display:flex; align-items:center; justify-content:center;
    clip-path:polygon(8px 0, 100% 0, 100% 100%, 0 100%, 0 8px);
    box-shadow:0 0 8px var(--ds-glow) inset;
  }

  /* Persistent music player overlay — sits above every screen (menu, gameplay, pause, game over) */
  #musicPlayer{
    position:absolute; top:64px; right:14px; z-index:200;
    display:flex; align-items:center; gap:6px;
    background:rgba(10,14,30,0.85); border:1px solid var(--panel-line); border-radius:10px;
    padding:6px 8px; box-shadow:0 0 12px rgba(63,240,255,0.12);
    max-width:min(64vw, 260px); pointer-events:auto;
    cursor:grab; touch-action:none;
  }
  #musicPlayer.dragging{ cursor:grabbing; opacity:0.85; box-shadow:0 0 18px rgba(63,240,255,0.3); }
  #musicPlayerTrack{
    font-size:10px; color:var(--text-dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
    max-width:112px; margin-right:2px;
  }
  .musicBtn{
    width:26px; height:26px; border-radius:7px; border:1px solid var(--panel-line);
    background:rgba(14,19,48,0.85); color:var(--text); font-size:12px; cursor:pointer;
    display:flex; align-items:center; justify-content:center; flex:0 0 auto; padding:0;
    transition:all 0.15s ease;
  }
  .musicBtn.on{border-color:var(--cyan); color:#fff; background:rgba(63,240,255,0.18); box-shadow:0 0 8px rgba(63,240,255,0.25);}
  @media (max-width:520px){ #musicPlayerTrack{display:none;} }

  /* Weapon tray */
  #weaponTray{
    position:absolute; bottom:16px; left:50%; transform:translateX(-50%);
    display:flex; gap:8px;
  }
  .weaponIcon{
    width:42px; height:42px; border:1px solid var(--ds-panel-line);
    background:var(--ds-panel); display:flex; align-items:center; justify-content:center;
    font-size:20px; position:relative; box-shadow:0 0 10px var(--ds-glow);
    clip-path:polygon(9px 0, 100% 0, 100% calc(100% - 9px), calc(100% - 9px) 100%, 0 100%, 0 9px);
  }
  .weaponIcon .lvl{
    position:absolute; bottom:-4px; right:-4px; background:var(--ds-amber); color:#1a0d00;
    font-size:9px; font-weight:800; padding:1px 4px; border-radius:6px;
  }


  /* Mobile joystick */
  #joyZone{
    position:absolute; bottom:0; left:0; width:45%; height:45%;
    display:none;
  }
  #joyBase{
    position:absolute; width:100px; height:100px; border-radius:50%;
    border:2px solid rgba(63,240,255,0.35); background:rgba(63,240,255,0.05);
    display:none;
  }
  #joyStick{
    position:absolute; width:44px; height:44px; border-radius:50%;
    background:rgba(63,240,255,0.5); border:1px solid var(--cyan);
    box-shadow:0 0 14px rgba(63,240,255,0.7);
  }

  /* Overlays */
  .overlay{
    position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    background:rgba(4,6,16,0.88); z-index:20; flex-direction:column; text-align:center;
    padding:20px;
    overflow-y:auto; touch-action:pan-y; -webkit-overflow-scrolling:touch;
  }
  .hidden{display:none !important;}

  /* Uppercase, letter-spaced code entry field — used by the redeem-code input in Settings. */
  .codeInput{
    background:rgba(8,11,26,0.85); border:1px solid var(--panel-line); border-radius:8px;
    color:#fff; font-size:22px; letter-spacing:8px; text-align:center; text-transform:uppercase;
    padding:12px; width:100%; box-sizing:border-box;
  }
  .codeInput:focus{ outline:none; border-color:var(--cyan); }

  /* Comm log character portrait — shown to the right of the dialogue panel, and behind it
     (lower z-index + a slight horizontal overlap into the panel's edge), the way a lot of RPGs
     peek a character sprite out from beside/behind the text box instead of floating it separately.
     Only used for STORY_BEATS entries that carry a `portrait` path (the handful of levels where
     Vesper identifies which crew member a boss/mini-boss used to be — see showCommLog). */
  #commLogPortrait{
    position:absolute; z-index:1; bottom:8%;
    left:min(calc(50% + 190px), calc(100vw - 34vw - 16px));
    max-height:76vh; max-width:34vw; object-fit:contain; object-position:bottom;
    filter:drop-shadow(0 14px 26px rgba(0,0,0,0.65));
    pointer-events:none;
  }

  /* Vesper's dialogue-box avatar — a frame noticeably larger than the portrait it holds, so her
     face reads clearly at a glance instead of filling a tiny circle edge-to-edge. The image sits
     centered and padded inside the ring rather than being cropped/cover-fit to the frame's edge. */
  .vesperAvatarFrame{
    width:76px; height:76px; border-radius:50%; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    background:radial-gradient(circle at 35% 32%, rgba(63,240,255,0.35), rgba(10,20,40,0.9) 70%);
    border:2px solid var(--cyan); box-shadow:0 0 18px rgba(63,240,255,0.55), inset 0 0 10px rgba(63,240,255,0.25);
  }
  /* Frame enlarged (64px -> 76px) and the vertical crop window shifted down (42% -> 50%) so the
     bottom of the cover-fit image includes her chin instead of clipping it — the source image
     itself is untouched, only how much of it this circular window reveals. */
  .vesperAvatarImg{
    width:60px; height:60px; border-radius:50%; object-fit:cover; object-position:center 50%;
  }
  @media (max-width:520px){
    .vesperAvatarFrame{width:60px; height:60px;}
    .vesperAvatarImg{width:47px; height:47px;}
  }
  @media (max-width:820px){
    /* Not enough width beside the panel on smaller/narrower screens without crowding or clipping
       off-screen — the dialogue text itself is the priority, so the portrait just sits this one out. */
    #commLogPortrait{ display:none !important; }
  }

  #mainMenu{
    background: linear-gradient(180deg, rgba(4,6,16,0.05) 0%, rgba(4,6,16,0.4) 55%, rgba(4,6,16,0.8) 100%),
                url('../scene images/main_menu_bg.jpg') center/cover no-repeat;
    backdrop-filter:none;
    padding-bottom:0;
  }
  #mainMenuVideo{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
    z-index:0; pointer-events:none;
  }
  #mainMenu > *:not(#mainMenuVideo){ position:relative; z-index:1; }
  /* Centered and sized to sit in the gap between the title and the ship in the background video,
     rather than the wider left-aligned panel this used to be. */
  #mainMenu{align-items:center; justify-content:center;}
  /* A single angular "console panel" holding every menu button, instead of six separate floating
     pills — reads as one control console rather than a stack of generic web buttons. */
  #mainMenuPanel{
    width:220px; max-width:calc(100vw - 32px); box-sizing:border-box; padding:18px 16px 14px;
    background:linear-gradient(160deg, rgba(8,12,28,0.84), rgba(8,12,28,0.6));
    backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
    border:1px solid rgba(63,240,255,0.4);
    border-radius:14px;
    box-shadow:0 0 40px rgba(0,0,0,0.45);
  }
  #mainMenuPanel .btn{
    width:100%; min-width:0; box-sizing:border-box; margin:0 0 8px 0; padding:11px 16px; font-size:11.5px;
    background:linear-gradient(135deg, rgba(10,14,34,0.7), rgba(10,14,34,0.42));
    backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
    border:1px solid rgba(63,240,255,0.3);
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.07), 0 4px 18px rgba(0,0,0,0.35);
  }
  #mainMenuPanel .btn:hover{
    border-color:var(--cyan);
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.1), 0 0 22px rgba(63,240,255,0.35);
  }
  /* Launch, Terminal and Ship Systems are all equal-weight console buttons — same size, same
     footing — so the menu reads as three peer options rather than one dominant action. */
  #mainMenuPanel #btnPlay{
    font-size:12px; padding:12px 16px; margin-bottom:12px;
    border-color:var(--cyan);
    background:linear-gradient(135deg, rgba(63,240,255,0.3), rgba(10,14,34,0.6));
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.12), 0 0 26px rgba(63,240,255,0.4);
  }
  /* Only two secondary buttons now (Terminal, Ship Systems), so they read as normal console
     buttons — same footing as Launch — rather than a cramped list of small links. */
  #mainMenuSecondary{
    display:flex; flex-direction:column; gap:8px;
    padding-top:12px; border-top:1px solid rgba(63,240,255,0.2);
  }
  #mainMenuSecondary .btn, #addonBtnWrap .btn{
    width:100%; padding:12px 16px; font-size:12px; text-align:left;
    background:linear-gradient(135deg, rgba(10,14,34,0.65), rgba(10,14,34,0.4));
    backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
    border:1px solid rgba(63,240,255,0.28);
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.06);
    margin-bottom:0;
  }
  #mainMenuSecondary .btn:hover, #addonBtnWrap .btn:hover{ border-color:var(--cyan); box-shadow:0 0 16px rgba(63,240,255,0.3); }
  #mainMenuSecondary .btn small, #addonBtnWrap .btn small{ font-size:10px; margin-top:3px; }
  /* Point of Origin sits below the Terminal/Ship Systems pair as a third peer in that same list —
     matching their exact button styling above (font size, padding, left-aligned title) was missing
     before this pass (it was only picking up the more generic #mainMenuPanel .btn rule, at a smaller
     font/padding and center-aligned), which read as an inconsistent, less "finished" button next to
     its neighbors. The top border here echoes #mainMenuSecondary's own separator line so the whole
     group reads as one list rather than two different button styles stacked on top of each other. */
  #addonBtnWrap{ padding-top:8px; border-top:1px solid rgba(63,240,255,0.2); }

  /* Terminal / Ship Systems hub screens — same console-panel language as the main menu so they
     feel like sub-panels of one system rather than a different UI. */
  .hubMenuList{ display:flex; flex-direction:column; gap:10px; margin:18px 0; }
  .hubMenuList .btn{ width:100%; text-align:left; padding:13px 18px; font-size:12.5px; }
  .hubMenuList .btn small{ font-size:10px; margin-top:3px; }

  .titleLogo{
    font-size:min(11vw, 64px); font-weight:900; letter-spacing:6px;
    background:linear-gradient(90deg, var(--cyan), var(--magenta));
    -webkit-background-clip:text; background-clip:text; color:transparent;
    text-shadow:none; margin:0; line-height:1;
    filter:drop-shadow(0 0 20px rgba(63,240,255,0.35));
  }
  .subtitle{color:var(--text-dim); letter-spacing:4px; font-size:12px; margin-top:6px; margin-bottom:34px; text-transform:uppercase;}

  .btn{
    font-family:inherit; font-weight:700; letter-spacing:1px; text-transform:uppercase;
    padding:14px 34px; margin:7px; border-radius:10px; border:1px solid var(--panel-line);
    background:linear-gradient(180deg, rgba(63,240,255,0.14), rgba(14,19,48,0.6));
    color:var(--text); font-size:14px; cursor:pointer; min-width:220px;
    transition:transform 0.08s ease, box-shadow 0.15s ease, border-color 0.15s ease;
    box-shadow:0 0 0 rgba(63,240,255,0);
  }
  .btn:hover{border-color:var(--cyan); box-shadow:0 0 18px rgba(63,240,255,0.35); transform:translateY(-1px);}
  .btn:active{transform:translateY(1px) scale(0.98);}
  .btn.primary{background:linear-gradient(180deg, rgba(63,240,255,0.3), rgba(14,19,48,0.7)); border-color:var(--cyan);}
  .btn.danger{border-color:var(--red);}
  .btn.danger:hover{box-shadow:0 0 18px rgba(255,71,87,0.4);}
  .btn small{display:block; font-size:10px; font-weight:400; color:var(--text-dim); letter-spacing:0.5px; margin-top:3px; text-transform:none;}

  .panel{
    background:var(--panel); border:1px solid var(--panel-line); border-radius:16px;
    padding:28px; max-width:520px; width:92%;
    box-shadow:0 0 40px rgba(0,0,0,0.5);
    touch-action:pan-y;
  }

  .modeColumns{display:flex; gap:28px; align-items:flex-start; justify-content:center; flex-wrap:wrap; margin-top:12px;}
  .modeColumn{display:flex; flex-direction:column; align-items:center;}
  .modeColumnLabel{
    font-size:11px; letter-spacing:2px; text-transform:uppercase; color:var(--text-dim);
    margin-bottom:10px; text-align:center;
  }
  .modeGrid{display:flex; flex-direction:column; gap:7px; width:100%; max-width:400px;}
  .modeRow{display:flex; align-items:flex-start; gap:18px;}
  .modeGridMain{max-width:400px;}
  .modeGridChallenge{max-width:220px; padding-top:26px;}
  .modeSectionGap{height:14px; border-top:1px solid rgba(63,240,255,0.18); margin:2px 0 3px;}
  .modeColumnDivider{width:1px; align-self:stretch; background:linear-gradient(180deg, transparent, rgba(63,240,255,0.25), transparent); margin-top:26px;}
  .modeChallengeLabel{font-size:9.5px; margin-bottom:2px;}
  @media (max-width:760px){
    .modeRow{flex-direction:column; align-items:center;}
    .modeColumnDivider{display:none;}
    .modeGridChallenge{max-width:400px; padding-top:10px; border-top:1px solid rgba(63,240,255,0.18); margin-top:8px;}
  }
  .modeCard{
    display:flex; flex-direction:column; align-items:flex-start; text-align:left;
    padding:9px 16px; border-radius:12px; border:1px solid var(--panel-line);
    background:rgba(14,19,48,0.6); cursor:pointer; transition:border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease, padding-bottom 0.15s ease;
  }
  .modeCard:hover{border-color:var(--cyan); box-shadow:0 0 16px rgba(63,240,255,0.25); transform:translateY(-1px);}
  .modeCard h3{margin:0; font-size:14px; color:#fff; display:flex; align-items:center; gap:8px;}
  .modeCard h3 small{ font-size:10px; font-weight:600; color:var(--text-dim); letter-spacing:0.3px; }
  /* Descriptions are one click away on the mode's own launch-confirm screen already, so the grid
     itself only needs to show icon+title at a glance — full text collapses in here and only opens
     up on hover/keyboard-focus, which was the biggest single contributor to "too much to look at"
     player feedback about this screen (9 cards' worth of paragraphs all visible at once). */
  .modeCard p{
    margin:0; font-size:11px; color:var(--text-dim); line-height:1.4;
    max-height:0; opacity:0; overflow:hidden;
    transition:max-height 0.18s ease, opacity 0.12s ease, margin-top 0.18s ease;
  }
  .modeCard:hover p, .modeCard:focus-visible p, .modeCard.gp-focused p{
    max-height:52px; opacity:1; margin-top:4px;
  }

  /* Level up choices */
  #levelUpOverlay .panel{max-width:640px;}
  #upgradeChoices{display:flex; gap:14px; flex-wrap:wrap; justify-content:center; margin-top:18px;}
  .upgradeCard{
    width:170px; padding:16px 12px; border-radius:12px; border:1px solid var(--panel-line);
    background:rgba(10,14,34,0.9); cursor:pointer; transition:all 0.15s ease;
    display:flex; flex-direction:column; align-items:center; text-align:center; gap:6px;
  }
  .upgradeCard:hover{border-color:var(--gold); box-shadow:0 0 20px rgba(255,210,63,0.35); transform:translateY(-3px);}
  .upgradeCard .icon{font-size:30px;}
  .upgradeCard .name{font-weight:700; font-size:13px; color:#fff;}
  .upgradeCard .desc{font-size:11px; color:var(--text-dim); line-height:1.4;}
  .upgradeCard .tag{font-size:9px; letter-spacing:1px; color:var(--cyan); text-transform:uppercase;}
  .upgradeCard.new .tag{color:var(--magenta);}

  /* Was written as an ID selector (#statsList) but every actual usage in index.html is
     class="statsList" (three different overlays reuse it) — the ID selector never matched
     anything, so this styling silently never applied anywhere. Fixed to a class selector. */
  .statsList{width:100%; text-align:left; margin:18px 0; font-size:13px; color:var(--text-dim); display:flex; flex-direction:column; gap:6px;}
  .statsList span{color:#fff; font-weight:700;}

  /* How To Play */
  .htpScroll{width:100%; max-height:58vh; overflow-y:auto; touch-action:pan-y; padding-right:4px; margin:14px 0;}
  .htpSection{margin-bottom:16px;}
  .htpSection:last-child{margin-bottom:0;}
  .htpSectionTitle{
    font-size:10.5px; letter-spacing:1.5px; text-transform:uppercase; color:var(--cyan);
    font-weight:700; margin-bottom:8px; text-align:left;
  }
  .htpGrid{display:grid; grid-template-columns:1fr 1fr; gap:8px;}
  @media (max-width:520px){ .htpGrid{grid-template-columns:1fr;} }
  .htpRow{
    display:flex; align-items:center; gap:10px; text-align:left;
    padding:10px 12px; border-radius:10px; border:1px solid var(--panel-line); background:rgba(14,19,48,0.5);
  }
  .htpRow .htpIcon{font-size:20px; flex-shrink:0;}
  .htpRow b{display:block; font-size:12.5px; color:#fff;}
  .htpRow small{display:block; font-size:10.5px; color:var(--text-dim); line-height:1.4; margin-top:2px;}

  /* Daily/Weekly results: the regular score breakdown panel stays exactly as it is for every other
     mode, this just adds a second panel alongside it (real cross-player standings, see
     js/leaderboard.js) — #gameOverOverlay.withChallengeBoard switches the overlay's own flex
     direction from its normal centered column to a row so the two panels sit side by side, wrapping
     to stacked on narrow viewports same as everywhere else in this game handles small screens. */
  #gameOverOverlay.withChallengeBoard{ flex-direction:row; flex-wrap:wrap; align-items:flex-start; }
  .challengeLeaderboardPanel{ max-width:340px; text-align:left; }
  .challengeLeaderboardPanel h3{ font-size:15px; letter-spacing:1px; }
  .challengeLeaderboardPanel .hofRow{ margin-bottom:6px; }
  .challengeLeaderboardPanel .hofRow.lbRowMe{
    border-color:var(--cyan); box-shadow:0 0 14px rgba(63,240,255,0.35);
    /* The "climbing into the standings" effect: this row starts translated down/faded and
       transitions to its natural resting spot once renderChallengeLeaderboard removes .lbRowEnter
       a frame later (see that function) — a plain CSS transition rather than a JS animation loop,
       so it can't get out of sync with anything else on this screen. */
    transition: transform 0.6s cubic-bezier(0.16,1,0.3,1), opacity 0.5s ease;
  }
  .challengeLeaderboardPanel .hofRow.lbRowMe.lbRowEnter{ transform:translateY(40px); opacity:0; }
  .challengeLeaderboardPanel .lbRankNote{
    font-size:10.5px; color:var(--text-dim); text-align:center; margin:6px 0;
  }

  /* Level-complete score breakdown */
  .scoreBreakdownPanel{ max-width:760px; }
  .scoreBreakdownColumns{
    display:flex; gap:16px; align-items:flex-start; width:100%; margin-top:6px;
  }
  .scoreBreakdownColumn{ flex:1; min-width:0; }
  .scoreBreakdownColumnLabel{
    font-size:11px; color:var(--gold); text-transform:uppercase; letter-spacing:1px;
    text-align:left; margin:0 0 6px;
  }
  @media (max-width:720px){
    .scoreBreakdownColumns{ flex-direction:column; }
  }
  #scoreBreakdownList, #collectibleBreakdownList{
    width:100%; max-height:34vh; overflow-y:auto; touch-action:pan-y;
    display:flex; flex-direction:column; gap:6px;
  }
  .scoreRow{
    display:flex; align-items:center; gap:8px; text-align:left;
    padding:6px 8px; border-radius:10px; background:rgba(14,19,48,0.55); border:1px solid var(--panel-line);
  }
  .scoreIcon{width:24px; height:24px; flex-shrink:0; filter:drop-shadow(0 0 4px rgba(63,240,255,0.35));}
  .scoreIconEmoji{display:flex; align-items:center; justify-content:center; font-size:16px; filter:none;}
  .scoreName{flex:1; min-width:0; font-size:12px; font-weight:700; color:#fff; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .scoreKills{font-size:11px; color:var(--text-dim); min-width:28px;}
  .scoreEach{font-size:10px; color:var(--text-dim); min-width:52px; text-align:right;}
  .scoreSubtotal{font-size:12px; font-weight:800; color:var(--cyan); min-width:56px; text-align:right;}

  /* Same ID-vs-class mismatch as .statsList above — index.html's two usages (levelCompleteOverlay
     and, once split out below, gameOverOverlay) are both class="scoreBreakdownTotals" so two
     separate elements can each use it; an #id selector could only ever have matched one of them
     even if the id/class mismatch had been the other way around. */
  .scoreBreakdownTotals{
    width:100%; margin-top:14px; padding-top:12px; border-top:1px solid var(--panel-line);
    display:flex; flex-direction:column; gap:6px; font-size:13px; color:var(--text-dim);
  }
  .scoreBreakdownTotals div{display:flex; justify-content:space-between;}
  .scoreBreakdownTotals span{color:#fff; font-weight:800; font-size:15px;}
  #totalScoreDisplay, #finalScore{color:var(--gold);}
  #speedBonusDisplay{color:var(--cyan);}
  #bestLevelScoreDisplay, #bestScore{color:var(--cyan);}

  .newBestBadge{
    margin-top:10px; padding:6px 14px; border-radius:20px; display:inline-block;
    background:rgba(255,210,63,0.15); border:1px solid var(--gold); color:var(--gold);
    font-weight:800; font-size:12.5px; letter-spacing:0.5px;
    animation:newBestPulse 1.4s ease-in-out infinite;
  }
  @keyframes newBestPulse{
    0%,100%{ box-shadow:0 0 6px rgba(255,210,63,0.35); }
    50%{ box-shadow:0 0 18px rgba(255,210,63,0.75); }
  }

  #starRow{display:flex; justify-content:center; gap:14px; margin:18px 0 6px;}
  .starSlot{position:relative; font-size:42px; line-height:1; width:46px; height:46px; text-align:center;}
  .starSlot.filled{animation:starPop 0.4s ease;}
  .starOutline{position:absolute; inset:0; color:rgba(125,136,184,0.35); -webkit-text-stroke:1px rgba(125,136,184,0.5);}
  .starFillWrap{position:absolute; inset:0; width:0%; overflow:hidden; white-space:nowrap;}
  .starFill{color:var(--gold); text-shadow:0 0 16px rgba(255,210,63,0.9);}
  .sparkleLayer{position:absolute; inset:0; pointer-events:none;}
  .sparkle{
    position:absolute; top:50%; left:50%; width:4px; height:4px; margin:-2px;
    background:#ffd23f; border-radius:50%; box-shadow:0 0 6px 2px rgba(255,210,63,0.8);
    animation:sparklePop 0.65s ease-out forwards;
  }
  @keyframes sparklePop{
    0%{ transform:translate(0,0) scale(1); opacity:1; }
    100%{ transform:translate(var(--dx),var(--dy)) scale(0); opacity:0; }
  }
  @keyframes starPop{
    0%{ transform:scale(1); } 45%{ transform:scale(1.4); } 100%{ transform:scale(1); }
  }

  /* Achievement toast — slides in from off-screen right to a resting spot at mid-height, then
     slides back out the same way once it's done showing, instead of dropping from the top. */
  #achievementToast{
    position:fixed; top:50%; right:-400px; transform:translateY(-50%);
    z-index:300; display:flex; align-items:center; gap:12px;
    background:rgba(10,14,30,0.95); border:1px solid var(--panel-line); border-radius:14px;
    padding:12px 20px; box-shadow:0 8px 28px rgba(0,0,0,0.5);
    pointer-events:none; transition:right 0.45s cubic-bezier(0.2,0.9,0.3,1.3);
    max-width:min(86vw,360px);
  }
  #achievementToast.show{ right:20px; }
  #achievementToast .achToastIcon{font-size:30px; flex-shrink:0;}
  #achievementToast .achToastLabel{font-size:9.5px; letter-spacing:1.5px; color:var(--text-dim); text-transform:uppercase;}
  #achievementToast .achToastName{font-size:14px; font-weight:800; color:#fff;}
  #achievementToast .achToastDesc{font-size:11px; color:var(--text-dim);}
  #achievementToast.tier-bronze{border-color:#cd7f32; box-shadow:0 8px 28px rgba(205,127,50,0.35);}
  #achievementToast.tier-silver{border-color:#c8ced8; box-shadow:0 8px 28px rgba(200,206,216,0.35);}
  #achievementToast.tier-gold{border-color:var(--gold); box-shadow:0 8px 28px rgba(255,210,63,0.4);}
  #achievementToast.tier-platinum{border-color:#3ff0ff; box-shadow:0 8px 28px rgba(63,240,255,0.5);}

  /* First-level interactive tutorial — a short wide bar hugging the bottom edge so it reads
     without blocking the arena/background behind it. */
  #tutorialCallout{
    position:fixed; left:50%; bottom:28px; transform:translateX(-50%);
    z-index:250; display:flex; flex-direction:row; flex-wrap:wrap; align-items:center; justify-content:center;
    gap:8px 16px;
    background:rgba(10,14,30,0.95); border:1px solid var(--cyan); border-radius:12px;
    padding:10px 22px; box-shadow:0 8px 32px rgba(63,240,255,0.3);
    width:max-content; max-width:min(94vw,680px); text-align:center;
  }
  #tutorialCallout.hidden{display:none;}
  #tutorialCallout .tutorialStepDots{display:flex; gap:5px; flex:0 0 auto;}
  #tutorialCallout .tutorialStepDots span{width:6px; height:6px; border-radius:50%; background:var(--panel-line);}
  #tutorialCallout .tutorialStepDots span.on{background:var(--cyan); box-shadow:0 0 6px var(--cyan);}
  #tutorialCallout .tutorialText{font-size:13.5px; color:#fff; font-weight:600; line-height:1.35; flex:1 1 260px; text-align:left;}
  #tutorialCallout .tutorialGlyph{
    font-size:14px; font-weight:800; color:#1a1408; letter-spacing:0.3px; flex:0 0 auto;
    padding:6px 14px; border-radius:8px; background:var(--gold);
    box-shadow:0 0 0 1px rgba(255,210,63,0.5), 0 0 14px rgba(255,210,63,0.55);
    animation:tutorialGlyphPulse 1.6s ease-in-out infinite;
  }
  #tutorialCallout .tutorialGlyph::before{
    content:'Press'; font-weight:600; text-transform:uppercase; font-size:9.5px;
    letter-spacing:1px; opacity:0.65; margin-right:7px;
  }
  #tutorialCallout .tutorialGlyph:empty{display:none;}
  @keyframes tutorialGlyphPulse{
    0%,100%{ box-shadow:0 0 0 1px rgba(255,210,63,0.5), 0 0 10px rgba(255,210,63,0.45); }
    50%{ box-shadow:0 0 0 1px rgba(255,210,63,0.7), 0 0 20px rgba(255,210,63,0.85); }
  }
  #tutorialCallout .tutorialHint{flex:0 0 100%; font-size:10.5px; color:var(--text-dim); letter-spacing:0.3px;}
  #tutorialCallout .tutorialHint:empty{display:none;}

  /* Achievements screen */
  #achievementsProgress{font-size:12.5px; color:var(--gold); font-weight:700; margin-bottom:12px; text-align:center;}
  #achievementsList{
    width:100%; max-height:56vh; overflow-y:auto; touch-action:pan-y;
    display:flex; flex-direction:column; gap:8px;
  }
  .achCard{
    display:flex; align-items:center; gap:12px; text-align:left;
    padding:10px 14px; border-radius:12px; border:1px solid var(--panel-line);
    background:rgba(14,19,48,0.5); opacity:0.5; filter:grayscale(0.6);
  }
  .achCard.unlocked{opacity:1; filter:none;}
  .achCard .achIcon{font-size:24px; flex-shrink:0;}
  .achCard .achName{font-size:13px; font-weight:700; color:#fff;}
  .achCard .achDesc{font-size:11px; color:var(--text-dim); margin-top:2px;}
  .achCard .achCheck{color:var(--green); font-size:16px; margin-left:auto; flex-shrink:0;}
  .achCard.tier-bronze.unlocked{border-color:#cd7f32;}
  .achCard.tier-silver.unlocked{border-color:#c8ced8;}
  .achCard.tier-gold.unlocked{border-color:var(--gold);}
  .achCard.tier-platinum.unlocked{border-color:#3ff0ff; box-shadow:0 0 12px rgba(63,240,255,0.25);}

  .codexCard{
    display:flex; align-items:flex-start; gap:14px; text-align:left;
    padding:13px 16px; border-radius:10px; border:1px solid var(--panel-line);
    border-left:3px solid rgba(63,240,255,0.4);
    background:linear-gradient(135deg, rgba(14,19,48,0.65), rgba(14,19,48,0.4));
    box-shadow:0 2px 10px rgba(0,0,0,0.25);
    transition:border-color 0.15s ease, box-shadow 0.15s ease;
  }
  .codexCard:hover{ border-left-color:var(--cyan); box-shadow:0 2px 14px rgba(63,240,255,0.15); }
  .codexCard .codexIcon{
    width:56px; height:56px; flex-shrink:0; border-radius:8px; margin-top:1px;
    background:rgba(0,0,0,0.4); border:1px solid rgba(63,240,255,0.2);
    display:flex; align-items:center; justify-content:center; overflow:hidden;
  }
  .codexCard .codexIcon canvas, .codexCard .codexIcon img{ width:100%; height:100%; }
  /* Extraction Ship's Codex card (see renderCodex's Ships tab) — noticeably larger than the
     regular player-ship thumbnails since it's meant to read as a genuinely large capital ship. */
  .codexCard .codexIcon.codexIconLarge{ width:92px; height:92px; }
  .codexCard .codexText{ min-width:0; flex:1; }
  .codexCard .codexName{font-size:13.5px; font-weight:700; color:#fff; letter-spacing:0.3px;}
  .codexCard .codexDesc{font-size:11.5px; color:var(--text-dim); margin-top:4px; line-height:1.45;}
  .codexCard .codexAttack{
    font-size:11px; color:#dfe6ff; margin-top:8px; padding-top:8px; line-height:1.45;
    border-top:1px solid rgba(63,240,255,0.15);
  }
  .codexCard .codexAttackLabel{
    display:inline-block; font-size:9px; font-weight:800; letter-spacing:1px; text-transform:uppercase;
    color:var(--gold); background:rgba(255,210,63,0.12); border:1px solid rgba(255,210,63,0.3);
    border-radius:4px; padding:1px 6px; margin-right:7px; vertical-align:1px;
  }

  /* Hall of Fame */
  #hallOfFameList{
    width:100%; max-height:52vh; overflow-y:auto; touch-action:pan-y;
    display:flex; flex-direction:column; gap:6px;
  }
  #hallOfFameList .hofEmpty{color:var(--text-dim); font-size:12.5px; padding:20px 0; text-align:center;}
  .hofRow{
    display:flex; align-items:center; gap:14px; text-align:left;
    padding:10px 14px; border-radius:10px; border:1px solid var(--panel-line);
    background:linear-gradient(135deg, rgba(14,19,48,0.65), rgba(14,19,48,0.4));
    box-shadow:0 2px 8px rgba(0,0,0,0.2);
  }
  .hofRow.rank-1{border-color:var(--gold); box-shadow:0 0 14px rgba(255,210,63,0.3);}
  .hofRow.rank-2{border-color:#c8ced8; box-shadow:0 0 10px rgba(200,206,216,0.15);}
  .hofRow.rank-3{border-color:#cd7f32; box-shadow:0 0 10px rgba(205,127,50,0.15);}
  .hofRow .hofRankBadge{
    width:32px; height:32px; border-radius:50%; flex-shrink:0; font-size:14px;
    display:flex; align-items:center; justify-content:center;
    font-weight:800; color:var(--text-dim); background:rgba(0,0,0,0.3); border:1px solid var(--panel-line);
  }
  .hofRow.rank-1 .hofRankBadge{ background:linear-gradient(135deg,#ffe27a,#c9962b); color:#3a2a00; border-color:var(--gold); }
  .hofRow.rank-2 .hofRankBadge{ background:linear-gradient(135deg,#e8ecf2,#a7afbb); color:#1a1e26; border-color:#c8ced8; }
  .hofRow.rank-3 .hofRankBadge{ background:linear-gradient(135deg,#e0a86a,#8a5321); color:#2a1500; border-color:#cd7f32; }
  .hofRow .hofInfo{ flex:1; min-width:0; }
  .hofRow .hofScore{font-size:16px; font-weight:800; color:#fff;}
  .hofRow .hofMeta{font-size:10.5px; color:var(--text-dim); margin-top:2px;}

  .flashText{
    position:absolute; top:38%; left:50%; transform:translate(-50%,-50%);
    font-size:min(9vw,46px); font-weight:900; letter-spacing:3px; color:var(--gold);
    text-shadow:0 0 24px rgba(255,210,63,0.8); pointer-events:none; z-index:30;
    opacity:0; text-transform:uppercase;
  }

  #comboIndicator{
    position:absolute; top:70px; left:14px; font-size:12px; color:var(--ds-amber);
    opacity:0; font-weight:700; letter-spacing:1px; text-shadow:0 0 8px var(--ds-glow);
  }

  /* Low-HP warning: a soft red vignette at the screen edges (center stays clear so it never
     obscures the ship or nearby threats), pulsing gently rather than a hard strobe. */
  #lowHpVignette{
    position:absolute; inset:0; z-index:14; pointer-events:none;
    background:radial-gradient(ellipse at center, rgba(255,20,20,0) 42%, rgba(255,20,20,0.55) 100%);
    opacity:0; transition:opacity 0.5s ease;
  }
  #lowHpVignette.active{ animation:lowHpPulse 1.7s ease-in-out infinite; }
  @keyframes lowHpPulse{
    0%,100%{ opacity:0.16; }
    50%{ opacity:0.42; }
  }

  .crtVignette{
    position:absolute; inset:0; pointer-events:none; z-index:5;
    box-shadow:inset 0 0 140px rgba(0,0,0,0.75);
  }

  #modeBadge{
    position:absolute; bottom:76px; right:16px;
    font-size:10px; letter-spacing:2px; color:var(--text-dim); text-transform:uppercase;
    background:var(--ds-panel); padding:2px 12px; border:1px solid var(--ds-panel-line);
    clip-path:polygon(6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%, 0 6px);
  }

  /* Salvage Run only — shown/enabled from updateHUD once world.salvageExtractReady flips true.
     Sits just above the mode badge so it reads as belonging to the same HUD cluster. */
  #btnExtract{
    position:absolute; bottom:104px; right:16px;
    font-family:inherit; font-weight:800; letter-spacing:1.5px; text-transform:uppercase;
    font-size:11px; padding:8px 16px; border-radius:8px; cursor:pointer;
    color:#0a0f06; background:linear-gradient(180deg, var(--gold), #d9a900);
    border:1px solid rgba(255,255,255,0.4);
    box-shadow:0 0 16px rgba(255,210,63,0.55);
    animation:extractPulse 1.6s ease-in-out infinite;
  }
  #btnExtract small{ display:block; font-size:8.5px; font-weight:600; letter-spacing:0.3px; text-transform:none; color:#4a3b00; margin-top:1px; }
  @keyframes extractPulse{
    0%,100%{ box-shadow:0 0 16px rgba(255,210,63,0.55); transform:scale(1); }
    50%{ box-shadow:0 0 26px rgba(255,210,63,0.85); transform:scale(1.03); }
  }
  /* Sits just above the standard Extract button — magenta/danger accent (matches this game's own
     "riskier" color convention elsewhere, e.g. Priya's corruption color) so the two are readable at
     a glance as "safe now" vs "bigger bet". */
  #btnExtractPriority{
    position:absolute; bottom:150px; right:16px;
    font-family:inherit; font-weight:800; letter-spacing:1px; text-transform:uppercase;
    font-size:10px; padding:7px 14px; border-radius:8px; cursor:pointer;
    color:#fff; background:linear-gradient(180deg, var(--magenta,#ff3fb0), #a8206e);
    border:1px solid rgba(255,255,255,0.35);
    box-shadow:0 0 14px rgba(255,63,176,0.5);
  }
  #btnExtractPriority small{ display:block; font-size:8px; font-weight:600; letter-spacing:0.3px; text-transform:none; color:#3d0620; margin-top:1px; }

  #recordingIndicator{
    position:absolute; top:40px; left:14px;
    display:flex; align-items:center; gap:6px;
    font-size:10px; font-weight:800; letter-spacing:1.5px; color:#fff;
    background:rgba(10,14,30,0.6); padding:3px 10px 3px 8px; border-radius:20px; border:1px solid rgba(255,59,59,0.5);
  }
  #recordingIndicator .recDot{
    width:8px; height:8px; border-radius:50%; background:#ff3b3b;
    box-shadow:0 0 6px #ff3b3b; animation:recPulse 1.2s ease-in-out infinite;
  }
  @keyframes recPulse{
    0%,100%{ opacity:1; }
    50%{ opacity:0.35; }
  }

  ::-webkit-scrollbar{width:6px;}
  ::-webkit-scrollbar-thumb{background:var(--panel-line); border-radius:3px;}

  @media (max-width:720px), (max-height:520px) and (orientation:landscape){
    #joyZone{display:block;}
    /* #topBar's two #statCluster blocks have a hard min-width:150px floor (see the desktop rule
       above) that, combined with its gap, can add up to more than a narrow phone's available width
       (topBar's own right inset already reserves room for the independently-positioned #pauseBtn,
       see above) — flexbox lets the row overflow rather than shrink those below their floor.
       Shrinking the floor and gap here keeps the whole bar readable and on-screen. */
    #topBar{ gap:8px; }
    .statCluster{ min-width:78px; }
    #timerDisplay{ font-size:15px; letter-spacing:1px; }
    #killCount{ font-size:10px; }
    .titleLogo{letter-spacing:3px;}
    .upgradeCard{width:140px; padding:12px 8px;}
    .upgradeCard .icon{font-size:24px;}
    .upgradeCard .name{font-size:12px;}
    .upgradeCard .desc{font-size:10px;}
    /* Keep the touch control set simple: Dash, Shield, and Ultimate cover what mobile needs */
    #rewindIndicator{display:none !important;}

    /* Shrink every menu/overlay to fit a phone screen instead of a scaled-down desktop layout */
    /* .overlay is flex-direction:column, so it's justify-content (not align-items) that centers
       children vertically — and justify-content:center (the desktop default, set on .overlay above)
       combined with overflow-y:auto is a well-known flexbox trap: when centered content is taller
       than the container, the browser centers it by overflowing equally above AND below the visible
       area, but scrollTop can never go negative — so the portion that overflowed off the TOP (here,
       the title and whatever's first in the list, e.g. the Campaign card on Mode Select) becomes
       permanently unreachable by scrolling, while content nearer the bottom stays visible/scrollable.
       Top-aligning on small/short screens instead means the full content is always reachable by
       scrolling straight down from the start. */
    .overlay{padding:10px; justify-content:flex-start;}
    .panel{padding:16px 18px; border-radius:12px;}
    .btn{padding:10px 20px; margin:5px; font-size:12.5px; min-width:160px;}
    .subtitle{font-size:11px; margin-bottom:20px;}
    .modeCard{padding:12px 14px;}
    .modeCard h3{font-size:14px;}
    .modeCard p{font-size:11px;}
  }

  #joyHint{
    position:absolute; left:60px; bottom:60px; width:100px; height:100px;
    border-radius:50%; border:2px solid rgba(63,240,255,0.25);
    background:rgba(63,240,255,0.06); pointer-events:none; display:none;
  }
  @media (max-width:720px), (max-height:520px) and (orientation:landscape){
    #joyHint{display:block;}
  }

  /* ---- Controller / Settings ---- */
  .focusable:focus-visible, .focusable.gp-focused{
    outline:none;
    box-shadow:0 0 0 3px var(--gold), 0 0 20px rgba(255,210,63,0.5) !important;
    border-color:var(--gold) !important;
  }
  #controllerStatus{
    display:flex; align-items:center; gap:8px; justify-content:center;
    font-size:12px; color:var(--text-dim); margin-bottom:16px; padding:8px 14px;
    border:1px solid var(--panel-line); border-radius:20px; background:rgba(14,19,48,0.5);
  }
  #controllerStatus .dot{width:8px; height:8px; border-radius:50%; background:var(--red); box-shadow:0 0 8px var(--red);}
  #controllerStatus.connected .dot{background:var(--green); box-shadow:0 0 8px var(--green);}
  #controllerStatus.connected{color:var(--text);}

  #gamepadDiagramWrap{display:flex; flex-direction:column; align-items:center; gap:10px;}

  #settingsHint{font-size:11.5px; color:var(--text-dim); text-align:center; margin-top:10px; line-height:1.6;}

  /* ---- Settings: category tabs (Graphics / Audio / Controls / Gameplay) ---- */
  .settingsTabs{
    display:flex; gap:6px; justify-content:center; margin-bottom:16px; flex-wrap:wrap;
    border-bottom:1px solid rgba(42,53,112,0.4); padding-bottom:12px;
  }
  .settingsTab{
    font-family:inherit; font-weight:700; font-size:11.5px; letter-spacing:0.6px; text-transform:uppercase;
    padding:8px 16px; border-radius:20px; border:1px solid var(--panel-line);
    background:rgba(14,19,48,0.6); color:var(--text-dim); cursor:pointer; transition:all 0.15s ease;
  }
  .settingsTab:hover{ border-color:var(--cyan); color:var(--text); }
  .settingsTab.on{
    border-color:var(--cyan); color:#fff; background:rgba(63,240,255,0.18);
    box-shadow:0 0 10px rgba(63,240,255,0.25);
  }
  .settingsTabPanel.hidden{ display:none; }

  /* ---- Settings: Graphics tab hardware-acceleration callout ---- */
  .hwAccelCallout{
    border:1px solid var(--panel-line); border-radius:10px; background:rgba(63,240,255,0.06);
    padding:12px 14px; margin-bottom:14px;
  }
  .hwAccelStatus{
    font-size:12px; font-weight:700; letter-spacing:0.3px; margin-bottom:6px;
    display:flex; align-items:center; gap:6px;
  }
  .hwAccelStatus.ok{ color:var(--green); }
  .hwAccelStatus.warn{ color:var(--gold); }
  .hwAccelCallout p{ margin:0; font-size:11.5px; color:var(--text-dim); line-height:1.55; }

  /* ---- Settings: Controls tab key-binding rows ---- */
  .keyBindSectionLabel{
    font-size:11px; letter-spacing:1.5px; text-transform:uppercase; color:var(--text-dim);
    margin:18px 0 4px; padding-top:12px; border-top:1px solid rgba(42,53,112,0.4);
  }
  .keyBindSectionLabel small{
    display:block; font-size:10.5px; text-transform:none; letter-spacing:0.2px; margin-top:3px; font-weight:400;
  }
  .keyBindBtn, .gpBindBtn{
    font-family:inherit; font-weight:700; font-size:11px; letter-spacing:0.5px;
    padding:8px 16px; border-radius:8px; border:1px solid var(--panel-line);
    background:rgba(14,19,48,0.7); color:#fff; cursor:pointer; min-width:76px; text-align:center;
    transition:all 0.15s ease;
  }
  .keyBindBtn:hover, .gpBindBtn:hover{ border-color:var(--cyan); }
  .keyBindBtn.listening, .gpBindBtn.listening{
    border-color:var(--gold); color:var(--gold); background:rgba(255,210,63,0.14);
    box-shadow:0 0 10px rgba(255,210,63,0.3); animation:keyBindPulse 1s ease-in-out infinite;
  }
  @keyframes keyBindPulse{ 0%,100%{ opacity:1; } 50%{ opacity:0.55; } }
  #keyBindStatus, #gpBindStatus{
    text-align:center; font-size:11px; color:var(--text-dim); min-height:16px; margin-top:8px;
  }

  .settingRow{
    display:flex; align-items:center; justify-content:space-between; gap:14px;
    padding:12px 4px; border-bottom:1px solid rgba(42,53,112,0.4);
  }
  .settingRow:last-child{border-bottom:none;}
  .settingLabel{font-size:13px; color:var(--text); font-weight:600;}
  .settingLabel small{display:block; font-size:10.5px; color:var(--text-dim); font-weight:400; margin-top:2px;}

  /* ---- Bug Report Form ---- */
  .bugFormRow{ margin-bottom:14px; }
  .bugFormLabel{
    display:block; font-size:11.5px; font-weight:700; letter-spacing:0.3px;
    color:var(--text); margin-bottom:6px;
  }
  .bugFormSelect, .bugFormInput, .bugFormTextarea{
    width:100%; box-sizing:border-box; font-family:inherit; font-size:13px;
    background:rgba(8,11,26,0.85); border:1px solid var(--panel-line); border-radius:8px;
    color:#fff; padding:9px 10px; outline:none; transition:border-color 0.15s ease;
  }
  .bugFormSelect:focus, .bugFormInput:focus, .bugFormTextarea:focus{ border-color:var(--cyan); }
  .bugFormInput[readonly]{ color:var(--text-dim); background:rgba(8,11,26,0.55); }
  .bugFormTextarea{ resize:vertical; min-height:80px; line-height:1.5; }
  .bugFormSelect{ appearance:none; -webkit-appearance:none;
    background-image:linear-gradient(45deg, transparent 50%, var(--cyan) 50%), linear-gradient(135deg, var(--cyan) 50%, transparent 50%);
    background-position:calc(100% - 16px) center, calc(100% - 11px) center; background-size:5px 5px, 5px 5px; background-repeat:no-repeat;
    padding-right:28px;
  }

  .toggleBtn{
    font-family:inherit; font-weight:700; font-size:11px; letter-spacing:0.5px;
    padding:8px 18px; border-radius:20px; border:1px solid var(--panel-line);
    background:rgba(14,19,48,0.7); color:var(--text-dim); cursor:pointer; min-width:70px;
    transition:all 0.15s ease;
  }
  .toggleBtn.on{border-color:var(--cyan); color:#fff; background:rgba(63,240,255,0.18); box-shadow:0 0 10px rgba(63,240,255,0.25);}

  .segToggle{display:flex; flex-wrap:wrap; gap:8px;}
  .segToggle button{
    font-family:inherit; font-weight:700; font-size:11px; letter-spacing:0.5px;
    padding:8px 16px; border-radius:20px; border:1px solid var(--panel-line);
    background:rgba(14,19,48,0.7); color:var(--text-dim); cursor:pointer;
    transition:all 0.15s ease;
  }
  .segToggle button:hover{ border-color:var(--cyan); color:var(--text); }
  .segToggle button.on{border-color:var(--cyan); color:#fff; background:rgba(63,240,255,0.18); box-shadow:0 0 10px rgba(63,240,255,0.25);}
  #colorblindToggle button{padding:7px 11px; font-size:9.5px; min-width:52px;}

  #volumeSlider{
    -webkit-appearance:none; width:130px; height:6px; border-radius:3px;
    background:rgba(255,255,255,0.12); outline:none;
  }
  #volumeSlider::-webkit-slider-thumb{
    -webkit-appearance:none; width:16px; height:16px; border-radius:50%;
    background:var(--cyan); box-shadow:0 0 8px rgba(63,240,255,0.7); cursor:pointer;
  }
  #volumeSlider::-moz-range-thumb{
    width:16px; height:16px; border-radius:50%; border:none;
    background:var(--cyan); box-shadow:0 0 8px rgba(63,240,255,0.7); cursor:pointer;
  }
  #volumeValue{font-size:11px; color:var(--cyan); min-width:32px; text-align:right;}

  #abilityBar{
    position:absolute; bottom:16px; right:16px; display:none; gap:10px; z-index:11;
  }
  /* Fixed-position callout for boss/attack status text, so it can't get buried in on-screen
     chaos the way world-space floating text can. Sits centered above the ability icon row. */
  #statusBanner{
    position:absolute; left:50%; bottom:82px; z-index:15; pointer-events:none;
    transform:translate(-50%, 8px); opacity:0; transition:opacity 0.25s ease, transform 0.25s ease;
    max-width:min(92vw,560px); text-align:center; white-space:normal;
    font-weight:800; letter-spacing:0.5px; text-transform:uppercase; font-size:15px;
    padding:9px 22px; border-radius:10px; border:1px solid var(--panel-line);
    background:rgba(8,11,26,0.85); box-shadow:0 4px 20px rgba(0,0,0,0.4);
  }
  #statusBanner.show{ opacity:1; transform:translate(-50%, 0); }

  #bossWarningFlash{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
    z-index:500; pointer-events:none; opacity:0; display:none;
    transition:opacity 0.35s ease;
    background-color:#3a0000; /* fallback tint if the image itself somehow still fails to load — the flash is never fully invisible */
  }
  .abilityIcon{
    position:relative; width:46px; height:46px;
    border:2px solid var(--ds-panel-line); background:var(--ds-panel);
    display:flex; align-items:center; justify-content:center; font-size:18px;
    cursor:pointer; clip-path:polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
  }
  .abilityIcon.ready{border-color:var(--ds-amber); box-shadow:0 0 14px var(--ds-glow);}
  /* Fires exactly once, right as an ability comes off cooldown (see updateAbilityIndicator) — a
     quick bright pulse the player catches out of the corner of their eye, distinct from the
     steady .ready glow it settles into a moment later. Respects Reduce Flashing with a softer,
     slower version instead of skipping it outright, since "ability is ready" is useful gameplay
     information, not a purely decorative flourish. */
  .abilityIcon.justReady{ animation:abilityReadyFlash 0.45s ease-out; }
  .abilityIcon.justReadySoft{ animation:abilityReadyFlashSoft 0.7s ease-out; }
  @keyframes abilityReadyFlash{
    0%{ box-shadow:0 0 4px var(--ds-glow); transform:scale(1); }
    35%{ box-shadow:0 0 28px 6px rgba(255,145,66,0.9); transform:scale(1.14); border-color:#fff; }
    100%{ box-shadow:0 0 14px var(--ds-glow); transform:scale(1); }
  }
  @keyframes abilityReadyFlashSoft{
    0%{ box-shadow:0 0 4px var(--ds-glow); }
    50%{ box-shadow:0 0 18px rgba(255,145,66,0.7); }
    100%{ box-shadow:0 0 14px var(--ds-glow); }
  }
  .abilityCooldownRing{
    position:absolute; inset:0;
    background:conic-gradient(rgba(0,0,0,0.7) var(--pct,0%), transparent 0%);
    clip-path:polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
  }
  .abilityIcon .abilityGlyph{ position:relative; z-index:1; transition:opacity 0.15s ease; }
  .abilityIcon:not(.ready) .abilityGlyph{ opacity:0.3; }
  .abilityIcon .cooldownNum{
    position:absolute; inset:0; z-index:2;
    display:flex; align-items:center; justify-content:center;
    font-size:17px; font-weight:800; color:#fff; font-family:'Segoe UI', Arial, sans-serif;
    text-shadow:0 0 6px rgba(0,0,0,0.9), 0 0 10px rgba(255,145,66,0.6);
    pointer-events:none;
  }
  .abilityIcon .cooldownNum:empty{ display:none; }
  /* While a number is showing, the emoji glyph behind it fades back so the countdown reads clearly
     instead of the two overlapping. */
  .abilityIcon .cooldownNum:not(:empty) ~ .hint{ opacity:0.85; }
  .abilityIcon .hint{
    position:absolute; bottom:-16px; left:50%; transform:translateX(-50%);
    font-size:8.5px; color:var(--text-dim); white-space:nowrap;
  }

  /* ---- Controls Info Overlay (Triangle/△ toggle) ---- */
  #controlsInfoOverlay{
    position:absolute; top:70px; right:16px; width:230px; max-height:70vh; overflow-y:auto;
    background:rgba(8,11,26,0.72); border:1px solid var(--panel-line); border-radius:12px;
    padding:14px; z-index:60; display:none; backdrop-filter:blur(3px);
  }
  #controlsInfoOverlay h3{
    margin:0 0 10px 0; font-size:12px; letter-spacing:1px; color:var(--gold); text-transform:uppercase;
  }
  #controlsInfoOverlay .row{
    display:flex; justify-content:space-between; gap:8px; font-size:11.5px; padding:5px 0;
    border-bottom:1px solid rgba(42,53,112,0.35); color:var(--text);
  }
  #controlsInfoOverlay .row:last-child{border-bottom:none;}
  #controlsInfoOverlay .row .btn-tag{
    color:var(--cyan); font-weight:700; flex-shrink:0;
  }

  /* ---- Campaign Map ---- */
  .tierTab.active{border-color:var(--gold); background:rgba(255,210,63,0.14); color:#fff;}
  .hangarTab.active{border-color:var(--cyan); background:rgba(63,240,255,0.14); color:#fff;}
  .shipStyleRow{
    display:flex; align-items:center; justify-content:space-between; gap:10px;
    padding:11px 14px; border:1px solid var(--panel-line); border-radius:10px;
    background:linear-gradient(135deg, rgba(14,19,48,0.68), rgba(14,19,48,0.42));
    box-shadow:0 2px 8px rgba(0,0,0,0.2);
    transition:border-color 0.15s ease, box-shadow 0.15s ease;
  }
  .shipStyleRow:hover{ border-color:rgba(63,240,255,0.5); }
  .shipStyleRow.equipped{border-color:var(--green); box-shadow:0 0 12px rgba(63,255,158,0.25);}
  .shipStyleRow .styleInfo{font-size:12.5px; color:#fff; font-weight:600; text-align:left; flex:1;}
  .shipStyleRow .styleInfo small{display:block; font-size:10px; color:var(--text-dim); font-weight:400; margin-top:2px;}
  .shipStyleRow .styleThumbWrap{
    position:relative; width:56px; height:40px; flex-shrink:0; border-radius:8px;
    background:rgba(0,0,0,0.4); border:1px solid rgba(63,240,255,0.15);
    display:flex; align-items:center; justify-content:center; overflow:hidden;
  }
  .shipStyleRow .styleThumbWrap canvas{width:100%; height:100%;}
  .shipStyleRow.locked .styleThumbWrap canvas{opacity:0.4; filter:grayscale(0.5);}
  .shipStyleRow .styleThumbWrap .lockIcon{position:absolute; font-size:14px; text-shadow:0 1px 3px #000;}
  .hangarUnlockHint{
    font-size:11px; color:var(--text-dim); text-align:center; line-height:1.6; margin-bottom:14px;
    padding:8px 14px; border-radius:8px; background:rgba(255,210,63,0.06); border:1px solid rgba(255,210,63,0.2);
  }
  .hangarUnlockHint b{color:var(--gold);}
  .colorSwatch{
    width:44px; height:44px; border-radius:50%; border:2px solid var(--panel-line);
    cursor:pointer; position:relative; display:flex; align-items:center; justify-content:center;
    font-size:9px; color:#fff; font-weight:700; box-shadow:0 2px 6px rgba(0,0,0,0.3);
    transition:transform 0.12s ease, border-color 0.15s ease;
  }
  .colorSwatch:hover{ transform:translateY(-1px); }
  .colorSwatch.equipped{border-color:var(--green); box-shadow:0 0 12px rgba(63,255,158,0.5);}
  .colorSwatch.locked{opacity:0.35;}
  .colorSwatch .lockIcon{position:absolute; font-size:14px;}
  .campNode{
    display:flex; align-items:center; gap:12px; padding:11px 14px; border-radius:10px;
    border:1px solid var(--panel-line); background:rgba(14,19,48,0.55); cursor:pointer;
    transition:all 0.15s ease;
  }
  .campNode:hover:not(.locked){border-color:var(--cyan); box-shadow:0 0 12px rgba(63,240,255,0.25);}
  .campNode.locked{opacity:0.4; cursor:not-allowed;}
  .campNode.completed{border-color:rgba(63,255,158,0.5);}
  .campNode.current{border-color:var(--gold); box-shadow:0 0 14px rgba(255,210,63,0.3);}
  .campNode .nodeIcon{font-size:20px; width:30px; text-align:center; flex-shrink:0;}
  .campNode .nodeInfo{flex:1;}
  .campNode .nodeTitle{font-size:13px; font-weight:700; color:#fff;}
  .campNode .nodeSub{font-size:10.5px; color:var(--text-dim);}
  .campNode .nodeStars{font-size:11px; color:var(--gold); letter-spacing:2px; margin-top:2px;}
  .campNode .nodeCheck{color:var(--green); font-size:16px;}

  .perkRow{
    display:flex; align-items:center; justify-content:space-between; gap:10px;
    padding:12px 14px; border:1px solid var(--panel-line); border-radius:10px; background:rgba(14,19,48,0.5);
  }
  .perkRow .perkInfo{font-size:13px; color:#fff; font-weight:600;}
  .perkRow .perkInfo small{display:block; font-size:10.5px; color:var(--text-dim); font-weight:400; margin-top:2px;}
  .perkBtn{
    font-family:inherit; font-weight:700; font-size:11px; padding:8px 16px; border-radius:16px;
    border:1px solid var(--panel-line); background:rgba(63,240,255,0.15); color:var(--cyan); cursor:pointer; min-width:80px;
  }
  .perkBtn.owned{background:rgba(63,255,158,0.15); color:var(--green); border-color:rgba(63,255,158,0.4); cursor:default;}
  .perkBtn:disabled{opacity:0.4; cursor:not-allowed;}
  /* Salvage Run material requirement, shown under a perk's description — only ever earned in that
     one mode, so this doubles as a quiet nudge toward playing it. .short (missing the material)
     reads as a soft warning color rather than the plain dim text a satisfied requirement gets. */
  .perkRow .perkMaterialCost{font-size:10.5px; color:var(--text-dim); margin-top:3px;}
  .perkRow .perkMaterialCost.short{color:var(--gold);}
  .perkRow .ascensionTag{
    font-size:9px; font-weight:800; letter-spacing:1px; color:var(--magenta);
    border:1px solid rgba(255,63,176,0.5); border-radius:6px; padding:1px 5px; margin-left:4px;
  }

  /* ---- Splash Screen ---- */
  #splashOverlay{
    position:absolute; inset:0; z-index:100;
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    background:#000000; cursor:pointer;
  }
  #splashLogo{
    max-width:min(60vw, 320px); max-height:40vh; width:auto; height:auto;
    opacity:0; transform:scale(0.96); transition:opacity 0.8s ease, transform 0.8s ease;
  }
  #splashOverlay.show #splashLogo{ opacity:1; transform:scale(1); }
  #splashSkipHint{
    position:absolute; bottom:26px; font-size:10.5px; color:var(--text-dim);
    letter-spacing:1px; opacity:0; transition:opacity 1s ease 0.8s;
  }
  #splashOverlay.show #splashSkipHint{ opacity:0.6; }

  body.hide-cursor, body.hide-cursor canvas, body.hide-cursor #gameContainer{ cursor:none !important; }
  /* ---- Photo Mode: hide everything in #gameContainer except the canvas itself and the vignette,
     so a screenshot taken while this is active is just the game world, no HUD/menus/text. New DOM
     added to #gameContainer later automatically stays hidden too since this targets "everything
     that isn't the canvas/vignette/hint" rather than naming each HUD piece individually. ---- */
  body.photo-mode #gameContainer > *:not(#game):not(.crtVignette):not(#photoModeHint):not(#statusBanner){
    display:none !important;
  }
  #photoModeHint{
    position:absolute; bottom:22px; left:50%; transform:translateX(-50%);
    background:rgba(4,8,16,0.72); border:1px solid var(--panel-line); border-radius:10px;
    padding:8px 18px; font-size:12.5px; letter-spacing:0.5px; color:var(--text-dim);
    z-index:90; pointer-events:none;
  }

  /* ---- Addon menu entries (see refreshAddonMenuEntries in game.js) — locked ones stay visible
     rather than disappearing, styled dim/greyed like a locked DLC listing rather than a disabled
     button, since clicking one is still a valid action (jumps to Redeem Code). ---- */
  .addonLocked{
    opacity:0.6; filter:grayscale(0.4);
  }
  .addonLocked:hover{ opacity:0.8; }

  /* Point of Origin's 1-hour demo badge/countdown (see refreshAddonButtons/showDemoHud in game.js) */
  #addonBtnWrap{ position:relative; }
  #addonDemoBadge{
    position:absolute; top:-9px; right:10px; z-index:2;
    background:linear-gradient(135deg, var(--gold), #ffb238);
    color:#1a1400; font-size:9.5px; font-weight:800; letter-spacing:0.3px;
    padding:3px 8px; border-radius:20px; white-space:nowrap;
    box-shadow:0 2px 8px rgba(0,0,0,0.5);
  }
  #addonDemoBadge.demoActive{ background:linear-gradient(135deg, var(--cyan), #7de8ff); }
  #demoCountdownHud{
    position:absolute; top:10px; left:50%; transform:translateX(-50%); z-index:70;
    background:rgba(8,11,26,0.82); border:1px solid rgba(63,240,255,0.4); border-radius:20px;
    color:var(--cyan); font-size:12px; font-weight:700; letter-spacing:0.5px;
    padding:6px 16px; box-shadow:0 2px 10px rgba(0,0,0,0.4); pointer-events:none;
  }

  /* ---------- DEV NEWS PANEL (same feature as Bank or Bust's own news tab, reskinned to Void
     Wake's cyan/magenta palette) ---------- */
  #mainMenu > #newsTabBtn{
    position:absolute; top:50%; right:0; transform:translateY(-50%);
    z-index:30; cursor:pointer;
    display:flex; flex-direction:column; align-items:center;
    writing-mode:vertical-lr; text-orientation:upright;
    font-family:inherit; font-weight:700; font-size:13px; letter-spacing:4px; text-transform:uppercase;
    color:var(--bg); background:var(--cyan);
    border:none; border-radius:8px 0 0 8px;
    padding:16px 8px;
    box-shadow:-2px 0 12px rgba(0,0,0,0.4);
    transition:padding 0.15s ease, filter 0.15s ease;
  }
  #newsTabBtn:hover{ padding-right:10px; filter:brightness(1.1); }
  #newsPanelOverlay{
    position:fixed; inset:0; z-index:600; background:rgba(4,6,16,0.7);
    opacity:0; pointer-events:none; transition:opacity 0.3s ease;
  }
  #newsPanelOverlay.open{ opacity:1; pointer-events:auto; }
  #newsPanel{
    position:fixed; top:0; right:0; bottom:0; z-index:601;
    width:min(380px, 88vw);
    background:linear-gradient(180deg, rgba(10,14,34,0.98), rgba(6,9,22,0.98));
    border-left:1px solid rgba(63,240,255,0.3);
    box-shadow:-8px 0 30px rgba(0,0,0,0.5);
    padding:56px 22px 24px;
    overflow-y:auto;
    text-align:left;
    transform:translateX(100%);
    transition:transform 0.35s cubic-bezier(.34,1.1,.64,1);
  }
  #newsPanel.open{ transform:translateX(0); }
  #newsPanel h2{ color:var(--cyan); font-size:24px; margin:0 0 16px; text-align:left; }
  #newsPanel .newsHeading{
    font-size:13px; letter-spacing:1px; text-transform:uppercase; color:var(--magenta);
    margin:0 0 8px; text-align:left;
  }
  #newsPanel .newsBody{ margin:0; font-size:12.5px; line-height:1.6; color:var(--text-dim); }
  .newsSection{ margin-bottom:22px; }
  .newsSectionImg{
    width:100%; height:96px; border-radius:10px; margin-bottom:10px;
    background-size:cover; background-repeat:no-repeat; background-color:rgba(14,19,48,0.6);
    border:1px solid rgba(63,240,255,0.25);
    box-shadow:inset 0 0 0 1px rgba(255,255,255,0.04), 0 4px 14px rgba(0,0,0,0.4);
  }
  #newsImgOrigin{
    background-image:url('../addon_vw_point_of_origin/backgrounds/galaxy_map.png');
    background-position:center 40%;
  }
  #newsImgNext{
    background-image:url('../scene images/main_menu_bg.jpg');
    background-position:center 55%;
  }
  #newsImgOddbit{
    background-image:url('../logos/splash_logo.jpg');
    background-position:center center; background-size:contain;
  }
  #newsPanelCloseBtn{
    position:absolute; top:14px; left:16px; background:none; border:none; cursor:pointer;
    color:var(--text-dim); font-size:22px; line-height:1; padding:4px 8px; z-index:1;
  }
  #newsPanelCloseBtn:hover{ color:#fff; }
  .newsExternalLink{
    display:block; margin-top:6px; font-size:12px; font-weight:700;
    color:var(--cyan); text-decoration:none; border:1px solid rgba(63,240,255,0.4); border-radius:8px;
    padding:10px 12px; text-align:center; transition:background 0.15s ease;
  }
  .newsExternalLink:hover{ background:rgba(63,240,255,0.12); }
  @media (max-width:420px){
    #newsTabBtn{ font-size:11px; padding:12px 5px; }
  }
  #demoCountdownHud.hidden{ display:none; }
