/* ═══════════════════════════════════════════════════════════════
   Scapewatch — Base Styles
   Fixed 1920×1080 container, centered with letterboxing.
   ═══════════════════════════════════════════════════════════════ */

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    --game-font: 'Chakra Petch', 'Play', 'Noto Sans', 'Noto Sans Thai', 'Noto Sans SC', 'Noto Sans TC', 'Noto Sans JP', 'Noto Sans KR', sans-serif;

    /* ── Theme Colors (defaults = Oldschool) ──────────────── */
    --bg-darkest:       #1a1a1a;
    --bg-dark:          #1c1c0e;
    --bg-panel:         #2b2216;
    --bg-cell:          #3a3226;
    --bg-hover:         #4a4230;
    --border-primary:   #5c4a2a;
    --border-secondary: #7a6a3a;
    --text-bright:      #ffff00;
    --text-gold:        #FFD700;
    --text-accent:      #c8a83e;
    --text-light:       #cccccc;
    --text-muted:       #888888;
    --text-dim:         #aaaaaa;
    --text-dark:        #666666;
    --text-disabled:    #555555;
    --text-success:     #88FF88;  /* online indicators, "moving" state, friend-online dot */

    /* ── Slay Tier Colors ──────────────────────────────────── */
    --tier-feeble:  #4CAF50;  /* T1 green */
    --tier-dire:    #4FC3F7;  /* T2 light blue */
    --tier-savage:  #FF9800;  /* T3 orange */
    --tier-fell:    #F44336;  /* T4 red */
    --tier-ancient: #9C27B0;  /* T5 purple */

    /* ── Bar Fill Colors (raid contrib HUD + future bars) ──
       Per-theme overrides come from GameTheme.BAR_FILLS; these
       are the Oldschool-theme defaults so the bars still render
       cleanly if GameTheme.apply() hasn't run yet. */
    --bar-fill-damage:    #b8442d;
    --bar-fill-progress:  #5a8a3a;
}

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: #000;
    font-family: var(--game-font);
}

#game-container {
    position: absolute;
    width: 1920px;
    height: 1080px;

    /* Center in viewport */
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);

    /* Scale down to fit if viewport is smaller than 1920×1080 */
    transform-origin: center center;

    /* Game-feel: prevent text selection and image dragging */
    user-select: none;
    -webkit-user-select: none;
}

#game-container img {
    -webkit-user-drag: none;
    pointer-events: none;
}

#game-canvas {
    display: block;
    width: 100%;
    height: 100%;
    background: #1a1a2e;
    image-rendering: pixelated;
    /* Canvas owns its own touch gestures: single-finger pan, two-finger
       pinch, long-press for player context menu. touch-action: none
       stops the browser from intercepting any of these as scroll,
       zoom, or "double-tap to zoom". Active for everyone, not gated
       on body.is-touch, since the touch listeners in main.js are
       wired unconditionally and the rule is inert for mouse input. */
    touch-action: none;
}

/* Responsive scaling — fit the 1920×1080 container within the viewport.
   Disabled when body.no-scale is set (Constants.SCALED_CONTAINER = false). */
@media (max-aspect-ratio: 16/9) {
    /* Viewport is taller than 16:9 — width is the constraint */
    body:not(.no-scale) #game-container {
        width: 100vw;
        height: calc(100vw * 9 / 16);
    }
}

@media (min-aspect-ratio: 16/9) {
    /* Viewport is wider than 16:9 — height is the constraint */
    body:not(.no-scale) #game-container {
        height: 100vh;
        width: calc(100vh * 16 / 9);
    }
}


/* ═══════════════════════════════════════════════════════════════
   UI Overlay Container
   Positioned over the canvas. Scales with the game container.
   All panels are children of this container and use 1920×1080
   coordinate space (scaled via CSS transform).
   ═══════════════════════════════════════════════════════════════ */

#ui-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 1920px;
    height: 1080px;
    z-index: 10;
    pointer-events: none;
}

/* All interactive panels need pointer events */
#ui-container > * {
    pointer-events: auto;
}

/* Overlay containers must NOT capture events (overrides > * specificity) */
#ui-container > .loot-drop-zone,
#ui-container > .xp-drops-container,
#ui-container > .celebration-container,
#ui-container > .combat-encounter,
#ui-container > #screen-effects {
    pointer-events: none;
}


/* ═══════════════════════════════════════════════════════════════
   Touch-device adjustments
   `body.is-touch` is set by TouchHelpers.init (matchMedia
   (hover: none) and (pointer: coarse), upgraded by the first
   touchstart if the matchMedia missed). Rules below apply only
   when the user is on a touch device, leaving desktop untouched.
   ═══════════════════════════════════════════════════════════════ */

/* Horizontal scrolling containers (slay master tier rows, mob card
   strips) need explicit touch-action so the browser doesn't fight
   the swipe with a vertical-scroll guess. */
body.is-touch .mob-cards-scroll,
body.is-touch .tier-row-scroll,
body.is-touch .horizontal-scroll {
    touch-action: pan-x;
    -webkit-overflow-scrolling: touch;
}

/* Slot filter / list scrolling on touch: momentum scrolling */
body.is-touch .gom-tab-content,
body.is-touch .bank-grid,
body.is-touch .quest-list,
body.is-touch .hiscores-table-wrap,
body.is-touch .browse-clans-list,
body.is-touch .chat-messages {
    -webkit-overflow-scrolling: touch;
}

/* Bigger native form controls on touch. Range sliders default to a
   ~12px thumb on most browsers; bump to 24px so the thumb is
   tappable. Also widens checkbox/select hit areas slightly. */
body.is-touch input[type="range"]::-webkit-slider-thumb {
    width: 24px;
    height: 24px;
}
body.is-touch input[type="range"]::-moz-range-thumb {
    width: 24px;
    height: 24px;
}
body.is-touch input[type="range"] {
    height: 28px;
}

/* Suppress the synthesized 300ms click delay on tappable surfaces
   the game wires up. touch-action: manipulation eats the
   double-tap-to-zoom gesture too, which is correct because the
   game has its own pinch-zoom plumbing on the canvas. */
body.is-touch button,
body.is-touch .icon-option,
body.is-touch .reroll-option,
body.is-touch .master-tile,
body.is-touch .skill-cell,
body.is-touch .quest-row,
body.is-touch .clan-browse-row,
body.is-touch .mob-row,
body.is-touch .proc-recipe-card,
body.is-touch .settings-toggle-switch,
body.is-touch .ctrl-btn,
body.is-touch .loadout-btn,
body.is-touch .xp-toggle-btn,
body.is-touch .panel-tab-btn,
body.is-touch .floating-tab-btn,
body.is-touch .window-control-btn {
    touch-action: manipulation;
}

/* Per-modal touch tweaks (batched at the end of Phase 5, surfaced
   by individual implementation agents as "CSS NEEDED"). */

/* Bank slots: pointer-drag reorder needs the browser to not steal
   the swipe as a vertical scroll the moment the user starts moving. */
body.is-touch .bank-slot { touch-action: none; }

/* Chat resize handles are 6px thick which is unreachable on touch.
   Widen the hit area with a transparent expansion via padding +
   negative margin (keeps the visible 6px line, hit area 18px). */
body.is-touch .chat-resize-handle {
    height: 18px;
    margin-top: -6px;
    background-clip: content-box;
    padding: 6px 0;
    touch-action: none;
}
body.is-touch .chat-resize-handle-right {
    width: 18px;
    margin-right: -6px;
    background-clip: content-box;
    padding: 0 6px;
    touch-action: none;
}

/* Chat-header chrome buttons land below the 32px floor on desktop;
   touch needs them bumped to at least ~40px to be reliable. */
body.is-touch .chat-font-btn,
body.is-touch .chat-toggle-btn {
    min-width: 40px;
    min-height: 40px;
}

/* Active Potions collapsed pill chevron icon. */
body.is-touch .active-potions-pill-icon {
    min-width: 32px;
    min-height: 32px;
}

/* Panel tabs (bottom-right tab bar). Currently 42px tall, bump to
   44px touch-target floor without changing the desktop layout. */
body.is-touch .panel-tab-btn {
    min-width: 44px;
    min-height: 44px;
}

/* Window controls (top-right strip). Currently 36x36, bump for touch. */
body.is-touch .window-control-btn {
    min-width: 44px;
    min-height: 44px;
}

/* Skill Customization +/- lever buttons. Currently 28x28; under
   the 32px floor, hard to tap on touch. */
body.is-touch .ctrl-btn,
body.is-touch .lever-btn {
    min-width: 36px;
    min-height: 36px;
}

/* Bank's touch-only "Compare equipped" toggle (mirrors the bank
   potion-stats / spirit-stats toggles, since touch can't do
   Shift+hover). Only rendered when body.is-touch by BankModal. */
.equip-compare-toggle-wrap {
    position: absolute;
    top: 6px;
    right: 82px;
    width: 32px;
    height: 32px;
    z-index: 10;
}
.equip-compare-toggle {
    width: 32px;
    height: 32px;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.15s ease, filter 0.15s ease;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.equip-compare-toggle.active {
    opacity: 1;
    filter: drop-shadow(1px 1px 0 #000) drop-shadow(0 0 4px var(--text-bright));
}
.equip-compare-toggle:hover {
    opacity: 0.85;
}


/* ═══════════════════════════════════════════════════════════════
   Skills Panel — Bottom Right (320×440)
   4×8 grid: 7 rows of skills + 1 row of totals.
   Matches mocks/skills_panel.html exactly.
   ═══════════════════════════════════════════════════════════════ */

.skills-panel {
    position: absolute;
    right: 0px;
    bottom: 66px;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
    padding: 6px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 320px;
    height: 440px;
}

/* ── Individual skill cell ── */
.skill-cell {
    position: relative;
    display: flex;
    align-items: center;
    gap: 4px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 3px 5px;
    cursor: pointer;
    /* 50px: 8 rows (7 skill rows + the Delve/Fortify/luck/alms row, with
       Total Level filling that row's trailing 2 cells) fit the fixed 440px
       panel exactly (8 x 50 + 7 gaps x 4 + 12 padding = 440). */
    height: 50px;
    width: 73px;
}

.skill-cell:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
}

.skill-cell img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.skill-level {
    margin-left: auto;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
}

/* ── Progress bar under each cell ── */
.skill-progress {
    position: absolute;
    bottom: 1px;
    left: 3px;
    right: 3px;
    height: 3px;
    background: var(--bg-darkest);
    border-radius: 1px;
    overflow: hidden;
}

.skill-progress-fill {
    height: 100%;
    background: #4caf50;
    transition: width .3s;
}

/* Past the level cap the bar tracks the Trimmed Cape instead, so it gets
   the gold treatment to read as a different goal. 'done' (Trimmed Cape
   earned) stays full and gold — there is nothing left to fill. */
.skill-progress-fill.trimmed-phase,
.skill-progress-fill.done-phase {
    background: var(--text-gold, #e8c15a);
}

/* ── Total level row (two cells) ── */
.total-cell {
    grid-column: span 2;
    display: flex;
    align-items: center;
    gap: 4px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 3px 5px;
    height: 50px;
    width: 150px;
    position: relative;
    cursor: pointer;
}

.total-cell:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
}

.total-cell img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.total-cell .skill-level {
    margin-left: auto;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
}


/* ═══════════════════════════════════════════════════════════════
   Inventory (Bag) Panel — Bottom Right (shares slot with Skills)
   4×7 grid with 28 item slots.
   ═══════════════════════════════════════════════════════════════ */

.inventory-panel {
    position: absolute;
    right: 0px;
    bottom: 66px;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: repeat(7, 1fr);
    gap: 4px;
    padding: 6px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 320px;
    height: 440px;
    justify-items: center;
    /* Satchel overlay slots are offset out past the right/bottom edge,
       so let them spill beyond the panel bounds rather than clip. */
    overflow: visible;
}

/* Satchel-expanded inventory slots are positioned as overlays via inline
   styles set by BagPanel (rightward translate + grid placement). They
   carry no fill/border/shadow of their own, so they read like the base
   grid whether empty or filled. */

/* ═══════════════════════════════════════════════════════════
   Diary Achievements Panel — Bottom Right (shares panel slot)
   Per-location progress: header total + one row per bank with a
   5-notch progress bar (20/40/60/80/100%) granting free node-lever
   floors (tier 1-5). Rows expand to list steps.
   ═══════════════════════════════════════════════════════════ */

.diary-panel {
    position: absolute;
    right: 0px;
    bottom: 66px;
    display: flex;
    flex-direction: column;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 320px;
    height: 440px;
    overflow: hidden;
    box-sizing: border-box;
}

.diary-header {
    padding: 8px 10px;
    border-bottom: 1px solid var(--border-primary);
    flex: 0 0 auto;
}

.diary-title {
    color: var(--text-gold);
    font-weight: bold;
    font-size: 20px;
}

.diary-sub {
    color: var(--text-dim);
    font-size: 16px;
    margin-top: 2px;
}

.diary-all-bar { margin-top: 6px; }

.diary-scroll {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 6px;
}

.diary-row {
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 6px 8px;
    margin-bottom: 6px;
    cursor: pointer;
}

.diary-row:hover { border-color: var(--text-accent); }
.diary-row.complete { border-color: var(--text-success); }

.diary-row-top {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 4px;
}

.diary-bank-name { color: var(--text-light); font-size: 18px; font-weight: bold; }
.diary-bank-count { color: var(--text-muted); font-size: 18px; }

.diary-bar {
    position: relative;
    width: 100%;
    height: 12px;
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    overflow: hidden;
}

.diary-bar-fill {
    height: 100%;
    background: linear-gradient(180deg, #4caf50 0%, #2e7d32 100%);
    transition: width .3s;
}

.diary-notch {
    position: absolute;
    top: 0;
    width: 1px;
    height: 100%;
    background: rgba(0, 0, 0, 0.6);
    pointer-events: none;
}

.diary-row-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
}

.diary-tier-badge {
    font-size: 14px;
    padding: 1px 5px;
    border-radius: 3px;
    background: var(--border-primary);
    color: var(--text-light);
}
.diary-tier-badge.tier-0 { opacity: 0.5; }
.diary-tier-badge.tier-5 { background: var(--text-gold); color: #000; }

.diary-tier-reward { color: var(--text-accent); font-size: 16px; }

.diary-steps {
    margin-top: 6px;
    border-top: 1px solid var(--border-primary);
    padding-top: 4px;
}

.diary-step {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 16px;
    color: var(--text-muted);
    padding: 1px 0;
}
.diary-step.done { color: var(--text-success); }
.diary-step-mark { width: 12px; text-align: center; flex: 0 0 auto; }
.diary-step-icon {
    width: 16px;
    height: 16px;
    object-fit: contain;
    image-rendering: pixelated;
    flex: 0 0 auto;
}
.diary-step-tier { color: var(--text-accent); font-weight: bold; }
.diary-step-name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Header carries the explainer tooltip (TooltipManager trigger). */
.diary-header { cursor: help; position: relative; }
.diary-sort-toggles {
    position: absolute;
    top: 8px;
    right: 10px;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    z-index: 1;
}
.diary-sort-toggle,
.diary-bank-sort-toggle {
    font-size: 14px;
    color: var(--text-light);
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 0px 6px;
    cursor: pointer;
    user-select: none;
}
.diary-sort-toggle:hover,
.diary-bank-sort-toggle:hover { border-color: var(--text-accent); color: var(--text-accent); }
.diary-info-title { color: var(--text-gold); font-weight: bold; margin-bottom: 4px; white-space: normal; }
.diary-info-body { color: var(--text-light); white-space: normal; width: 240px; }

/* Task tooltip diary hint line. */
.tt-diary-line { color: var(--text-accent); }

/* Panel title doubles as a button to open the full-size modal view. */
.diary-title { cursor: pointer; }
.diary-title:hover { color: var(--text-accent); }

/* ═══════════════════════════════════════════════════════════
   Diary Achievements — full-size view inside the Unlocks modal.
   Reuses the .diary-row / .diary-bar / .diary-step visuals from the
   panel, laid out as a multi-column card grid with a bulk free-floor
   stepper per location.
   ═══════════════════════════════════════════════════════════ */

.diary-modal-summary {
    margin-bottom: 24px;
}
.diary-modal-title {
    color: var(--text-gold);
    font-weight: bold;
    font-size: 48px;
    display: block;
}
.diary-modal-sub {
    color: var(--text-dim);
    font-size: 32px;
    display: block;
    margin-top: 4px;
}
.diary-modal-summary .diary-all-bar {
    margin-top: 12px;
    height: 24px;
    max-width: 960px;
}
.diary-modal-help {
    color: var(--text-muted);
    font-size: 28px;
    margin-top: 16px;
    max-width: 1520px;
    line-height: 1.4;
}
.diary-modal-search {
    display: block;
    width: 100%;
    max-width: 960px;
    box-sizing: border-box;
    margin-top: 16px;
    padding: 10px 16px;
    font-size: 28px;
    color: var(--text-light);
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 5px;
    outline: none;
}
.diary-modal-search::placeholder { color: var(--text-muted); }
.diary-modal-search:focus { border-color: var(--text-accent); }

.diary-modal-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px;
    align-items: start;
}

/* Card = a .diary-row scaled up roughly 2x for legibility. The reused
   panel classes (name/bar/badge/steps) are overridden below, scoped to
   the modal so the small panel keeps its compact sizing. */
.diary-modal-card {
    margin-bottom: 0;
    padding: 20px 24px;
    border-radius: 8px;
}
.diary-modal-card .diary-row-top { margin-bottom: 8px; }
.diary-modal-card .diary-bank-name { font-size: 36px; }
.diary-modal-card .diary-bank-count { font-size: 36px; }
.diary-modal-card .diary-bar {
    height: 24px;
    border-radius: 5px;
}
.diary-modal-card .diary-notch { width: 2px; }
.diary-modal-card .diary-row-meta {
    gap: 12px;
    margin-top: 8px;
}
.diary-modal-card .diary-tier-badge {
    font-size: 28px;
    padding: 2px 10px;
    border-radius: 5px;
}
.diary-modal-card .diary-tier-reward { font-size: 32px; }
.diary-modal-card .diary-steps {
    margin-top: 12px;
    padding-top: 8px;
}
.diary-modal-card .diary-step {
    /* Was 32px. The row sits under a node header that carries the lever,
       and at 32px in a three-across card that left about six characters
       for the name. */
    font-size: 25px;
    gap: 10px;
    padding: 2px 0;
}
/* Indented under the group header so the header reads as the thing that
   owns them, not as another row in the same flat list. */
.diary-modal-card .diary-node-group .diary-step { padding-left: 24px; }
.diary-modal-card .diary-step-mark { width: 20px; }
.diary-modal-card .diary-step-icon { width: 26px; height: 26px; }
.diary-modal-card .diary-step-mark { width: 24px; }
.diary-modal-card .diary-step-icon { width: 32px; height: 32px; }

/* Bulk free-floor stepper. */
.diary-modal-bulk {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px dashed var(--border-primary);
}
.diary-bulk-label { color: var(--text-muted); font-size: 28px; }
.diary-bulk-stepper {
    display: flex;
    align-items: center;
    gap: 12px;
}
/* The stepper sits on its own row under the labels: at the modal's
   3-column width there isn't room for both beside each other. */
.diary-bulk-stepper .diary-bulk-reset { margin-left: auto; }
.diary-bulk-btn {
    width: 48px;
    height: 48px;
    line-height: 44px;
    text-align: center;
    font-size: 36px;
    font-weight: bold;
    color: var(--text-light);
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 5px;
    cursor: pointer;
    user-select: none;
}
.diary-bulk-btn:hover { border-color: var(--text-accent); color: var(--text-accent); }
.diary-bulk-btn.disabled {
    opacity: 0.35;
    cursor: default;
    pointer-events: none;
}
.diary-bulk-val {
    min-width: 56px;
    text-align: center;
    font-size: 36px;
    font-weight: bold;
    color: var(--text-light);
}
.diary-bulk-val.pos { color: var(--text-success); }
.diary-bulk-val.neg { color: var(--tier-fell); }

/* Reset: puts every free-range lever at the location back to neutral.
   Paid levers are never touched, so this can't destroy skill credits. */
.diary-bulk-reset {
    padding: 0 18px;
    height: 48px;
    line-height: 46px;
    font-size: 24px;
    color: var(--text-muted);
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 5px;
    cursor: pointer;
    user-select: none;
}
.diary-bulk-reset:hover { border-color: var(--tier-fell); color: var(--tier-fell); }
.diary-bulk-reset.disabled { opacity: 0.35; cursor: default; pointer-events: none; }

/* Label stack: what the stepper acts on, and how far those nodes are. */
.diary-bulk-labels { display: flex; flex-direction: column; gap: 2px; }
.diary-bulk-avgdist { color: var(--text-muted); font-size: 20px; opacity: 0.8; }

/* Distribution line. Shown only when the levers disagree or some are
   paid, so an even location stays quiet. */
.diary-bulk-breakdown {
    margin-top: 8px;
    font-size: 20px;
    color: var(--text-muted);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.diary-bd-top { color: var(--text-light); font-weight: bold; }
.diary-bd-other { color: var(--text-muted); }
.diary-bd-paid { color: var(--text-accent); }
.diary-bd-sep { opacity: 0.5; }

/* Bank distance on a step row, right-aligned like the node rows in
   Skill Customization. */
.diary-step-dist {
    margin-left: auto;
    padding-left: 12px;
    color: var(--text-muted);
    font-size: 18px;
    opacity: 0.75;
    flex: 0 0 auto;
}

/* Node groups inside the step list. A lever is per SKILL and per NODE,
   never per activity -- every Plunder node offers the whole Plunder
   ladder, so a lever hung off an activity row would be shared by a dozen
   of them and every copy would move at once. The lever lives on the group
   header instead, with the steps it moves indented underneath. */
.diary-node-group + .diary-node-group {
    margin-top: 10px;
    border-top: 1px dashed var(--border-primary);
}
/* Combat encounters own no node weight, so their group is inert: the
   stepper is still drawn (in its usual place) but greyed and dead. */
.diary-node-group.inert .diary-node-name,
.diary-node-group.inert .diary-step-lv-val { opacity: 0.55; }
.diary-group-empty {
    font-size: 20px;
    color: var(--text-dark);
    font-style: italic;
    padding: 2px 0 2px 34px;
}
.diary-node-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 0 2px;
    font-size: 25px;
    color: var(--text-light);
}
.diary-node-icon { width: 26px; height: 26px; flex: 0 0 auto; image-rendering: pixelated; }
.diary-node-name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.diary-node-dist { color: var(--text-muted); font-size: 18px; opacity: 0.75; flex: 0 0 auto; }

.diary-step-lever {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-left: 10px;
    flex: 0 0 auto;
}
.diary-step-lv-btn {
    width: 26px;
    height: 26px;
    line-height: 23px;
    text-align: center;
    font-size: 20px;
    font-weight: bold;
    color: var(--text-light);
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
    user-select: none;
}
.diary-step-lv-btn:hover { border-color: var(--text-accent); color: var(--text-accent); }
.diary-step-lv-btn.disabled { opacity: 0.3; cursor: default; pointer-events: none; }
.diary-step-lv-val {
    min-width: 30px;
    text-align: center;
    font-size: 20px;
    font-weight: bold;
    color: var(--text-muted);
}
.diary-step-lv-val.pos { color: var(--text-success); }
.diary-step-lv-val.neg { color: var(--tier-fell); }

/* ═══════════════════════════════════════════════════════════
   Barter Panel — Bottom Right (shares slot with other panels)
   6 item slots: 3 resource, 3 equipment with buy/sell controls.
   ═══════════════════════════════════════════════════════════ */

.barter-panel {
    position: absolute;
    right: 0px;
    bottom: 66px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 2px 6px 0 6px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 320px;
    height: 440px;
    overflow: hidden;
    font-family: var(--game-font);
    box-sizing: border-box;
}

.barter-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 2px;
    flex-shrink: 0;
}

.barter-title-wrap {
    display: flex;
    align-items: center;
    gap: 6px;
}

.barter-title-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(0 0 4px rgba(255, 215, 0, 0.5));
}

.barter-title {
    color: var(--text-bright);
    font-size: 20px;
    font-weight: bold;
    letter-spacing: 1px;
}

.barter-gold-wrap {
    display: flex;
    align-items: center;
    gap: 3px;
    margin-left: 8px;
}

.barter-header-gold-icon {
    width: 16px;
    height: 16px;
    image-rendering: pixelated;
}

.barter-header-gold {
    color: var(--text-gold);
    font-size: 20px;
    font-weight: bold;
}

.barter-budget-wrap {
    display: flex;
    align-items: center;
    gap: 3px;
    margin-left: 8px;
}

.barter-header-budget {
    color: var(--text-light);
    font-size: 16px;
    font-weight: bold;
    opacity: 0.85;
}
.barter-header-budget::before {
    content: 'x';
    color: var(--text-dim);
    font-weight: normal;
    margin-right: 2px;
    font-size: 14px;
}

.barter-reroll-btn {
    position: relative;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    color: var(--text-accent);
    font-family: var(--game-font);
    font-size: 20px;
    padding: 2px 8px;
    border-radius: 3px;
    cursor: pointer;
    transition: background 0.15s;
}

.barter-reroll-btn:hover:not(.disabled) {
    background: var(--bg-hover);
}

.barter-reroll-btn.disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* ── Slot rows ── */

.barter-slot-row {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 3px 6px;
    border-radius: 4px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    min-height: 54px;
    flex-shrink: 0;
}

.barter-slot-row.barter-slot-locked {
    opacity: 0.45;
}

.barter-slot-locked .barter-slot-icon,
.barter-slot-locked .barter-slot-info,
.barter-slot-locked .barter-slot-controls {
    pointer-events: none;
}

.barter-slot-type {
    position: relative;
    writing-mode: vertical-lr;
    text-orientation: mixed;
    font-size: 10px;
    color: var(--text-dim);
    letter-spacing: 1px;
    width: 14px;
    text-align: center;
    flex-shrink: 0;
    cursor: default;
}

.barter-slot-icon {
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.barter-slot-icon .inv-slot {
    margin: 0;
}

/* ── Info column (price + bank qty) ── */

.barter-slot-info {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 80px;
    flex: 1;
}

.barter-price {
    display: flex;
    align-items: center;
    gap: 3px;
}

.barter-gold-icon {
    width: 24px;
    height: 24px;
    image-rendering: pixelated;
}

.barter-price-value {
    color: var(--text-gold);
    font-size: 20px;
    font-weight: bold;
}

.barter-mod-label {
    font-size: 20px;
    color: var(--text-muted);
}

.barter-mod-good {
    color: #4CAF50;
}

.barter-mod-bad {
    color: #F44336;
}

/* Consumed overlay — covers the slot rows after a buy/sell, leaving
   the header (gold, BARTER tooltip, reroll button) interactive. The
   `top` value is set at runtime from the live header height in
   BarterPanel.update(). Blocks pointer events so the slot triggers
   below don't fire tooltips or clicks. */
.barter-consumed-overlay {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.8);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px 18px;
    text-align: center;
    pointer-events: auto;
    z-index: 2;
}

.barter-consumed-text {
    font-family: var(--game-font);
    color: var(--text-bright);
}

.barter-consumed-title {
    font-size: 22px;
    font-weight: bold;
    letter-spacing: 1px;
    margin-bottom: 6px;
}

.barter-consumed-sub {
    font-size: 16px;
    color: var(--text-light);
    line-height: 1.35;
}

/* ── Controls column (qty + buy/sell) ── */

.barter-slot-controls {
    display: flex;
    flex-direction: row;
    gap: 3px;
    align-items: center;
    flex-shrink: 0;
}

.barter-btn-col {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.barter-qty-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
}

.barter-qty-label {
    color: var(--text-bright);
    font-family: var(--game-font);
    font-size: 16px;
    margin-bottom: 6px;
}

.barter-qty-input {
    -webkit-appearance: none;
    appearance: none;
    width: 80px;
    height: 12px;
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    outline: none;
    cursor: pointer;
}

.barter-qty-input::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 10px;
    height: 16px;
    background: var(--text-accent);
    border-radius: 2px;
    cursor: pointer;
}

.barter-qty-input::-moz-range-thumb {
    width: 10px;
    height: 16px;
    background: var(--text-accent);
    border: none;
    border-radius: 2px;
    cursor: pointer;
}

.barter-btn {
    font-family: var(--game-font);
    font-size: 16px;
    padding: 1px 6px;
    border-radius: 2px;
    border: 1px solid var(--border-secondary);
    cursor: pointer;
    transition: background 0.15s;
}

.barter-buy-btn {
    background: #2a4a2a;
    color: #88cc88;
}

.barter-buy-btn:hover:not(:disabled) {
    background: #3a5a3a;
}

.barter-sell-btn {
    background: #4a2a2a;
    color: #cc8888;
}

.barter-sell-btn:hover:not(:disabled) {
    background: #5a3a3a;
}

.barter-btn:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

/* ── Equipment Panel (bottom-right, same position as other panels) ── */
.equipment-panel {
    position: absolute;
    right: 0px;
    bottom: 66px;
    display: flex;
    flex-direction: column;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 320px;
    height: 440px;
    overflow: hidden;
}

.equip-panel-tabs {
    display: flex;
    flex-shrink: 0;
    border-bottom: 2px solid var(--border-primary);
}

.equip-panel-tab {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 6px 2px;
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    border-right: 1px solid var(--bg-cell);
    font-family: var(--game-font);
    font-size: 16px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    cursor: pointer;
    transition: all 0.15s;
}
.equip-panel-tab:last-child { border-right: none; }
.equip-panel-tab:hover { background: var(--bg-panel); color: var(--text-light); }
.equip-panel-tab.active {
    color: var(--text-bright);
    border-bottom: 2px solid var(--text-accent);
    background: var(--bg-panel);
}
.equip-panel-tab img {
    width: 22px;
    height: 22px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.equip-panel-paperdoll {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(3, 90px);
    grid-template-rows: repeat(5, 68px);
    gap: 0px;
    justify-content: center;
    align-content: center;
    padding: 0px 6px;
}

.equip-panel-paperdoll .inv-slot {
    width: 72px;
    height: 60px;
    cursor: default;
    border-color: var(--bg-hover);
    background: var(--bg-cell);
    border-radius: 4px;
    justify-self: center;
    align-self: center;
}
.equip-panel-paperdoll .inv-slot.empty {
    background: var(--bg-darkest);
    border-color: var(--bg-cell);
}

.equip-panel-paperdoll .inv-slot .equip-panel-item-img {
    transform: scale(1.75);
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.equip-panel-paperdoll .inv-slot .equip-panel-sil {
    transform: scale(1.75);
    image-rendering: pixelated;
    opacity: 0.4;
    filter: drop-shadow(1px 1px 0 #000);
}

.equip-panel-view-toggle {
    border-left: 2px solid var(--border-primary);
    border-right: none !important;
    flex: 0 0 36px;
}

.equip-panel-stats {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 12px 16px;
    overflow-y: auto;
}
.equip-panel-stats .stats-weapon-line {
    text-align: center;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}
.equip-panel-stats .stats-info-grid {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 2px 10px;
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
}
.equip-panel-stats .stats-info-label {
    color: var(--text-muted);
    text-align: right;
}
.equip-panel-stats .stats-info-grid .style-val { color: var(--text-accent); }
.equip-panel-stats .stats-info-grid .speed-val { color: #88cc88; }
.equip-panel-stats .stats-info-grid .maxhit-val { color: #ff6644; }
.equip-panel-stats .stats-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
}
.equip-panel-stats .stats-table th {
    color: var(--text-accent);
    font-weight: normal;
    padding: 2px 6px;
    text-align: center;
    border-bottom: 1px solid var(--bg-cell);
}
.equip-panel-stats .stats-table th:first-child {
    text-align: left;
    width: 30px;
}
.equip-panel-stats .stats-table td {
    padding: 3px 6px;
    text-align: center;
    color: var(--text-light);
}
.equip-panel-stats .stats-table td:first-child {
    text-align: center;
    width: 30px;
}
.equip-panel-stats .stats-table .stat-pos { color: #4caf50; }
.equip-panel-stats .stats-table .stat-zero { color: var(--border-primary); }
.equip-panel-stats .stats-table .stat-neg { color: #ff4444; }
.equip-panel-stats .stats-table .str-cell { text-align: center; }
.equip-panel-stats .stats-table .stats-icon-wrap {
    display: inline-block;
    vertical-align: middle;
    width: 20px;
    height: 20px;
}
.equip-panel-stats .stats-table .stats-icon-wrap img {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.equip-panel-stats .potion-stats-toggle-wrap {
    top: 124px;
}
.equip-panel-stats .spirit-stats-toggle-wrap {
    top: 124px;
}

.inv-slot {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid transparent;
    border-radius: 4px;
    cursor: default;
    height: 56px;
    width: 56px;
}

.inv-slot img {
    transform: scale(1.5);
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* ── Scale variants (32×32 base sprite) ── */
.inv-slot.inv-s05 { width: 24px; height: 24px; }
.inv-slot.inv-s05 img { transform: scale(0.5); }

.inv-slot.inv-s10 { width: 40px; height: 40px; }
.inv-slot.inv-s10 img { transform: scale(1.0); }

.inv-slot.inv-s15 { width: 56px; height: 56px; }
.inv-slot.inv-s15 img { transform: scale(1.5); }

.inv-slot.inv-s20 { width: 72px; height: 72px; }
.inv-slot.inv-s20 img { transform: scale(2.0); }

.inv-qty {
    position: absolute;
    top: -2px;
    left: 2px;
    font-size: 18px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
    pointer-events: none;
}
/* OSRS-style tier colors. Hard black drop-shadow on the base class
   keeps these readable on both dark and light theme backgrounds. */
.inv-qty.inv-qty-k { color: #FFD24A; }
.inv-qty.inv-qty-m { color: #88FF88; }
.inv-qty.inv-qty-b { color: #44CCFF; }
.inv-label {
    position: absolute;
    bottom: 0px;
    left: 2px;
    font-size: 16px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
    pointer-events: none;
}
.hide-potion-labels .inv-label { display: none; }

.inv-tier-label {
    position: absolute;
    bottom: 0px;
    left: 2px;
    font-size: 16px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
    pointer-events: none;
    white-space: nowrap;
}
.hide-bank-tier-labels .bank-tier-label { display: none; }
.hide-task-tier-labels .task-tier-label { display: none; }
/* Task-tier badge lives in the same bottom-left corner as the indicator
   cascade (luck/quest/scroll). _renderIndicatorRow reserves slot 0 for
   this badge by starting icons at slot 1, but bump z above the icons'
   max z so any residual edge overlap still reads as text-on-icon. */
.task-tier-label { z-index: 25; }


/* ═══════════════════════════════════════════════════════════════
   Floating Current Task HUD — Top Center (340px)
   Shows active task, progress, and level bar.
   Matches mocks/floating_task.html exactly.
   ═══════════════════════════════════════════════════════════════ */

.floating-current-task {
    position: absolute;
    top: 0;
    left: var(--playable-center-x, 50%);
    transform: translateX(-50%);
    width: 340px;
    z-index: 500;
    transition: left 0.3s ease;
}

/* ═══════════════════════════════════════════════════════════════
   Raid Contribution HUD - top-center bar graph during raid combat.
   Sits below the floating task widget, above the rest of the HUD.
   ═══════════════════════════════════════════════════════════════ */
/* WoW-style damage meter. Top-center, sits over where the floating
   task widget normally lives (TaskDisplay is hidden while this is
   visible). z-index 505 keeps it above the task widget's 500. */
.raid-contrib-hud {
    position: absolute;
    top: 8px;
    left: var(--playable-center-x, 50%);
    transform: translateX(-50%);
    width: 600px;
    z-index: 505;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    padding: 6px 8px;
    pointer-events: none;
    user-select: none;
    font-family: var(--game-font);
}
body.login-active .raid-contrib-hud { display: none !important; }

.raid-contrib-row {
    margin-bottom: 4px;
}
.raid-contrib-row:last-child { margin-bottom: 0; }

/* Bar wrapper is the full row. Fill grows left-to-right; label
   overlays the whole wrapper so the name reads inside the fill.
   Outline color is mixed lighter than the fill via color-mix so the
   bar always reads against the surrounding panel regardless of theme. */
.raid-contrib-barwrap {
    position: relative;
    width: 100%;
    height: 26px;
    background: rgba(0, 0, 0, 0.55);
    border: 1px solid color-mix(in srgb, var(--bar-fill-damage) 70%, white 30%);
    border-radius: 3px;
    overflow: hidden;
}
.raid-contrib-barwrap-progress {
    border-color: color-mix(in srgb, var(--bar-fill-progress) 70%, white 30%);
}

.raid-contrib-barfill {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    background: linear-gradient(
        to bottom,
        color-mix(in srgb, var(--bar-fill-damage) 85%, white 15%),
        color-mix(in srgb, var(--bar-fill-damage) 85%, black 15%)
    );
    transition: width 0.2s ease;
}

/* Top progress row uses the theme's progress hue so it reads as a
   different metric from the per-player damage bars. */
.raid-contrib-barfill-progress {
    background: linear-gradient(
        to bottom,
        color-mix(in srgb, var(--bar-fill-progress) 85%, white 15%),
        color-mix(in srgb, var(--bar-fill-progress) 85%, black 15%)
    );
}

.raid-contrib-bar-dead {
    position: absolute;
    top: 0;
    right: 0;
    width: 50%;
    height: 100%;
    background: rgba(80, 80, 80, 0.75);
}

/* Label sits on top of the bar wrapper (not the fill) so the name
   stays readable even when the fill is narrow. 3-cell grid for
   name (left) / pct or timer (center) / dmg or hp (right). */
.raid-contrib-label {
    position: absolute;
    inset: 0;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    align-items: center;
    gap: 8px;
    padding: 0 10px;
    font-size: 16px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    line-height: 1;
    pointer-events: none;
}
.raid-contrib-name {
    text-align: left;
    white-space: nowrap;
    width: 100px;
}
.raid-contrib-pct {
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.raid-contrib-dmg {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.raid-contrib-progress .raid-contrib-label {
    font-weight: bold;
}
.raid-contrib-row.is-dead .raid-contrib-label {
    color: var(--text-dim);
}

/* ── Special-drop odds ladder (endless raids only) ── */
.raid-contrib-specials {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    margin: 2px 0 5px;
}
/* Gauntlet HUD reuses the ladder under its stat rows — center it. */
.gauntlet-hud-rares {
    justify-content: center;
    margin: 4px 0 2px;
}
.raid-contrib-spec-caption {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin-right: 2px;
}
.raid-contrib-spec-pill {
    position: relative;
    font-size: 11px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    padding: 1px 5px;
    border-radius: 3px;
    background: rgba(0, 0, 0, 0.35);
    border: 1px solid currentColor;
    line-height: 1.4;
    /* The raid HUD root is pointer-events:none so it never eats world
       clicks; opt the pills back in so they can be hovered for the
       shared TooltipManager tooltip. */
    pointer-events: auto;
    cursor: help;
}
/* Tier hues mirror the icon convention: T1 green -> T5 purple, C magenta. */
.raid-contrib-spec-pill.spec-t1 { color: #57d36a; }
.raid-contrib-spec-pill.spec-t2 { color: #4ea3ff; }
.raid-contrib-spec-pill.spec-t3 { color: #ff9d3c; }
.raid-contrib-spec-pill.spec-t4 { color: #ff5a52; }
.raid-contrib-spec-pill.spec-t5 { color: #c46bff; }
.raid-contrib-spec-pill.spec-c  { color: #ff5ad6; }
/* C7 (the tool band, wave 121+) is the last rung, so it takes the chaos
   tier's rainbow. The text colour stays a solid so the currentColor
   border and the capped glow still resolve; the spectrum rides behind it
   as a low-alpha background instead. */
.raid-contrib-spec-pill.spec-c7 {
    color: #fff2a8;
    background: linear-gradient(90deg, rgba(255, 68, 68, 0.38), rgba(255, 136, 0, 0.38),
        rgba(255, 221, 0, 0.38), rgba(68, 255, 68, 0.38), rgba(68, 136, 255, 0.38),
        rgba(136, 68, 255, 0.38));
}
/* Dimmed before wave 121 — drop the spectrum so it reads as "not yet". */
.raid-contrib-spec-pill.spec-c7.inactive { background: rgba(0, 0, 0, 0.35); }
/* Not yet active (wave below the tier's activation): dimmed + neutral. */
.raid-contrib-spec-pill.inactive {
    opacity: 0.4;
    color: var(--text-dim);
}
/* Hit the 50% cumulative cap — glow so it reads as "maxed". */
.raid-contrib-spec-pill.capped {
    box-shadow: 0 0 5px currentColor;
}

/* ── Raid DPS panel: vertical tab rail (DPS Current / DPS Total /
   Recap). The rail attaches to the panel's top-left and sticks out to
   the left so it costs no vertical space. The HUD is pointer-events:none,
   so the rail re-enables pointer events for itself only. */
.raid-contrib-tabs {
    position: absolute;
    top: 0;
    right: 100%;            /* sit just left of the panel's left edge */
    display: flex;
    flex-direction: column;
    gap: 3px;
    pointer-events: auto;
}
.raid-contrib-tab {
    appearance: none;
    -webkit-appearance: none;
    font-family: var(--game-font);
    font-size: 14px;
    line-height: 1.2;
    white-space: nowrap;
    text-align: right;
    padding: 5px 8px;
    cursor: pointer;
    color: var(--text-muted);
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-right: none;
    border-radius: 5px 0 0 5px;
    width: 100px;
}
.raid-contrib-tab:hover {
    background: var(--bg-hover);
    color: var(--text-light);
}
.raid-contrib-tab.active {
    background: color-mix(in srgb, var(--bar-fill-damage) 65%, black 35%);
    color: var(--text-bright);
    font-weight: bold;
}

/* ── Collapse toggle. Shared chrome for both top-center raid HUDs (Raid
   DPS and Fortress): a chevron on the panel's right edge mirroring the
   tab rail on the left, so it costs no vertical space, and re-enabling
   pointer events for itself the same way. What .hud-collapsed actually
   hides is per-HUD, see the rules further down. The starting state comes
   from the Raids settings; the in-run toggle is temporary. */
.hud-collapse-btn {
    position: absolute;
    top: 0;
    left: 100%;             /* sit just right of the panel's right edge */
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    color: var(--text-muted);
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-left: none;
    border-radius: 0 5px 5px 0;
    pointer-events: auto;
}
.hud-collapse-btn:hover {
    background: var(--bg-hover);
    color: var(--text-light);
}
/* Chevron points down while collapsed ("open me downward") and flips
   once the hidden rows are showing. */
.hud-collapse-btn svg {
    transition: transform 0.15s ease;
}
.raid-contrib-hud:not(.hud-collapsed) > .hud-collapse-btn svg,
.gauntlet-hud:not(.hud-collapsed) > .hud-collapse-btn svg {
    transform: rotate(180deg);
}

/* Raid DPS collapsed: every party row but yours drops out. The render
   path still builds them all, so shares, DPS and the leader-normalized
   bar widths stay correct on the row that remains. Skipped when we
   can't identify your row (.raid-contrib-noself, e.g. spectating) so
   the meter never collapses to no bars at all. */
.raid-contrib-hud.hud-collapsed:not(.raid-contrib-noself)
    .raid-contrib-rows > .raid-contrib-row:not(.is-self) {
    display: none;
}
/* :last-child still targets a hidden row, so clear the margin on the
   one row that is actually visible. */
.raid-contrib-hud.hud-collapsed:not(.raid-contrib-noself)
    .raid-contrib-rows > .raid-contrib-row.is-self {
    margin-bottom: 0;
}

/* ═══════════════════════════════════════════════════════════════
   Gauntlet HUD — top-center army meter during the skilling raid.
   Same placement rules as the raid contrib HUD (TaskDisplay is
   hidden while visible). Each stat row: your army's bar filling
   left→right | stat label | enemy wave's bar filling right→left.
   ═══════════════════════════════════════════════════════════════ */
.gauntlet-hud {
    position: absolute;
    top: 8px;
    left: var(--playable-center-x, 50%);
    transform: translateX(-50%);
    width: 640px;
    z-index: 505;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    padding: 6px 8px;
    pointer-events: none;
    user-select: none;
    font-family: var(--game-font);
}
body.login-active .gauntlet-hud { display: none !important; }

.gauntlet-hud-header {
    font-size: 15px;
    font-weight: bold;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
    margin-bottom: 5px;
    font-variant-numeric: tabular-nums;
}

/* Wave charge bar under the header: fills toward the next wave during
   prep (gold), charges each damage-exchange round during a wave (red,
   resets every 4s). The transition glides between 4 Hz server updates. */
.gauntlet-hud-chargewrap {
    height: 5px;
    background: rgba(0, 0, 0, 0.55);
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 5px;
}
.gauntlet-hud-chargefill {
    height: 100%;
    width: 0;
    background: #d4af37;
    transition: width 0.25s linear;
}
.gauntlet-hud-chargewrap.in-wave .gauntlet-hud-chargefill {
    background: #ff4d4d;
    /* Each exchange round resets the fill to ~0 — skip the glide on the
       way down so it reads as a snap + recharge, not a rewind. */
    transition: width 0.25s linear;
}

.gauntlet-hud-row {
    display: grid;
    grid-template-columns: 1fr 92px 1fr;
    align-items: center;
    gap: 4px;
    margin-bottom: 3px;
}

/* Fortress collapsed: the five army stat rows drop out. The header,
   wave-charge bar, loot-chance ladder and the role footer all stay, so
   the HUD keeps telling you where the wave is and lets you keep
   switching roles without expanding. */
.gauntlet-hud.hud-collapsed .gauntlet-hud-row {
    display: none;
}

.gauntlet-hud-statlabel {
    text-align: center;
    font-size: 13px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    /* HUD root is pointer-events:none; opt the label back in so its
       "what does this stat do" tooltip is hoverable. */
    pointer-events: auto;
    cursor: help;
}

.gauntlet-hud-barwrap {
    position: relative;
    height: 20px;
    background: rgba(0, 0, 0, 0.55);
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    overflow: hidden;
    /* Hoverable for the per-player contribution / enemy-lane tooltip. */
    pointer-events: auto;
    cursor: help;
}
.gauntlet-hud-barfill {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    opacity: 0.8;
    transition: width 0.2s ease;
}
/* Enemy side mirrors: fill anchors right and grows right→left. */
.gauntlet-hud-barwrap.mirrored .gauntlet-hud-barfill {
    left: auto;
    right: 0;
}
/* During prep the enemy side previews the UPCOMING wave, dimmed so it
   reads as "incoming" rather than "under attack". */
.gauntlet-hud-barwrap.upcoming { opacity: 0.55; }
.gauntlet-hud-barwrap.upcoming .gauntlet-hud-barfill {
    background-image: repeating-linear-gradient(
        45deg, rgba(0,0,0,0.25) 0 6px, transparent 6px 12px);
}
.gauntlet-hud-barval {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 0 6px;
    font-size: 13px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.gauntlet-hud-barwrap.mirrored .gauntlet-hud-barval {
    justify-content: flex-start;
}

/* Footer = mid-raid role switcher. One column per role: a clickable
   pill (the pair's two skill icons) above a live roster of the party
   sprites currently on that role. */
.gauntlet-hud-footer {
    margin-top: 6px;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    gap: 8px;
    /* Children opt back into pointer events individually. */
    pointer-events: none;
}
.gauntlet-foot-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    min-width: 44px;
}
.gauntlet-foot-pill {
    position: relative;
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 2px 5px;
    border-radius: 4px;
    background: rgba(0, 0, 0, 0.4);
    border: 1px solid var(--border-secondary);
    pointer-events: auto;
    cursor: pointer;
    transition: border-color 0.1s, background 0.1s, box-shadow 0.1s;
}
.gauntlet-foot-pill:hover {
    border-color: var(--role-color, var(--text-accent));
    background: rgba(0, 0, 0, 0.6);
}
/* The local player's current role. */
.gauntlet-foot-pill.active {
    border-color: var(--role-color, var(--text-accent));
    background: color-mix(in srgb, var(--role-color, #888) 28%, rgba(0, 0, 0, 0.5));
    box-shadow: 0 0 5px var(--role-color, transparent);
}
.gauntlet-foot-pill-icon {
    width: 18px;
    height: 18px;
    image-rendering: pixelated;
}
.gauntlet-foot-roster {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 2px;
    max-width: 92px;
}
.gauntlet-foot-sprite {
    position: relative;
    width: 28px;
    height: 34px;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    pointer-events: auto;
    cursor: help;
}
.gauntlet-foot-sprite.offline {
    opacity: 0.45;
    filter: grayscale(0.7);
}
.gauntlet-foot-sprite canvas {
    image-rendering: pixelated;
}
.gauntlet-foot-sprite-fallback {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--bg-hover, #333);
    border: 1px solid var(--border-secondary);
    color: var(--text-light);
    font-size: 12px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ── Recap view (Recap tab), rendered inside the DPS panel. Two
   columns: stats (left) | loot received (right). ── */
.raid-recap-cols {
    display: flex;
    gap: 16px;
    align-items: flex-start;
}
.raid-recap-col-stats { flex: 0 0 46%; }
.raid-recap-col-loot {
    flex: 1 1 auto;
    min-width: 0;
}
.raid-recap-header {
    font-size: 15px;
    font-weight: bold;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
    margin-bottom: 6px;
    padding-bottom: 5px;
    border-bottom: 1px solid var(--border-secondary);
}
.raid-recap-stats {
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.raid-recap-stat {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 14px;
}
.raid-recap-stat-label { color: var(--text-muted); }
.raid-recap-stat-value {
    color: var(--text-bright);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.raid-recap-subhead {
    margin: 8px 0 4px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-accent);
}
/* In the two-column layout the loot heading is the column's first row,
   so drop its top margin to line up with the stats column. */
.raid-recap-col-loot .raid-recap-subhead { margin-top: 0; }
.raid-recap-loot-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.raid-recap-loot-empty {
    font-size: 13px;
    font-style: italic;
    color: var(--text-dim);
}


.float-task-inner {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-top: none;
    border-radius: 0 0 6px 6px;
    padding: 6px 10px;
}

.floating-current-task.combat-expanded .float-task-inner {
    border-radius: 0;
    border-bottom: 1px solid var(--border-primary);
}

/* ── Skill icon ── */
.float-icon {
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-cell);
    border: 2px solid var(--text-accent);
    border-radius: 4px;
}

.float-icon img,
.float-icon canvas {
    width: 44px;
    height: 44px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* ── Details column ── */
.float-details {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.float-task-name {
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.float-task-node {
    font-size: 18px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── Progress bars ── */
.float-bar {
    position: relative;
    width: 100%;
    height: 16px;
    background: var(--bg-darkest);
    border-radius: 3px;
    overflow: hidden;
}

.float-bar-fill {
    height: 100%;
    transition: width .3s;
}

.float-bar-fill.task-fill {
    background: linear-gradient(180deg, #4caf50 0%, #2e7d32 100%);
}

.float-bar-fill.level-fill {
    background: linear-gradient(180deg, #3a8fd6 0%, #2567a8 100%);
}

/* ── Text overlay on bars ── */
.float-bar-text {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 6px;
    pointer-events: none;
}

.float-bar-text span {
    font-size: 16px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    line-height: 1;
}

.float-bar-text .bar-center {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
}

/* ── Combat info row (Row 2: loadout + skill, two equal columns) ── */
.float-combat-info {
    display: flex;
    align-items: center;
    padding: 4px 10px;
    background: var(--bg-panel);
    border-left: 2px solid var(--border-primary);
    border-right: 2px solid var(--border-primary);
    font-size: 17px;
    line-height: 1;
}

.float-combat-col {
    flex: 1;
    text-align: center;
    text-shadow: 1px 1px 0 #000;
    cursor: pointer;
}
.float-combat-col:hover {
    text-decoration: underline;
}

.float-combat-col:first-child {
    color: var(--text-gold);
}

.float-combat-col:last-child {
    color: var(--text-light);
}

/* ── Combat toggle row (Row 3: auto-slay + auto-loadout pills, two equal columns) ── */
.float-combat-toggles {
    display: flex;
    align-items: center;
    padding: 4px 10px 5px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-top: 1px solid var(--border-primary);
    border-radius: 0 0 6px 6px;
}

.float-toggle-pill {
    flex: 1;
    font-family: var(--game-font);
    font-size: 15px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 10px;
    padding: 2px 12px;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.float-toggle-pill:hover {
    background: var(--bg-cell);
    color: var(--text-light);
    border-color: var(--text-accent);
}

.float-toggle-pill.active {
    color: var(--text-bright);
    border-color: var(--text-accent);
    background: var(--bg-cell);
}

/* ── Auto toggle row (auto-slay + auto-loadout side by side) ── */
.auto-toggle-row {
    display: flex;
    gap: 6px;
}

.auto-toggle-row .auto-slay-btn {
    flex: 1;
}

/* ── Save Autoloadout button (Mob Selection Modal) ── */
.save-autoloadout-btn {
    width: 100%;
    height: 38px;
    padding: 4px 20px;
    font-family: var(--game-font);
    font-size: 19px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
    text-align: center;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.save-autoloadout-btn:hover {
    background: var(--bg-cell);
    color: var(--text-gold);
    border-color: var(--text-accent);
}

.autoloadout-confirm {
    font-family: var(--game-font);
    font-size: 17px;
    color: #4caf50;
    text-shadow: 1px 1px 0 #000;
    text-align: center;
    padding: 4px 0;
}

/* ── Combat Defaults (Settings) ── */
.combat-defaults-wrap {
    padding: 4px 0;
}

.combat-defaults-fam-label {
    font-family: var(--game-font);
    font-size: 14px;
    color: var(--text-accent);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin: 8px 0 4px;
}

.combat-defaults-btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 10px;
}

.combat-defaults-btn {
    font-family: var(--game-font);
    font-size: 18px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 4px 14px;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.combat-defaults-btn:hover {
    background: var(--bg-cell);
    color: var(--text-light);
    border-color: var(--text-accent);
}

.combat-defaults-btn.active {
    color: var(--text-bright);
    border-color: var(--text-accent);
    background: var(--bg-cell);
}

/* ── Potion Stats Toggle (brew icon in stats panels) ── */
.potion-stats-toggle-wrap {
    position: absolute;
    top: 6px;
    right: 6px;
    cursor: pointer;
    z-index: 1;
}

.spirit-stats-toggle-wrap {
    position: absolute;
    top: 6px;
    right: 44px;
    cursor: pointer;
    z-index: 1;
}

/* Gear Calc launcher — mirrors the brew/spirit toggles but sits top-left. */
.gearcalc-launch-wrap {
    position: absolute;
    top: 6px;
    left: 6px;
    cursor: pointer;
    z-index: 1;
}
.gearcalc-launch {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    opacity: 0.6;
    transition: opacity 0.15s;
    filter: drop-shadow(1px 1px 0 #000);
}
.gearcalc-launch:hover { opacity: 1.0; }

.equip-stats-panel {
    position: relative;
}

.potion-stats-toggle,
.spirit-stats-toggle {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    opacity: 0.4;
    transition: opacity 0.15s;
    filter: drop-shadow(1px 1px 0 #000);
}

.potion-stats-toggle.active,
.spirit-stats-toggle.active {
    opacity: 1.0;
}

.potion-stats-toggle:hover,
.spirit-stats-toggle:hover {
    opacity: 0.8;
}

.potion-stats-toggle.active:hover,
.spirit-stats-toggle.active:hover {
    opacity: 1.0;
}

.combat-defaults-apply-btn {
    width: 100%;
    padding: 8px 16px;
    font-family: var(--game-font);
    font-size: 20px;
    color: var(--text-gold);
    text-shadow: 1px 1px 0 #000;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
    text-align: center;
    transition: background 0.15s, border-color 0.15s;
    margin-top: 6px;
}

.combat-defaults-apply-btn:hover {
    background: var(--bg-cell);
    border-color: var(--text-accent);
}


/* ═══════════════════════════════════════════════════════════════
   Shared Tooltip Styles
   Used by Skills Panel, Inventory, and future panels.
   ═══════════════════════════════════════════════════════════════ */

.tooltip {
    display: none;
    position: absolute;
    z-index: 100;
    left: 50%;
    bottom: calc(100% + 8px);
    transform: translateX(-50%);
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 6px 10px;
    white-space: nowrap;
    pointer-events: none;
    text-align: left;
    box-shadow: 0 2px 8px rgba(0,0,0,0.8);
}

/* Per-element tooltips stay display:none — TooltipManager shows the global tooltip */

/* Global tooltip rendered by TooltipManager.js. Mounted on document.body
   (a sibling of the tutorial overlay) so its z-index can directly beat
   the tutorial highlight ring/bubble. position: fixed + viewport coords;
   TooltipManager applies transform: scale(...) to match the scaled
   #ui-container so the tooltip looks the right size at any viewport. */
.global-tooltip {
    position: fixed;
    z-index: 99999;
    left: auto;
    bottom: auto;
    transform: none;
}

.tooltip .tt-name {
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

.tooltip .tt-line {
    font-size: 22px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
}
/* Effective combat level, e.g. "Effective 96 (Unlocks: 5, Potions: 3)".
   Accented so it reads as the derived number rather than another plain
   stat line, and slightly smaller since it sits under the real level. */
.tooltip .tt-line.tt-eff {
    font-size: 20px;
    color: var(--text-accent);
}

/* Opt a long tooltip line out of the tooltip's default nowrap so
   multi-sentence descriptions wrap instead of stretching off-screen. */
.tooltip .tt-line.tt-wrap {
    white-space: normal;
    max-width: 320px;
}
.tt-potion-boost {
    display: flex;
    align-items: center;
    gap: 4px;
}
.tt-food-boost {
    display: flex;
    align-items: center;
    gap: 4px;
    color: #e07b6c;
}
.tt-skill-icon {
    width: 16px;
    height: 16px;
    image-rendering: pixelated;
}
.tt-section-label {
    color: var(--accent, #f0a040);
    font-weight: 700;
    margin-top: 4px;
}
/* Visual break between stacked tooltip sections (e.g. the combined
   barter-header tooltip: Gold split on top, Pool Access underneath). */
.tt-divider {
    height: 1px;
    background: var(--border-primary, rgba(255,255,255,0.15));
    margin: 8px 0;
}
.tt-pool-row {
    display: flex;
    align-items: center;
    gap: 6px;
}
.tt-pool-label {
    min-width: 160px;
}
.tt-pool-tier {
    min-width: 70px;
    color: var(--text-bright);
    font-weight: 600;
}
.tt-pool-icons {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-left: auto;
}

/* BUY / SELL pills used in the barter-header tooltip price-range block.
   Colors mirror .barter-buy-btn / .barter-sell-btn so the pill reads as
   the same action surface as the slot buttons below the header. */
.tt-pill {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.5px;
    line-height: 1.2;
}
.tt-pill-buy {
    background: #2a4a2a;
    color: #88cc88;
}
.tt-pill-sell {
    background: #4a2a2a;
    color: #cc8888;
}

.tooltip .tt-bar-bg {
    margin-top: 4px;
    height: 6px;
    background: var(--bg-darkest);
    border-radius: 2px;
    overflow: hidden;
}

.tooltip .tt-bar-fill {
    height: 100%;
    background: #4caf50;
}

/* Trimmed Cape phases — matches the skill cell's bar (see .skill-progress-fill). */
.tooltip .tt-bar-fill.trimmed-phase,
.tooltip .tt-bar-fill.done-phase {
    background: var(--text-gold, #e8c15a);
}

/* Equipment stat table inside tooltips — mirrors stats panel layout */
.tooltip .tt-equip-table {
    border-collapse: collapse;
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
    margin-top: 4px;
}
.tooltip .tt-equip-table th {
    color: var(--text-accent);
    font-weight: normal;
    padding: 1px 6px;
    text-align: center;
    border-bottom: 1px solid var(--bg-cell);
}
.tooltip .tt-equip-table th:first-child {
    text-align: left;
    width: 100px;
}
.tooltip .tt-equip-table td {
    padding: 1px 6px;
    text-align: center;
    color: var(--text-light);
}
.tooltip .tt-equip-table td:first-child {
    text-align: left;
    color: var(--text-accent);
    width: 100px;
}
.tooltip .tt-equip-table .stat-pos { color: #4caf50; }
.tooltip .tt-equip-table .stat-zero { color: var(--border-primary); }
.tooltip .tt-equip-table .stat-neg { color: #ff4444; }
.tooltip .tt-equip-table .str-cell { text-align: center; color: var(--text-light); }
.tooltip .tt-equip-table .str-label { color: var(--text-muted); }
.tooltip .tt-equip-icon-wrap {
    display: inline-block;
    vertical-align: middle;
    width: 20px;
    height: 20px;
    margin-right: 4px;
}
.tooltip .tt-equip-icon-wrap img {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.tooltip .tt-style-val { color: var(--text-accent); }
.tooltip .tt-speed-val { color: #88cc88; }
.tooltip .tt-maxhit-val { color: #ff6644; }
.tooltip .tt-compare-hint {
    font-size: 18px;
    color: var(--text-dim);
    margin-top: 2px;
}

/* Special-item passive effect text */
.tooltip .tt-special-desc {
    color: #c9a0ff;
    margin-top: 3px;
    white-space: normal;
    max-width: 320px;
}
.tooltip .tt-special-req {
    color: #AAAAAA;
    font-style: italic;
}

/* Overworld node tooltip — wraps multi-line content (default tooltip is nowrap). */
.global-tooltip.node-style {
    white-space: normal;
    max-width: 520px;
    padding: 8px 12px;
}
/* Keep "Nearest bank: <name> (<dist>)" on a single line — the parenthetical
   distance was wrapping below the bank name at the previous max-width. */
.global-tooltip.node-style .tt-bank-line {
    white-space: nowrap;
}
.global-tooltip.node-style .tt-name {
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 2px;
}
.global-tooltip.node-style .tt-line {
    font-size: 22px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
}
.global-tooltip.node-style .tt-val {
    color: var(--text-bright);
    font-weight: 600;
}
.global-tooltip.node-style .tt-dim {
    color: var(--text-dim);
    font-size: 20px;
}
.global-tooltip.node-style .tt-section-label {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--accent, #f0a040);
    font-weight: 700;
    font-size: 22px;
    margin-top: 6px;
    margin-bottom: 2px;
}
.global-tooltip.node-style .tt-skill-icon {
    width: 22px;
    height: 22px;
    image-rendering: pixelated;
}
.global-tooltip.node-style .tt-act-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 20px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    padding: 1px 0;
}
.global-tooltip.node-style .tt-act-lv {
    min-width: 56px;
    color: var(--text-bright);
    font-weight: 600;
}
.global-tooltip.node-style .tt-act-icon {
    width: 24px;
    height: 24px;
    image-rendering: pixelated;
}
.global-tooltip.node-style .tt-act-name {
    flex: 1;
}
.global-tooltip.node-style .tt-attack-line {
    display: flex;
    align-items: center;
    gap: 6px;
}
.global-tooltip.node-style .tt-style-icon {
    width: 22px;
    height: 22px;
    image-rendering: pixelated;
    vertical-align: middle;
}


/* ═══════════════════════════════════════════════════════════════
   Custom Scrollbar (matches mockup palette)
   ═══════════════════════════════════════════════════════════════ */

#ui-container ::-webkit-scrollbar { width: 8px; }
#ui-container ::-webkit-scrollbar-track { background: var(--bg-dark); }
#ui-container ::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }


/* ═══════════════════════════════════════════════════════════════
   Tasks Panel — Right Side (320×440, above Skills Panel)
   1 current-slot + 5 queue-slots with hover popout.
   Matches mocks/tasks_panel.html exactly.
   ═══════════════════════════════════════════════════════════════ */

.tasks-panel {
    position: absolute;
    right: 0px;
    bottom: 66px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 6px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 320px;
    height: 440px;
}

/* Slay queue panel — shares the same bottom-right slot as the tasks
 * panel; toggled by the dedicated slay tab on the panel tab bar.
 */
.slay-tasks-panel {
    position: absolute;
    right: 0px;
    bottom: 66px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 6px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 320px;
    height: 440px;
}

/* Pin-popouts toggle — small button in the top-right corner of the
 * tasks / slay queue panels. When active it forces every option popout
 * in the panel to stay expanded (panel gets .popouts-pinned and each
 * .icon-container keeps .tap-open) instead of revealing only on hover.
 * State persists per panel in localStorage. z-index sits above the
 * expanded popouts (container z-60) so the button stays clickable. */
.queue-pin-btn {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    color: var(--text-muted);
    cursor: pointer;
    opacity: 0.7;
    transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.queue-pin-btn:hover {
    opacity: 1;
    background: var(--bg-hover);
    color: var(--text-light);
}
.queue-pin-btn svg {
    width: 13px;
    height: 13px;
    display: block;
    fill: currentColor;
}
.queue-pin-btn.active {
    opacity: 1;
    color: var(--text-gold);
    border-color: var(--border-secondary);
    background: var(--bg-hover);
}
/* In windowed mode the panel grows a 24px titlebar (with min/close
 * buttons at the top-right). Drop the pin below it so it doesn't
 * overlap those controls. */
body.panels-windowed .queue-pin-btn {
    top: 34px;
}

/* Master / control row — bottom of the slay panel. Six master tiles
 * on the left + Begin Combat + Auto Loadout on the right. Same height
 * as a queue-slot so the panel reads as a balanced 6-row stack.
 */
.slay-master-row {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 4px;
    background: var(--bg-cell);
    border: 2px solid var(--border-primary);
    border-radius: 4px;
    padding: 4px 6px;
}

/* Vertical pairs in the master row.
 *   .slay-combat-pair = Begin Combat (top) / Queue Combat (bottom).
 *   .slay-toggle-pair = Auto Slay (top) / Auto Loadout (bottom), far right.
 * margin-left:auto on the combat pair pushes both stacks to the right
 * so the picker's leftward popout doesn't have to overlap them.
 */
.slay-combat-pair,
.slay-toggle-pair {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex-shrink: 0;
}
.slay-combat-pair { margin-left: auto; }

/* Master picker container — uses the icon-container popout pattern.
 * Default state shows only the .selected tile (others display:none via
 * the .icon-container:not(:hover) .master-tile:not(.selected) rule).
 * Hover state widens the wrapper leftward to reveal the rest of the
 * masters in tier order, with the selected master pinned to the right.
 */
.slay-master-picker {
    width: 56px;
    height: 56px;
}
.slay-master-picker .icons-wrapper {
    gap: 4px;
}
.icon-container.slay-master-picker:not(:hover):not(.tap-open) .master-tile:not(.selected) {
    display: none;
}
.icon-container.slay-master-picker:hover .master-tile,
.icon-container.slay-master-picker.tap-open .master-tile {
    display: flex !important;
}

.master-tile {
    position: relative;
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid transparent;
    border-radius: 4px;
    cursor: pointer;
    background: var(--bg-dark);
    overflow: visible;
    transition: transform 0.1s ease, box-shadow 0.15s ease;
}

.master-tile img {
    width: 44px;
    height: 44px;
    object-fit: contain;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* Tier badge inside a master tile sits at the bottom-left corner. */
.master-tier-label {
    font-size: 16px;
}

.master-tile:hover {
    transform: scale(1.08);
}

/* Selected: tier border (inline style) + accent inset shadow ring so
 * it stands out even though the border colour stays tier-themed.
 */
.master-tile.selected {
    box-shadow: 0 0 0 2px var(--text-accent) inset;
}

/* Locked: dim ONLY the image (and the label slightly) so the tooltip
 * stays at full readability when the player hovers a tier they don't
 * meet the slay level for. Avoid `opacity` on the tile itself —
 * opacity creates a stacking context and child opacity is multiplied
 * by the parent's, so a tooltip can't escape a dimmed parent.
 */
.master-tile.locked {
    cursor: not-allowed;
}
.master-tile.locked img {
    opacity: 0.35;
}
.master-tile.locked .master-tier-label {
    opacity: 0.6;
}
.master-tile.locked:hover {
    transform: none;
}

/* Master-row text buttons (Begin Combat / Queue Combat / Auto Slay /
 * Auto Loadout). Stacked in pairs via .slay-combat-pair and
 * .slay-toggle-pair. Text labels show ON/OFF state inline for the two
 * toggle pills so the current setting is readable without hovering.
 */
.slay-row-btn {
    position: relative;
    width: 112px;
    height: 26px;
    padding: 0 8px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--bg-hover);
    border-radius: 4px;
    background: var(--bg-dark);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 12px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.slay-row-btn:hover {
    border-color: var(--text-accent);
    background: var(--bg-cell);
    color: var(--text-bright);
}
.slay-row-btn.active {
    border-color: var(--text-accent);
    background: var(--bg-cell);
    color: var(--text-bright);
}
/* Disabled: dim the label colour. Border + background stay readable.
 * Opacity isn't used here because the tooltip is a child element and
 * parent opacity would propagate into it.
 */
.slay-row-btn.disabled {
    cursor: not-allowed;
    color: rgba(180, 180, 180, 0.4);
}
.slay-row-btn.disabled:hover {
    border-color: var(--bg-hover);
    background: var(--bg-dark);
    color: rgba(180, 180, 180, 0.4);
}
/* Slay-row buttons and master tiles get their tooltips from TooltipManager
 * via a `.tooltip` child (not `.icon-tooltip`). The global tooltip is
 * viewport-clamped, so no local hover-show rule is needed here. */

/* ── Current Task Row ── */
.current-slot {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--bg-cell);
    border: 2px solid var(--border-secondary);
    border-radius: 4px;
    padding: 4px 6px;
}

.current-slot .icon-option {
    border-color: var(--text-accent);
}

/* Current-slot icon is display-only (cursor: default) — kill the
   inherited :hover scale. The transform creates a stacking context
   that traps the .icon-tooltip child below later-DOM-order siblings
   (notably the windowed-mode titlebar). Hover background + border
   still apply for normal feedback. */
.current-slot .icon-option:hover {
    transform: none;
}

.task-progress-bar {
    height: 4px;
    background: var(--bg-darkest);
    border-radius: 2px;
    overflow: hidden;
    margin-top: 2px;
}

.task-progress-fill {
    height: 100%;
    background: linear-gradient(180deg, #4caf50 0%, #2e7d32 100%);
    transition: width .3s;
}

/* ── Queue Slot Row ── */
.queue-slot {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 4px 6px;
    position: relative;
}

/* Whole-slot drag: cursor: grab on the slot itself; option icons /
   reroll button keep cursor: pointer via the more-specific override
   below so click affordance over the icon-container reads correctly.
   Source slot dims while dragging; drop targets highlight on the
   inner top/bottom edge depending on insert side. */
.queue-slot.queue-slot-draggable { cursor: grab; }
.queue-slot.queue-slot-draggable:active { cursor: grabbing; }
.queue-slot.queue-slot-draggable .icon-option,
.queue-slot.queue-slot-draggable .reroll-option { cursor: pointer; }
/* On touch, prevent the browser's default vertical-pan gesture from
   intercepting our drag-reorder pointermove stream. The icon area
   keeps its own touch-action: manipulation from the body.is-touch
   rule above so tap-to-select still feels snappy. */
body.is-touch .queue-slot.queue-slot-draggable { touch-action: none; }
body.is-touch .queue-slot.queue-slot-draggable .icon-container { touch-action: manipulation; }
.queue-slot.qsdh-source { opacity: 0.4; cursor: grabbing; }
.queue-slot.qsdh-drop-above {
    box-shadow: inset 0 3px 0 0 var(--text-bright);
}
.queue-slot.qsdh-drop-below {
    box-shadow: inset 0 -3px 0 0 var(--text-bright);
}

/* Combat-queued overlay divider. Straddles the boundary between the
   task row it sits under and the next one with zero flow impact: the
   parent slot is position:relative, divider is absolute-positioned
   with negative bottom so it half-overlaps the next slot's top edge.
   z-index sits above .icon-container (z-20) so the bar and its tooltip
   render in front of the task icons rather than behind them. */
.current-slot { position: relative; }
.combat-queued-divider {
    position: absolute;
    bottom: -12px;
    left: 0;
    right: 0;
    height: 28px;
    display: none;
    align-items: center;
    gap: 6px;
    padding: 0 2px;
    background: var(--bg-panel);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    z-index: 30;
    cursor: grab;
    touch-action: none;
    font-size: 14px;
    color: var(--text-bright);
    font-family: var(--game-font, inherit);
}
.combat-queued-divider.cqd-visible { display: flex; }
/* While dragging: dim slightly + grabbing cursor + brighter border so
   the bar reads as the thing being moved. */
.combat-queued-divider.cqd-dragging {
    cursor: grabbing;
    opacity: 0.9;
    border-color: var(--text-bright);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
}
.combat-queued-divider img.cqd-icon {
    width: 24px;
    height: 24px;
    image-rendering: pixelated;
    pointer-events: none;
}
.combat-queued-divider .cqd-label {
    flex: 1;
    pointer-events: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.combat-queued-divider .cqd-cancel {
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-bright);
    cursor: pointer;
    border: none;
    background: transparent;
    font-size: 14px;
    line-height: 1;
    font-family: inherit;
    padding: 0;
}
.combat-queued-divider .cqd-cancel:hover { color: var(--text-danger, #ff6b6b); }

/* ── Icon Container: popout on hover ── */
.icon-container {
    position: relative;
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    overflow: visible;
    z-index: 20;
}

/* Hovered (or tap-opened) container lifts above its siblings so its
   tooltip + popout render in front of neighboring task icons and
   their indicator badges, instead of being out-stacked by a later
   sibling sitting at the same z-20. */
.icon-container:hover,
.icon-container.tap-open {
    z-index: 60;
}

.icons-wrapper {
    display: flex;
    gap: 4px;
    position: absolute;
    right: 0;
    top: 0;
    z-index: 100;
    transition: all 0.2s ease;
    flex-direction: row-reverse;
}

/* Hide non-selected icons by default. The `.tap-open` class is the
   touch equivalent of :hover: TouchHelpers.tapToggleClass adds it
   when the user taps the icon-container on a touch device, removes
   it when they tap outside. Desktop keeps its hover-driven reveal. */
.icon-container:not(:hover):not(.tap-open) .icon-option:not(.selected) {
    display: none;
}
.icon-container:not(:hover):not(.tap-open) .reroll-option {
    display: none;
}

/* Expand on hover or tap. */
.icon-container:hover .icons-wrapper,
.icon-container.tap-open .icons-wrapper {
    background: var(--bg-panel);
    padding: 4px;
    border-radius: 4px;
    border: 1px solid var(--border-primary);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
    flex-direction: row;
}

.icon-container:hover .icon-option,
.icon-container:hover .reroll-option,
.icon-container.tap-open .icon-option,
.icon-container.tap-open .reroll-option {
    display: flex !important;
}

/* ── Individual icon option ── */
.icon-option {
    position: relative;
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-cell);
    border: 2px solid transparent;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.15s ease;
    flex-shrink: 0;
}

.icon-option:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
    transform: scale(1.08);
}

.icon-option.selected {
    background: var(--bg-cell);
    border-color: var(--text-accent);
}

.icon-option:not(.selected) {
    opacity: 0.5;
}
.icon-option:not(.selected):hover {
    opacity: 1;
}

.icon-option > img {
    width: 44px;
    height: 44px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.icon-qty {
    position: absolute;
    top: 0px;
    left: 2px;
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
    pointer-events: none;
}

.icon-qty-orange { color: #ff8c00; }
.icon-qty-red { color: #ff3232; }

.task-material-line {
    font-size: 16px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
}

.recenter-camera-btn {
    position: absolute;
    bottom: 80px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100;
    padding: 6px 16px;
    font-family: var(--game-font);
    font-size: 18px;
    color: var(--text-light);
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
    opacity: 0.8;
}
.recenter-camera-btn:hover {
    opacity: 1;
    color: var(--text-bright);
    border-color: var(--text-accent);
}
.recenter-camera-btn.combat-active {
    bottom: 140px;
}

/* z-index 4 (one below .icon-scroll-row-luck at 5) creates a stacking
   context so the inline z-indexes 100/99/98... on the cascading indicators
   inside this row stay scoped to the row. Without this they propagate up
   to #ui-container's context and render on top of queue-slot tooltips
   (which are trapped inside .icon-container at z-20). Luck row at z-5 stays
   above this row, preserving the existing overlay. */
.icon-scroll-row {
    position: absolute;
    bottom: 0px;
    left: 0px;
    height: 16px;
    pointer-events: none;
    z-index: 4;
}

.icon-scroll-indicator {
    position: absolute;
    bottom: 0;
    width: 22px;
    height: 22px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* ── Lucky tasks ────────────────────────────────────────────
   Border flips to --text-bright on the option icon, parent
   queue-slot, and the current-slot. Luck badge renders above
   quest/scroll indicators in the bottom-left corner. */
.icon-option.lucky,
.icon-option.lucky.selected,
.icon-option.lucky:hover {
    border-color: var(--text-bright);
}
.current-slot.lucky .icon-option.selected {
    border-color: var(--text-bright);
}
.queue-slot.lucky,
.current-slot.lucky {
    border-color: var(--text-bright);
}
/* Lucky badge sits in its own row container next to .icon-scroll-row.
   The container shares position/anchor with the scroll row but has a
   higher z-index so the luck icon overlays the quest/scroll icons at
   the same bottom-left position and size. Living outside .icon-scroll-row
   also keeps _renderIndicatorRow() from wiping it. */
.icon-scroll-row-luck {
    position: absolute;
    bottom: 0px;
    left: 0px;
    height: 16px;
    pointer-events: none;
    z-index: 5;
}
.luck-indicator { left: 0; }
.icon-tooltip .tt-line.tt-lucky-title { color: var(--text-bright); }
.icon-tooltip .tt-line.tt-lucky-line { color: var(--text-bright); }

/* ── Reroll button in popout ── */
.reroll-option {
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #2a2a1e;
    border: 2px solid var(--bg-hover);
    border-radius: 4px;
    cursor: pointer;
    font-size: 22px;
    color: var(--text-muted);
    font-family: var(--game-font);
    transition: all 0.15s ease;
    flex-shrink: 0;
}

.reroll-option:hover {
    color: var(--text-bright);
    border-color: var(--text-accent);
    background: var(--bg-cell);
    transform: scale(1.08);
}

.reroll-option.paused {
    opacity: 0.3;
    cursor: not-allowed;
    pointer-events: none;
    border-color: var(--text-accent);
}

/* Disabled: dim the glyph + border via colour so the icon-tooltip
 * stays at full opacity (CSS opacity on the tile would cascade into
 * the tooltip — its rendered opacity = parent × child — and there is
 * no way to escape a parent opacity from a child element).
 */
.reroll-option.disabled {
    color: rgba(180, 180, 180, 0.35);
    border-color: rgba(80, 80, 80, 0.6);
    cursor: not-allowed;
}
.reroll-option.disabled:hover {
    transform: none;
    color: rgba(180, 180, 180, 0.35);
    border-color: rgba(80, 80, 80, 0.6);
    background: #2a2a1e;
}

/* ── Task panel tooltips ── */
.icon-tooltip {
    display: none;
    position: absolute;
    z-index: 200;
    left: 50%;
    bottom: calc(100% + 8px);
    transform: translateX(-50%);
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 6px 10px;
    white-space: nowrap;
    pointer-events: none;
    text-align: left;
}
.icon-option:hover .icon-tooltip,
.reroll-option:hover .icon-tooltip,
.icon-option.tap-preview .icon-tooltip,
.reroll-option.tap-preview .icon-tooltip {
    display: block;
}
.icon-option.selected .icon-tooltip {
    border: 2px solid var(--text-bright);
}
/* On touch, the first tap on a popout child stamps .tap-preview;
   the second tap clears it and fires the click. A subtle border
   accent on the previewed item helps the user see which one is
   armed-but-not-yet-selected. */
body.is-touch .icon-option.tap-preview {
    box-shadow: inset 0 0 0 2px var(--text-bright);
}
.icon-tooltip .tt-name {
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}
.icon-tooltip .tt-line {
    font-size: 22px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
}
/* Quest match lines in task tooltips pop in the same accent color
   as the tooltip title so the player can spot at a glance that
   running this task also advances a quest. Sits on top of the
   default .tt-line color because this rule comes after. */
.icon-tooltip .tt-line.tt-quest-line {
    color: var(--text-bright);
}
/* Future (non-current) quest steps stay yellow but italicize and dim so
   the current step line reads as visually primary in a stack. Sits on
   top of the base .tt-quest-line color rule via class specificity. */
.icon-tooltip .tt-line.tt-quest-line.tt-quest-future {
    font-style: italic;
    opacity: 0.6;
}

/* ── Task details (to the right of icon) ── */
.task-details {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 2px;
    overflow: hidden;
    min-width: 0;
}

.task-name {
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.task-node {
    font-size: 18px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000;
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}


/* ═══════════════════════════════════════════════════════════════
   Quests Panel — At-a-glance active quest tracker (bottom-right)
   ═══════════════════════════════════════════════════════════════ */

.quests-panel {
    position: absolute;
    right: 0px;
    bottom: 66px;
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 6px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 320px;
    height: 440px;
}

/* ── Toggle Bar (Active / List) ── */
.qp-toggle-bar {
    display: flex;
    gap: 4px;
    margin-bottom: 4px;
    flex-shrink: 0;
}

.qp-toggle-btn {
    flex: 1;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    font-weight: 600;
    color: var(--text-muted);
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.15s ease;
}

.qp-toggle-btn:hover {
    color: var(--text-light);
    background: var(--bg-hover);
}

.qp-toggle-btn.active {
    color: var(--text-accent);
    background: var(--bg-hover);
    border-color: var(--text-accent);
}

.friends-add-btn {
    flex: 0 0 28px;
    font-size: 20px;
    font-weight: bold;
}
.friends-add-input {
    flex: 1;
    height: 28px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 2px 8px;
    font-family: var(--game-font);
    font-size: 18px;
    color: var(--text-light);
    outline: none;
}
.friends-add-input::placeholder { color: var(--text-dim); }
.friends-add-error {
    padding: 2px 8px;
    font-family: var(--game-font);
    font-size: 16px;
    color: #ff3232;
    text-shadow: 1px 1px 0 #000;
}

/* ── Content Area ── */
.qp-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.qp-content-active {
    gap: 4px;
}

.qp-content-list {
    gap: 0;
}

/* ── List Mode ── */
.qp-list-header {
    flex-shrink: 0;
    padding: 6px 8px;
    font-size: 16px;
    font-weight: 600;
    color: var(--text-light);
    text-align: center;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    margin-bottom: 4px;
}

.qp-list-scroll {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.qp-list-row {
    padding: 8px 10px;
    font-size: 16px;
    font-weight: 600;
    border-radius: 4px;
    white-space: nowrap;
    text-overflow: ellipsis;
    transition: background 0.1s ease;
    text-shadow: 1px 1px 0 #000;
}

.qp-list-row:hover {
    background: var(--bg-hover);
}

.quest-slot {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 6px 10px;
    background: var(--bg-cell);
    border: 2px solid var(--border-secondary);
    border-radius: 4px;
}

.quest-slot-empty {
    opacity: 0.4;
    display: flex;
    align-items: center;
    justify-content: center;
}

.quest-slot-empty-text {
    font-size: 13px;
    color: var(--text-dim);
}

.quest-slot-active {
    border-color: var(--text-accent);
}

.quest-slot-claimable {
    border-color: var(--text-bright);
    box-shadow: 0 0 6px color-mix(in srgb, var(--text-bright) 30%, transparent);
}

.quest-slot-header {
    display: flex;
    align-items: center;
    gap: 6px;
}

.quest-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.quest-dot-active {
    background: #e8d44d;
}

.quest-dot-claimable {
    background: #4a4;
}

.quest-slot-name {
    font-size: 16px;
    font-weight: 600;
    color: var(--text-light);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1;
}

.quest-slot-badge {
    font-size: 11px;
    padding: 1px 6px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--text-accent) 25%, transparent);
    color: var(--text-accent);
    flex-shrink: 0;
}

.quest-slot-badge-claim {
    background: color-mix(in srgb, var(--text-bright) 20%, transparent);
    color: var(--text-bright);
}

.quest-slot-progress {
    font-size: 13px;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.quest-slot-hint {
    font-size: 13px;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: flex;
    align-items: center;
    gap: 4px;
}

.quest-hint-icon {
    width: 14px;
    height: 14px;
    image-rendering: pixelated;
    flex-shrink: 0;
}


/* ═══════════════════════════════════════════════════════════════
   Friends Panel — Friend list with Online/Offline toggle
   ═══════════════════════════════════════════════════════════════ */

.friends-panel {
    position: absolute;
    right: 0px;
    bottom: 66px;
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 6px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 320px;
    height: 440px;
}

.friends-empty {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    color: var(--text-dim);
}

.friend-row {
    padding: 6px 8px;
    background: var(--bg-cell);
    border-radius: 4px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    transition: background 0.1s ease;
}

.friend-row:hover {
    background: var(--bg-hover);
}

.friend-row-header {
    display: flex;
    align-items: center;
    gap: 6px;
}

.friend-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.friend-row-name {
    font-size: 18px;
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.friend-row-activity {
    font-size: 14px;
    color: var(--text-dim);
    display: flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.friend-activity-icon {
    width: 24px;
    height: 24px;
    image-rendering: pixelated;
    flex-shrink: 0;
}


/* ═══════════════════════════════════════════════════════════════
   Player Context Menu — Right-click menu for player interactions
   ═══════════════════════════════════════════════════════════════ */

.player-ctx-menu {
    position: absolute;
    /* Wide enough to fit [TAG] Name [combat] N [total] N in the
       header without wrapping. */
    width: 300px;
    background: var(--bg-panel);
    border: 2px solid var(--border-secondary);
    border-radius: 6px;
    z-index: 2500;
    overflow: hidden;
}

/* Extended single-row header that packs clan tag + name + combat
   level + total level. Justified so the tag floats left, name takes
   the middle, and stat pills float right. */
.ctx-menu-header-multi {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.ctx-menu-header-multi .ctx-menu-tag,
.ctx-menu-header-multi .ctx-menu-name,
.ctx-menu-header-multi .ctx-menu-stat {
    font-size: 16px;
}
.ctx-menu-header-multi .ctx-menu-tag {
    font-weight: 600;
}
.ctx-menu-header-multi .ctx-menu-name {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ctx-menu-stat {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    color: var(--text-light);
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
}
.ctx-menu-stat img {
    width: 16px;
    height: 16px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.ctx-menu-header {
    padding: 8px 12px;
    font-size: 16px;
    font-weight: 600;
    color: var(--text-gold);
    text-shadow: 1px 1px 0 #000;
    border-bottom: 1px solid var(--border-primary);
    background: var(--bg-cell);
}

.ctx-menu-option {
    padding: 6px 12px;
    font-size: 14px;
    color: var(--text-light);
    cursor: pointer;
    transition: background 0.1s ease;
}

.ctx-menu-option:hover {
    background: var(--bg-hover);
    color: var(--text-accent);
}

/* Admin Actions header — mod-only section divider. Thick red bar
   so a mod can immediately tell admin tools from regular options. */
.ctx-menu-admin-header {
    margin-top: 4px;
    padding: 6px 12px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: #ffe0e0;
    background: rgba(160, 28, 28, 0.85);
    border-top: 3px solid #c83030;
    border-bottom: 1px solid rgba(220, 80, 80, 0.6);
    text-shadow: 1px 1px 0 #000;
    user-select: none;
}
.ctx-menu-option-admin {
    color: #ffd0d0;
}
.ctx-menu-option-admin:hover {
    background: rgba(140, 28, 28, 0.55);
    color: #ffffff;
}
.ctx-menu-option-admin-danger {
    color: #ff9090;
    font-weight: 600;
}
.ctx-menu-option-admin-danger:hover {
    background: rgba(180, 28, 28, 0.7);
    color: #ffffff;
}

/* Stacked picker: shown when right-clicking on overlapping players.
   Each row is a header (hoverable) + a slot for the active row's options.
   Inactive rows show only the header; hovering swaps which slot fills. */
.ctx-menu-stacked-row {
    display: block;
}
.ctx-menu-stacked-row .ctx-menu-header {
    cursor: pointer;
    transition: background 0.1s ease, color 0.1s ease;
}
.ctx-menu-stacked-row .ctx-menu-header:hover,
.ctx-menu-header-active {
    background: var(--bg-hover) !important;
    color: var(--text-accent) !important;
}
.ctx-menu-stacked-slot {
    /* Slot is empty for inactive rows so they collapse to just the
       header. Active row's options are appended here. */
}

/* ── In-game Confirmation Dialog ── */
.ctx-confirm-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 1920px;
    height: 1080px;
    background: rgba(0, 0, 0, 0.5);
    z-index: 6600;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ctx-confirm-dialog {
    background: var(--bg-panel);
    border: 2px solid var(--border-secondary);
    border-radius: 8px;
    padding: 20px 28px;
    min-width: 280px;
    text-align: center;
}

.ctx-confirm-text {
    font-size: 18px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 16px;
}

.ctx-confirm-btns {
    display: flex;
    gap: 12px;
    justify-content: center;
}

/* Text input inside a confirm dialog (e.g. naming an outfit preset). */
.ctx-confirm-input {
    width: 100%;
    box-sizing: border-box;
    background: var(--bg-dark);
    color: var(--text-bright);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 8px 10px;
    font-family: var(--game-font);
    font-size: 18px;
    text-align: center;
    outline: none;
    margin-bottom: 16px;
    text-shadow: 1px 1px 0 #000;
}
.ctx-confirm-input:focus { border-color: var(--text-accent); }

.ctx-confirm-btn {
    padding: 6px 20px;
    font-size: 16px;
    font-family: var(--game-font);
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.15s ease;
}

.ctx-confirm-yes {
    background: #5c2a2a;
    border: 1px solid #f44336;
    color: #f44336;
}

.ctx-confirm-yes:hover {
    background: #7a3a3a;
}

.ctx-confirm-no {
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    color: var(--text-muted);
}

.ctx-confirm-no:hover {
    background: var(--bg-hover);
    color: var(--text-light);
}

/* Accent (recommended) confirm action, e.g. "Leave when this raid ends".
   Sits between the danger .ctx-confirm-yes and the neutral .ctx-confirm-no. */
.ctx-confirm-alt {
    background: #1f3a40;
    border: 1px solid #4fc3f7;
    color: #4fc3f7;
}

.ctx-confirm-alt:hover {
    background: #2a4e57;
}

/* ── Settings Muted Players List ── */
.settings-muted-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 4px;
}

.settings-muted-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 8px;
    background: var(--bg-cell);
    border-radius: 4px;
}

.settings-muted-name {
    font-size: 16px;
    color: #f44336;
    text-shadow: 1px 1px 0 #000;
}

.settings-muted-unmute {
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: 4px;
    transition: all 0.15s ease;
}

.settings-muted-unmute:hover {
    color: #f44336;
    background: var(--bg-hover);
}


/* ═══════════════════════════════════════════════════════════════
   Chat Panel — Bottom-left chat with channel filters
   ═══════════════════════════════════════════════════════════════ */

.chat-panel {
    position: absolute;
    left: 58px;
    bottom: 0px;
    width: 580px;
    height: 220px;
    display: flex;
    flex-direction: column;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    z-index: 5;
}

/* Sidebar collapsed: snap attached chat to the screen edge. The 58px
   gutter clears a tab strip that's no longer visible. Floating chat
   (user-dragged in windowed mode) keeps its inline left. */
body.side-tabs-collapsed .chat-panel:not(.panel-floating) {
    left: 0;
}

.chat-panel.chat-minimized {
    height: auto;
}

/* ── Filter Bar ── */
.chat-filter-bar {
    display: flex;
    gap: 0;
    flex-shrink: 0;
    background: var(--bg-cell);
    border-top: 2px solid var(--border-primary);
    border-radius: 0 0 6px 6px;
    padding: 0 4px;
}

/* ── Font Size Buttons ── */
.chat-font-btn {
    width: 24px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-family: var(--game-font);
    color: var(--text-muted);
    cursor: pointer;
    flex-shrink: 0;
    transition: color 0.15s ease;
}

.chat-font-btn:hover {
    color: var(--text-light);
}

/* ── Toggle Button (minimize/maximize) ── */
.chat-toggle-btn {
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    color: var(--text-muted);
    cursor: pointer;
    flex-shrink: 0;
    transition: color 0.15s ease;
}

.chat-toggle-btn:hover {
    color: var(--text-light);
}

/* ── Resize Handle (top edge) ── */
.chat-resize-handle {
    position: absolute;
    top: -3px;
    left: 10px;
    right: 10px;
    height: 6px;
    cursor: ns-resize;
    z-index: 11;
}

.chat-resize-handle-right {
    position: absolute;
    top: 10px;
    right: -3px;
    bottom: 10px;
    width: 6px;
    cursor: ew-resize;
    z-index: 11;
}

.chat-filter-btn {
    flex: 1;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
    font-family: var(--game-font);
    cursor: pointer;
    opacity: 0.35;
    transition: opacity 0.15s ease;
    text-shadow: 1px 1px 0 #000;
    position: relative;
}

.chat-filter-btn:hover {
    opacity: 0.7;
}

.chat-filter-btn.active {
    opacity: 1;
}

/* Unread-message dot on filter pills. Hidden until the parent button
   gets .has-unread (set when a message arrives on a hidden channel). */
.chat-filter-dot {
    display: none;
    position: absolute;
    top: 4px;
    right: 4px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #ff5050;
    box-shadow: 0 0 0 1px #000;
    pointer-events: none;
}
.chat-filter-btn.has-unread .chat-filter-dot {
    display: block;
}

/* ── Content Wrapper ── */
.chat-content-wrap {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* ── Message Area ── */
.chat-message-area {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 4px 8px;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.chat-timestamp {
    display: inline-block;
    width: 6.0ch;
    flex-shrink: 0;
    color: var(--text-dim);
}

/* 3-letter clan tag rendered between timestamp and sender. Case is
   preserved exactly as the leader entered it. */
.chat-clan-tag {
    color: var(--text-accent);
}

/* Player name before the colon. Brighter than the message body so the
   speaker stands out from their text. Theme-reactive via --text-bright. */
.chat-sender-name {
    color: var(--text-bright);
}

/* Staff crown icon rendered next to the sender (player chat) or
   before the event text (game events). Stamped by the server from
   the StaffAccounts allowlist. */
.chat-staff-crown-wrap {
    display: inline-flex;
    vertical-align: middle;
    position: relative;
    cursor: default;
}
.chat-staff-crown {
    width: 1.5em;
    height: 1.5em;
    image-rendering: pixelated;
    vertical-align: middle;
    margin-right: 3px;
}

.chat-game-icon {
    width: 1.15em;
    height: 1.15em;
    image-rendering: pixelated;
    vertical-align: middle;
    margin-right: 3px;
}

/* Fixed-width column reserved for the player badge so every line's name
   starts at the same horizontal spot whether or not the player has a
   badge. Stays empty (but still occupies width) for badge-less players. */
.chat-badge-slot {
    display: inline-block;
    width: 1.5em;
    margin-right: 3px;
    text-align: center;
    vertical-align: middle;
}
/* Badge sits inside the fixed slot, so drop its own right margin (the
   slot provides the gap to the name). */
.chat-badge-slot .chat-staff-crown-wrap { margin-right: 0; }
.chat-badge-slot .chat-staff-crown { margin-right: 0; }

.chat-message {
    font-size: inherit;
    font-family: var(--game-font);
    /* Tall enough to fully contain the 1.5em chat badge without clipping
       or overlapping the neighbouring line. */
    line-height: 1.6;
    text-shadow: 1px 1px 0 #000;
    word-wrap: break-word;
}

/* ── Input Row ── */
.chat-input-row {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 6px;
    border-top: 2px solid var(--border-primary);
    flex-shrink: 0;
}
/* Chat input wrapper — flex item that anchors the absolute icon to
   the input's left text-start position. The icon vanishes the moment
   the field has content via the :placeholder-shown sibling rule
   below, mirroring how the placeholder text itself disappears. */
.chat-input-wrap {
    position: relative;
    flex: 1;
    display: flex;
    align-items: stretch;
    min-width: 0;
}
.chat-input-wrap .chat-input {
    /* No left padding — when the user types we want the cursor and
       text to start at the field's left edge. The icon + placeholder
       are pushed right via text-indent below only while the field is
       empty (the icon overlays the empty space). */
    width: 100%;
}
/* Shift the placeholder text to the right of the icon, but ONLY while
   the placeholder is showing. The moment the user types, :placeholder-shown
   stops matching, text-indent goes back to 0, and the typed cursor + text
   start flush-left. */
.chat-input-wrap .chat-input:placeholder-shown {
    text-indent: 22px;
}
.chat-input-icon {
    position: absolute;
    left: 6px;
    top: 50%;
    transform: translateY(-50%);
    width: 18px;
    height: 18px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    pointer-events: none;
}
/* Hide the icon as soon as the field has content — same trigger that
   makes the native placeholder text disappear. Icon must appear AFTER
   the input in the DOM for the sibling combinator to work. */
.chat-input-wrap .chat-input:not(:placeholder-shown) ~ .chat-input-icon {
    display: none;
}

.chat-channel-label {
    font-size: 14px;
    font-family: var(--game-font);
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    text-shadow: 1px 1px 0 #000;
    flex-shrink: 0;
    padding: 0 4px;
}

.chat-channel-label:hover {
    filter: brightness(1.3);
}

.chat-input {
    flex: 1;
    height: 26px;
    background: var(--bg-cell);
    color: var(--text-light);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 0 8px;
    font-size: 14px;
    font-family: var(--game-font);
    outline: none;
}

.chat-input:focus {
    border-color: var(--text-accent);
}

.chat-input::placeholder {
    color: var(--text-disabled);
}


/* ═══════════════════════════════════════════════════════════════
   HP Bar — Below panel tab bar (bottom-right)
   ═══════════════════════════════════════════════════════════════ */

.hp-bar {
    position: absolute;
    right: 0px;
    bottom: 0px;
    width: 320px;
    height: 24px;
    background: var(--bg-darkest);
    border: 2px solid var(--border-primary);
    border-radius: 0 0 6px 6px;
    z-index: 10;
    overflow: hidden;
}

.hp-bar-fill {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    background: linear-gradient(180deg, #4caf50 0%, #2e7d32 100%);
    transition: width 0.3s ease;
}

.hp-bar-content {
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    z-index: 1;
}

.hp-bar-icon {
    width: 16px;
    height: 16px;
    image-rendering: pixelated;
    flex-shrink: 0;
}

.hp-bar-text {
    font-size: 16px;
    font-family: var(--game-font);
    font-weight: 600;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
}


/* ═══════════════════════════════════════════════════════════════
   Panel Tab Bar — Horizontal tabs above the bottom-right panels.
   Toggles Tasks, Skills, Inventory, Quests, and Bank.
   ═══════════════════════════════════════════════════════════════ */

.panel-tab-bar {
    position: absolute;
    right: 0px;
    bottom: 24px;
    width: 320px;
    display: flex;
    flex-direction: row;
    gap: 0;
    /* Above .icon-container (z:20) so the bottom-right tab tooltips
       (children of this bar) aren't occluded by the task queue's
       selected icon option that sits just above the tab bar. Bumped
       to 100 so windowed panels (capped at 99 by WindowedPanels)
       can't cover the tab tooltips when dragged near the dock. */
    z-index: 100;
}

.panel-tab-btn {
    flex: 1;
    height: 42px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-top: none;
    border-radius: 0 0 6px 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.15s ease;
    margin-right: -2px;
}

.panel-tab-btn:last-child {
    margin-right: 0;
}

.panel-tab-btn:hover {
    border-color: var(--text-accent);
    background: var(--bg-cell);
}

.panel-tab-btn {
    position: relative;
}
.panel-tab-btn.active {
    border-color: var(--text-accent);
    background: var(--bg-cell);
    box-shadow: 0 0 8px color-mix(in srgb, var(--text-accent) 40%, transparent);
    z-index: 1;
}

/* Set by PanelManager._refreshQueuePathTabState when the queue-path
   overlay is showing this tab's queue. Yellow tint matches the default
   playerPathColor so the visual link to the on-map line is obvious. */
.panel-tab-btn.queue-path-active::after {
    content: '';
    position: absolute;
    inset: -2px;
    border: 2px solid #ffd24a;
    border-radius: 0 0 6px 6px;
    box-shadow: 0 0 6px rgba(255, 210, 74, 0.7);
    pointer-events: none;
    z-index: 2;
}

.panel-tab-dot {
    position: absolute;
    top: 4px;
    left: 4px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #4caf50;
    box-shadow: 0 0 4px #4caf50;
    pointer-events: none;
    z-index: 2;
}

.panel-tab-btn img {
    width: 28px;
    height: 28px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* Hover tooltip on the bottom-right panel tab bar.
   Positioned ABOVE the trigger so it doesn't clip off the bottom edge.
   Text is "Name [Key]" populated by HOTKEYS.refreshBadges. */
.panel-tab-tooltip {
    display: none;
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 4px 10px;
    white-space: nowrap;
    pointer-events: none;
    font-size: 20px;
    font-family: var(--game-font);
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
    z-index: 100;
}
.panel-tab-btn:hover .panel-tab-tooltip {
    display: block;
}

/* The bar is anchored to right:0, so the last tab's tooltip would
   overflow the container if centered. Right-anchor it instead so it
   extends leftward and stays inside the scaled game container. */
.panel-tab-btn:last-child .panel-tab-tooltip {
    left: auto;
    right: 0;
    transform: none;
}


/* ═══════════════════════════════════════════════════════════════
   Group of Modals — Full-screen tabbed modal system (1920×1080)
   UI Rendering Layer 2. Covers map and all persistent panels.
   Matches mocks/group_of_modals_bank.html exactly.
   ═══════════════════════════════════════════════════════════════ */

.modal-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 1920px;
    height: 1080px;
    background: rgba(0,0,0,0.8);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2000;
}

.modal-container {
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    width: 1920px;
    height: 1080px;
    position: relative;
    display: flex;
    overflow: hidden;
}

/* ── Left Tab Navigation ── */
.modal-tabs {
    width: 60px;
    flex-shrink: 0;
    background: var(--bg-dark);
    border-right: 2px solid var(--border-primary);
    display: flex;
    flex-direction: column;
    /* Top padding aligns the first modal tab with the first floating
       tab so icons don't jump when opening a modal. */
    padding: 32px 1px 4px;
    gap: 1px;
    z-index: 10;
}

.tab-btn {
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-panel);
    border: none;
    border-left: 3px solid transparent;
    cursor: pointer;
    position: relative;
    transition: background 0.1s;
    font-family: var(--game-font);
}
.tab-btn:hover {
    background: var(--bg-cell);
}
.tab-btn.active {
    background: var(--bg-cell);
    border-left: 3px solid var(--text-accent);
}
.tab-btn .tab-icon {
    font-size: 28px;
    filter: grayscale(0.3);
}
.tab-btn.active .tab-icon {
    filter: none;
}

.tab-tooltip {
    display: none;
    position: absolute;
    left: calc(100% + 8px);
    top: 50%;
    transform: translateY(-50%);
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 4px 10px;
    white-space: nowrap;
    pointer-events: none;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    box-shadow: 0 2px 8px rgba(0,0,0,0.8);
    z-index: 100;
}
.tab-btn:hover .tab-tooltip { display: block; }

.tab-separator {
    height: 1px;
    margin: 4px 8px;
    background: var(--border-primary);
}

/* ── Main Content Area ── */
.modal-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* ── Header ── */
.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    background: var(--bg-dark);
    border-bottom: 2px solid var(--border-primary);
    flex-shrink: 0;
    min-height: 60px;
    position: relative;
}

.header-left {
    display: flex;
    align-items: center;
    gap: 12px;
}

.header-icon {
    width: 48px;
    height: 48px;
    background: var(--bg-cell);
    border: 2px solid var(--text-accent);
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 28px;
    flex-shrink: 0;
}

.header-info-group {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.header-name {
    font-size: 36px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
}

.header-stats {
    display: flex;
    gap: 14px;
    font-size: 22px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000;
}

/* ── Processing-group in-modal nav (Smith/Craft/Imbue/Brew/Alms) ──
   Five icon buttons centered in the modal header; shown only while a
   processing tab is active. */
.processing-nav {
    display: flex;
    align-items: center;
    gap: 8px;
    /* Centered both axes in the modal header, independent of the
       header-left / close-button flex children. */
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}
.processing-nav-btn {
    position: relative;
    width: 44px;
    height: 44px;
    background: var(--bg-cell);
    border: 2px solid var(--border-primary);
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: border-color .12s, background .12s, transform .12s;
}
.processing-nav-btn:hover {
    border-color: var(--text-accent);
    background: var(--bg-panel);
    transform: translateY(-1px);
}
.processing-nav-btn.active {
    border-color: var(--text-bright);
    background: var(--bg-panel);
    box-shadow: inset 0 0 0 1px var(--text-bright);
}
.processing-nav-icon {
    width: 30px;
    height: 30px;
    image-rendering: pixelated;
    pointer-events: none;
}
.processing-nav-tooltip {
    position: absolute;
    top: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    white-space: nowrap;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    color: var(--text-bright);
    font-size: 14px;
    padding: 3px 8px;
    border-radius: 4px;
    pointer-events: none;
    opacity: 0;
    transition: opacity .12s;
    z-index: 10;
}
.processing-nav-btn:hover .processing-nav-tooltip {
    opacity: 1;
}

/* ── Header XP bar — current-level progress, a full-width strip directly
   below the modal header. Shown for smith/craft/imbue/brew (not alms). */
.header-xp-bar {
    position: relative;
    width: 100%;
    height: 22px;
    background: var(--bg-darkest);
    border-bottom: 2px solid var(--border-primary);
    overflow: hidden;
    flex-shrink: 0;
}
.header-xp-bar-fill {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 0;
    background: #4caf50;
    opacity: 0.35;
    transition: width .3s;
}
.header-xp-bar-label {
    position: relative;
    display: block;
    width: 100%;
    text-align: center;
    line-height: 22px;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
}

/* Modal close button — square widget matching the top-right
   window-control aesthetic but slightly larger since it's the
   modal's primary action. Subtle bg + border, red on hover for
   the destructive intent. margin-right reserves space for the
   global fullscreen + exit controls sitting top-right of the
   viewport. */
.modal-close {
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--game-font);
    font-size: 30px;
    line-height: 1;
    color: rgba(255,255,255,0.7);
    background: rgba(20,16,28,0.7);
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: 4px;
    cursor: pointer;
    padding: 0 0 4px;
    margin-right: 90px;
    transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.1s;
}
.modal-close:hover {
    background: rgba(120,28,28,0.75);
    border-color: rgba(220,80,80,0.85);
    color: #ffe0e0;
}
.modal-close:active {
    transform: scale(0.94);
}

/* ── Content Body ── */
.modal-body {
    flex: 1;
    overflow: hidden;
    display: flex;
}

.tab-content {
    display: none;
    width: 100%;
    height: 100%;
    overflow-y: auto;
}
.tab-content.active {
    display: flex;
    flex-direction: column;
}
.tab-content.active.layout-row {
    flex-direction: row;
}

/* ── Placeholder for future modals ── */
.placeholder-content {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 12px;
}
.placeholder-icon { font-size: 80px; opacity: 0.3; }
.placeholder-text {
    font-size: 32px;
    color: var(--border-primary);
    text-shadow: 1px 1px 0 #000;
}


/* ═══════════════════════════════════════════════════════════════
   Bank Modal (Tab 1) — Left: Bank Grid, Right: Equipment
   ═══════════════════════════════════════════════════════════════ */

.bank-layout {
    flex: 1;
    display: flex;
    gap: 0;
    overflow: hidden;
}

/* ── Bank Side (Left) ── */
.bank-side {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-right: 2px solid var(--border-primary);
}

.bank-toolbar {
    display: flex;
    align-items: center;
    padding: 6px 10px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border-primary);
    gap: 8px;
    flex-shrink: 0;
}

.bank-search {
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 4px 8px;
    font-family: var(--game-font);
    font-size: 20px;
    color: var(--text-bright);
    width: 200px;
    outline: none;
}
.bank-search::placeholder { color: var(--border-primary); }
.bank-search:focus { border-color: var(--text-accent); }

.bank-filter-btn {
    padding: 4px 10px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
}
.bank-filter-btn:hover { background: var(--bg-cell); color: var(--text-bright); border-color: var(--text-accent); }
.bank-filter-btn.active { color: var(--text-bright); border-color: var(--text-accent); background: var(--bg-cell); }

/* Slot filter clear pill — only visible when BankModal.slotFilter is set
   (player clicked an equipment slot in the paperdoll to filter the bank).
   Yellow border + bright text to mirror the active-slot highlight. */
.bank-slot-filter-clear {
    padding: 4px 10px;
    background: var(--bg-cell);
    border: 1px solid var(--text-bright);
    border-radius: 3px;
    color: var(--text-bright);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
}
.bank-slot-filter-clear:hover { background: var(--bg-panel); }

/* Active filter highlight on the paperdoll cell that's driving the slot
   filter. --text-bright border matches the lucky-task convention so the
   "selected" state reads consistently across the UI. */
.paperdoll .inv-slot.slot-filter-active {
    border-color: var(--text-bright);
    box-shadow: 0 0 6px rgba(255, 255, 0, 0.45);
}

.bank-grid-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 6px;
}

.bank-scrap-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding-bottom: 8px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--border-primary);
}

.bank-scraps-toggle {
    display: flex;
    align-items: center;
    gap: 4px;
    font-family: var(--game-font);
    font-size: 18px;
    color: var(--text-muted);
    cursor: pointer;
    white-space: nowrap;
}
.bank-scraps-toggle input[type="checkbox"] {
    cursor: pointer;
}

.bank-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, 57px);
    gap: 8px;
    justify-content: start;
}

/* ═══════════════════════════════════════════════════════════════
   Equipment Panel (Right side of Bank Modal)
   ═══════════════════════════════════════════════════════════════ */

.equip-side {
    width: 540px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* ── Loadout Style Tabs ── */
.loadout-tabs {
    display: flex;
    background: var(--bg-dark);
    border-bottom: 1px solid var(--border-primary);
    flex-shrink: 0;
}

.loadout-tab {
    flex: 1;
    padding: 4px 2px;
    text-align: center;
    font-family: var(--game-font);
    font-size: 20px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    background: none;
    border-top: none;
    border-left: none;
    border-right: 1px solid var(--bg-panel);
    transition: all 0.1s;
}
.loadout-tab:last-child { border-right: none; }
.loadout-tab:hover { background: var(--bg-panel); color: var(--text-light); }
.loadout-tab.active {
    color: var(--text-bright);
    border-bottom: 2px solid var(--text-accent);
    background: var(--bg-panel);
}

.loadout-tab .style-icon { font-size: 18px; margin-right: 2px; }

.loadout-tab-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    vertical-align: middle;
    margin-right: 4px;
}

/* ── Shared loadout selector (family tabs + 5 slots) ──
   Used by the bank, equipment panel, mob selection, combat encounter
   dropdown and raid lobby. Base classes style every instance; each
   surface adds a `<prefix>-sel` modifier on the root for tweaks. */
.loadout-sel { display: flex; flex-direction: column; gap: 4px; flex-shrink: 0; }
.loadout-sel-families { display: flex; gap: 3px; }
.loadout-sel-family {
    flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 4px;
    padding: 4px 2px; cursor: pointer; font-family: var(--game-font); font-size: 14px;
    color: var(--text-muted); background: var(--bg-dark); border: 1px solid var(--border-primary);
    border-radius: 3px; text-shadow: 1px 1px 0 #000; transition: all 0.1s;
}
.loadout-sel-family:hover { background: var(--bg-panel); color: var(--text-light); }
.loadout-sel-family.active { color: var(--text-bright); border-color: var(--text-accent); background: var(--bg-panel); }
.loadout-sel-family-icon { width: 22px; height: 22px; image-rendering: pixelated; filter: drop-shadow(1px 1px 0 #000); }

.loadout-sel-slots { display: flex; gap: 3px; }
.loadout-sel-slot {
    flex: 1; min-width: 0; position: relative; display: flex; flex-direction: column;
    align-items: center; gap: 2px; padding: 4px 2px; cursor: pointer;
    font-family: var(--game-font); font-size: 11px; color: var(--text-muted);
    background: var(--bg-cell); border: 1px solid var(--border-primary);
    border-radius: 3px; transition: all 0.1s;
}
.loadout-sel-slot:hover { background: var(--bg-hover); color: var(--text-light); }
.loadout-sel-slot.active { color: var(--text-bright); border-color: var(--text-accent); background: var(--bg-hover); }
.loadout-sel-slot-icon { width: 28px; height: 28px; image-rendering: pixelated; filter: drop-shadow(1px 1px 0 #000); }
.loadout-sel-slot-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.loadout-sel-rename {
    width: 92%; box-sizing: border-box; font-family: var(--game-font); font-size: 11px;
    text-align: center; background: var(--bg-dark); color: var(--text-bright);
    border: 1px solid var(--text-accent); border-radius: 2px; outline: none; padding: 1px 2px;
}

/* Equipment side panel hosts the selector beside the stats toggle button. */
.equip-panel-tabs { align-items: stretch; gap: 4px; }
.equip-panel-tabs .loadout-sel { flex: 1; min-width: 0; }
.equip-panel-loadout-sel .loadout-sel-slot { font-size: 10px; }
.equip-panel-loadout-sel .loadout-sel-slot-icon { width: 24px; height: 24px; }

/* Combat encounter dropdown menu hosts the selector. */
/* Fixed width (not min-width) so the menu stays the same size whether the
   viewed family is Melee, Range or Magic — otherwise the longest loadout
   name in each family resizes the menu. Slots flex to fill and labels
   ellipsis-truncate. */
.combat-encounter .loadout-dropdown-menu .loadout-sel { padding: 6px; width: 280px; }
.combat-loadout-sel .loadout-sel-slot { background: var(--bg-dark); }

/* Raid lobby: compact, icon-only slots to fit 6 in the narrow info column. */
.raid-loadout-sel { gap: 3px; width: 100%; }
.raid-loadout-sel .loadout-sel-families { gap: 2px; }
.raid-loadout-sel .loadout-sel-family { font-size: 12px; padding: 2px 1px; gap: 2px; }
.raid-loadout-sel .loadout-sel-family-icon { width: 14px; height: 14px; }
.raid-loadout-sel .loadout-sel-slots { gap: 2px; }
.raid-loadout-sel .loadout-sel-slot { padding: 3px 1px; }
.raid-loadout-sel .loadout-sel-slot-icon { width: 18px; height: 18px; }
.raid-loadout-sel .loadout-sel-slot-label { display: none; }

/* ── Equipment Display ── */
.equip-display {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.equip-title {
    font-size: 40px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 2px;
}

/* ── Paperdoll Grid (3 columns x 5 rows) ── */
.paperdoll {
    display: grid;
    grid-template-columns: repeat(3, 146px);
    grid-template-rows: repeat(5, 114px);
    gap: 6px;
    justify-content: center;
    align-content: center;
    justify-items: center;
}

/* ── Equipment slots in paperdoll — uses .inv-slot as base ── */
.paperdoll .inv-slot {
    cursor: pointer;
    border-color: var(--bg-hover);
    width: 108px;
    height: 108px;
}

.paperdoll .inv-slot img {
    transform: scale(2);
    filter: drop-shadow(2px 2px 0 #000);
}
.paperdoll .inv-slot.empty img { opacity: 0.5; }

/* Label for empty equipment slots (e.g. "Head", "Cape") */
.inv-slot-label {
    font-size: 13px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
    text-align: center;
    width: 100%;
}
.inv-slot:not(.empty) .inv-slot-label { display: none; }

/* ── Paperdoll Grid Positions ── */
.slot-head     { grid-column: 2; grid-row: 1; }
.slot-cape     { grid-column: 1; grid-row: 2; }
.slot-neck     { grid-column: 2; grid-row: 2; }
.slot-ammo     { grid-column: 3; grid-row: 2; }
.slot-mainhand { grid-column: 1; grid-row: 3; }
.slot-body     { grid-column: 2; grid-row: 3; }
.slot-offhand  { grid-column: 3; grid-row: 3; }
.slot-hands    { grid-column: 1; grid-row: 4; }
.slot-belt     { grid-column: 2; grid-row: 4; }
.slot-special  { grid-column: 3; grid-row: 4; }
.slot-ring1    { grid-column: 1; grid-row: 5; }
.slot-legs     { grid-column: 2; grid-row: 5; }
.slot-ring2    { grid-column: 3; grid-row: 5; }


/* ═══════════════════════════════════════════════════════════════
   Combat Stats Panel (bottom of Equipment side)
   ═══════════════════════════════════════════════════════════════ */

.equip-stats-panel {
    flex-shrink: 0;
    background: var(--bg-dark);
    border-top: 2px solid var(--border-primary);
    padding: 10px 16px 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.stats-weapon-line {
    text-align: center;
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow-x: clip;
}

.stats-style-line {
    text-align: center;
    font-size: 22px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
    white-space: nowrap;
    overflow-x: clip;
}
.stats-style-line .style-val { color: var(--text-accent); }
.stats-style-line .speed-val { color: #88cc88; }

.stats-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
}

.stats-table th {
    color: var(--text-accent);
    font-weight: normal;
    padding: 2px 6px;
    text-align: center;
    border-bottom: 1px solid var(--bg-cell);
}
.stats-table th:first-child {
    text-align: left;
    width: 70px;
}

.stats-table td {
    padding: 1px 6px;
    text-align: center;
    color: var(--text-light);
}
.stats-table td:first-child {
    text-align: left;
    color: var(--text-accent);
    width: 106px;
}

.stats-table .stat-pos { color: #4caf50; }
.stats-table .stat-zero { color: var(--border-primary); }
.stats-table .stat-neg { color: #ff4444; }

.stats-table .str-cell {
    text-align: center;
    color: var(--text-light);
}
.stats-table .str-label { color: var(--text-muted); }

.stats-table .stats-icon-wrap {
    display: inline-block;
    vertical-align: middle;
    width: 20px;
    height: 20px;
    margin-right: 4px;
}
.stats-table .stats-icon-wrap img {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.stats-style-line .maxhit-val { color: #ff6644; }


/* ── Swap / Insert Mode Toggle Buttons ── */
.bank-mode-btn {
    padding: 4px 10px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-muted);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
}
.bank-mode-btn:hover { background: var(--bg-cell); color: var(--text-light); border-color: var(--text-accent); }
.bank-mode-btn.active { color: var(--text-bright); border-color: var(--text-accent); background: var(--bg-cell); }

/* ── Bank Filters button + menu ──────────────────────────────
   The button carries two targets: the small check flips filtering off
   and on, the label opens the list (right-click does too). It reads
   "Filters (3)" while three switches are off, so the bank never hides
   things without saying so. */
.bank-filter-menu-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 4px 10px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-muted);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
}
.bank-filter-menu-btn:hover { background: var(--bg-cell); color: var(--text-light); border-color: var(--text-accent); }
.bank-filter-menu-btn.filtering { color: var(--text-bright); border-color: var(--text-accent); }
.bank-filter-btn-check {
    width: 15px;
    height: 15px;
    flex: 0 0 auto;
    border: 1px solid var(--border-secondary);
    border-radius: 2px;
    background: var(--bg-darkest);
}
.bank-filter-btn-check.checked {
    background: var(--text-accent);
    border-color: var(--text-accent);
}

.bank-filter-menu {
    position: absolute;
    z-index: 2300;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    min-width: 900px;
    display: flex;
    flex-direction: column;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
    font-family: var(--game-font);
}
.bank-filter-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 14px;
    font-size: 20px;
    font-weight: 600;
    color: var(--text-accent);
    border-bottom: 1px solid var(--border-primary);
}
.bank-filter-reset {
    font-size: 16px;
    font-weight: normal;
    color: var(--text-muted);
    cursor: pointer;
}
.bank-filter-reset:hover { color: var(--text-bright); }
/* No scrollbar: three columns fit the whole list on a 1080px screen. */
.bank-filter-body { padding: 4px 0 8px; }
.bank-filter-section {
    padding: 8px 14px 4px;
    font-size: 15px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--text-dark);
}
.bank-filter-row {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 4px 14px;
    cursor: pointer;
    font-size: 18px;
    color: var(--text-light);
}
.bank-filter-row:hover { background: var(--bg-hover); }
/* Switched-off rows dim rather than disappear: the list is also how you
   find out what you are currently hiding. */
.bank-filter-row.off { color: var(--text-dark); }
.bank-filter-row.off .bank-filter-icon { opacity: 0.3; filter: grayscale(1); }
.bank-filter-icon {
    width: 26px;
    height: 26px;
    flex: 0 0 auto;
    image-rendering: pixelated;
}
.bank-filter-label { flex: 1 1 auto; white-space: nowrap; }
.bank-filter-note {
    font-size: 14px;
    color: var(--text-dark);
    text-align: right;
    white-space: nowrap;
}
.bank-filter-check {
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
    border: 1px solid var(--border-secondary);
    border-radius: 2px;
    background: var(--bg-darkest);
}
.bank-filter-check.checked { background: var(--text-accent); border-color: var(--text-accent); }
/* Three independent questions, three columns: what kind of thing, whose
   materials, which gear. */
.bank-filter-cols { display: flex; align-items: flex-start; gap: 4px; }
.bank-filter-cols > div { flex: 1 1 0; min-width: 260px; }
.bank-filter-cols > div + div { border-left: 1px solid var(--border-primary); }

/* ── Placeholder Slots (qty 0 — holds position) ── */
.bank-placeholder {
    opacity: 0.5;
}
.bank-placeholder .inv-qty {
    color: var(--text-dim);
}

/* ── Drag Ghost (follows cursor during drag) ── */
.bank-drag-ghost {
    position: absolute;
    z-index: 10000;
    pointer-events: none;
    opacity: 0.85;
    background: var(--bg-panel);
    border: 2px solid var(--text-accent);
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.6);
}
.bank-drag-ghost img {
    transform: scale(1.5);
    image-rendering: pixelated;
}

/* ── Source slot dimmed while dragging ── */
.bank-slot-dragging {
    opacity: 0.3;
    border: 2px dashed var(--text-accent);
}

/* ── Image-based tab icons ── */
.tab-icon-img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    display: block;
}

/* ── Header icon image ── */
.header-icon-img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
}

/* ── Bank Grid Scrollbar ── */
.bank-grid-scroll::-webkit-scrollbar { width: 8px; }
.bank-grid-scroll::-webkit-scrollbar-track { background: var(--bg-dark); }
.bank-grid-scroll::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }


/* ═══════════════════════════════════════════════════════════════
   XP Drops — Floating gold text, top-center of screen.
   UI Rendering Layer 4. Z-index below Group of Modals.
   Matches mocks/xp_drops.html exactly.
   ═══════════════════════════════════════════════════════════════ */

.xp-drops-container {
    position: absolute;
    top: 12%;
    /* Drops rise from the bottom edge of this box to the top, so the
       height IS the travel. Shortening it by 50px starts them that much
       higher up the screen while leaving the endpoint at 12% alone. */
    height: calc(36% - 50px);
    left: var(--playable-center-x, 50%);
    transform: translateX(-50%);
    width: 280px;
    pointer-events: none;
    /* Under the chest reveal (2200): a big haul fills the screen and XP
       numbers floating over the loot make both harder to read.
       Notifications stay above it at 3000 -- those are the things you
       must not miss. */
    z-index: 2100;
    transition: left 0.3s ease;
}

.xp-drop {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 6px;
    animation: xpFloat 2s ease-out forwards;
    white-space: nowrap;
}

.xp-drop-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.xp-drop-text {
    font-family: var(--game-font);
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

@keyframes xpFloat {
    0%   { bottom: 0;    opacity: 1; }
    70%  {                opacity: 1; }
    100% { bottom: 100%; opacity: 0; }
}


/* ═══════════════════════════════════════════════════════════════
   Loot Drops — Spinning item icons at player position.
   Z-index below Group of Modals.
   Matches mocks/loot_drops.html exactly.
   ═══════════════════════════════════════════════════════════════ */

.loot-drop-zone {
    position: absolute;
    top: 0;
    left: 0;
    width: 1920px;
    height: 1080px;
    pointer-events: none;
    z-index: 1000;
}

.loot-drop {
    position: absolute;
    pointer-events: none;
    animation: lootRise 0.5s ease-out forwards;
}

.loot-drop-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    animation: lootSpin 0.5s ease-out forwards;
}

@keyframes lootSpin {
    0%   { transform: rotate(0deg) scale(0.4); }
    40%  { transform: rotate(270deg) scale(1.65); }
    100% { transform: rotate(360deg) scale(1.5); }
}

@keyframes lootRise {
    0%   { transform: translate(-50%, 0); opacity: 1; }
    50%  { opacity: 1; }
    100% { transform: translate(-50%, -60px); opacity: 0; }
}

/* ── Plunder food consume animation (downward variant) ── */
.loot-consume {
    position: absolute;
    pointer-events: none;
    animation: lootConsume 0.5s ease-in forwards;
}

.loot-consume-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    animation: lootSpinConsume 0.5s ease-in forwards;
}

@keyframes lootSpinConsume {
    0%   { transform: rotate(0deg) scale(1.5); }
    60%  { transform: rotate(270deg) scale(1.65); }
    100% { transform: rotate(360deg) scale(0.4); }
}

@keyframes lootConsume {
    0%   { transform: translate(-50%, 0); opacity: 1; }
    50%  { opacity: 1; }
    100% { transform: translate(-50%, 60px); opacity: 0; }
}

/* ── Notification type list (two switches per row) ── */
.settings-notif-cols {
    display: flex;
    align-items: center;
    gap: 18px;
}
/* Each column is as wide as the switch it holds, so the header labels
   line up over their own switches rather than drifting with the text. */
.settings-notif-cols > .settings-switch,
.settings-notif-cols > .settings-notif-col-head {
    width: 44px;
    flex: 0 0 44px;
}
.settings-notif-col-head {
    font-family: var(--game-font);
    font-size: 13px;
    color: var(--text-muted);
    text-align: center;
}
.settings-toggle-row.settings-notif-head {
    padding-bottom: 2px;
    border-bottom: 1px solid var(--border-primary);
}

/* ── Notification panel ──
   A framed background behind every celebration, in the same family as
   the treasure chest panel. Drawn on a pseudo-element rather than the
   wrapper itself so the opacity setting dims the PANEL only -- the text
   and icons stay fully readable at every value, which is what makes 0%
   mean "no frame" instead of "no notification".

   Targets [class^="celeb-"] rather than `> *` on purpose: fireworks are
   appended to the same container (see _createFireworks) and must not
   get a frame. Every notification wrapper carries exactly one class and
   it starts with celeb-; validate-notif-panel.js enforces that. */
.celebration-container > [class^="celeb-"] {
    position: relative;
    /* The animated transform already makes a stacking context, but say
       so explicitly so the z-index below can never escape it. */
    isolation: isolate;
    padding: 20px 32px 18px;
}
.celebration-container > [class^="celeb-"]::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: 6px;
    background: linear-gradient(168deg,
        color-mix(in srgb, var(--bg-panel) 97%, transparent) 0%,
        color-mix(in srgb, var(--bg-darkest) 98%, transparent) 100%);
    border: 2px solid color-mix(in srgb, var(--text-gold) 45%, transparent);
    box-shadow: 0 0 30px rgba(0,0,0,0.6),
                inset 0 1px 0 rgba(255,215,0,0.1),
                0 0 80px rgba(255,180,0,0.06);
    opacity: var(--notif-bg-opacity, 1);
}
/* Off: no frame and no padding, so the notification sits exactly where
   it did before the panel existed. */
body.hide-notif-bg .celebration-container > [class^="celeb-"] {
    padding: 0;
}
body.hide-notif-bg .celebration-container > [class^="celeb-"]::before {
    /* content: none stops the box being generated at all, rather than
       generating one and hiding it. */
    content: none;
}

/* ── New Collection notification ── */
/* Three stacked rows: badge + headline, what turned up, then the thing
   itself. Sized off the scroll-step celebration so it sits in the same
   visual family as the rest of the queue. */
.celeb-collection {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    /* Same rise-hold-fade every other celebration uses, run just under
       the 3200ms the queue holds this type for. */
    animation: celebSlide 3s ease-out forwards;
}
.celeb-collection-badge {
    width: 44px;
    height: 44px;
    image-rendering: pixelated;
}
.celeb-collection-title {
    font-family: var(--game-font);
    font-size: 48px;
    /* The pink the Collections chat category already uses, so the
       notification and the chat line read as the same event. */
    color: #FF99CC;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 18px rgba(255,153,204,0.6);
}
.celeb-collection-sub {
    font-family: var(--game-font);
    font-size: 36px;
    /* Gold across the whole line rather than only the item name: the
       line is one text node so the i18n rule can reorder it, and a span
       around half of it would have broken that. */
    color: var(--text-gold);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}
.celeb-collection-icon {
    width: 72px;
    height: 72px;
    image-rendering: pixelated;
    filter: drop-shadow(0 0 8px rgba(255, 153, 204, 0.7));
}

/* ── Inventory loot animation (reuses lootSpin) ── */
.inv-slot.loot-received img {
    animation: lootSpin 0.5s ease-out;
}

/* ── Inventory consume animation (counter-clockwise spin out) ── */
.inv-slot.loot-consumed img {
    animation: lootSpinReverse 0.5s ease-in forwards;
}

@keyframes lootSpinReverse {
    0%   { transform: rotate(0deg) scale(1.5); opacity: 1; }
    60%  { transform: rotate(-270deg) scale(1.65); opacity: 0.6; }
    100% { transform: rotate(-360deg) scale(0.4); opacity: 0; }
}

/* ── Inventory gold spend animation (horizontal shake) ── */
.inv-slot.gold-shake img {
    animation: goldShake 0.3s ease-in-out;
}

@keyframes goldShake {
    0%   { transform: scale(1.5) translateX(0); }
    25%  { transform: scale(1.5) translateX(4px); }
    50%  { transform: scale(1.5) translateX(-4px); }
    75%  { transform: scale(1.5) translateX(4px); }
    100% { transform: scale(1.5) translateX(0); }
}


/* ═══════════════════════════════════════════════════════════════
   Notifications — Centered celebration popups.
   UI Rendering Layer 4. Z-index ABOVE Group of Modals.
   Matches mocks/notifications.html exactly.
   ═══════════════════════════════════════════════════════════════ */

.celebration-container {
    position: absolute;
    top: 0px;
    left: calc(var(--playable-center-x, 50%) - 400px);
    pointer-events: none;
    z-index: 3000;
    width: 800px;
    height: 400px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: left 0.3s ease;
}

/* ── Level Up ── */
.celeb-levelup {
    animation: celebPulse 3s ease-out forwards;
    text-align: center;
}

.celeb-title {
    font-family: var(--game-font);
    font-size: 80px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 24px rgba(255,255,0,0.5);
    margin-bottom: 14px;
    animation: titleGlow 1.5s ease-in-out infinite;
}

.celeb-skill-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
}

.celeb-icon {
    width: 56px;
    height: 56px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.celeb-level-text {
    font-family: var(--game-font);
    font-size: 56px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

/* ── Task Complete ── */
.celeb-task {
    animation: celebSlide 2.5s ease-out forwards;
    text-align: center;
}

.celeb-task-text {
    font-family: var(--game-font);
    font-size: 56px;
    color: #4caf50;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 18px rgba(76,175,80,0.5);
}

/* ── Death ── */
.celeb-death {
    animation: celebPulse 2.8s ease-out forwards;
    text-align: center;
}

.celeb-death-title {
    font-family: var(--game-font);
    font-size: 80px;
    color: #ff4444;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 24px rgba(255,50,50,0.5);
    margin-bottom: 14px;
    animation: titleGlow 1.5s ease-in-out infinite;
}

.celeb-death-sub {
    font-family: var(--game-font);
    font-size: 40px;
    color: #ff6666;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

/* ── Notification Keyframes ── */
@keyframes celebPulse {
    0%   { transform: scale(0);    opacity: 0; }
    20%  { transform: scale(1.2);  opacity: 1; }
    40%  { transform: scale(0.95); }
    60%  { transform: scale(1.05); }
    80%  { transform: scale(1);    opacity: 1; }
    100% { transform: scale(1);    opacity: 0; }
}

@keyframes celebSlide {
    0%   { transform: translateY(50px); opacity: 0; }
    20%  { transform: translateY(0);    opacity: 1; }
    80%  { transform: translateY(0);    opacity: 1; }
    100% { transform: translateY(-30px);opacity: 0; }
}

@keyframes titleGlow {
    0%, 100% {
        text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 24px rgba(255,255,0,0.5);
    }
    50% {
        text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 44px rgba(255,255,0,0.8);
    }
}

/* ── Slay Task Complete ── */
.celeb-slay-task {
    animation: celebSlide 2.3s ease-out forwards;
    text-align: center;
}

.celeb-slay-task-title {
    font-family: var(--game-font);
    font-size: 48px;
    color: #c0392b;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 18px rgba(192,57,43,0.5);
    margin-bottom: 6px;
}

.celeb-slay-task-sub {
    font-family: var(--game-font);
    font-size: 36px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

/* ── Quest Begun ── */
.celeb-quest-begun {
    animation: celebSlide 2.3s ease-out forwards;
    text-align: center;
}

.celeb-quest-begun-title {
    font-family: var(--game-font);
    font-size: 48px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 18px rgba(200,168,62,0.5);
    margin-bottom: 6px;
}

.celeb-quest-begun-sub {
    font-family: var(--game-font);
    font-size: 36px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

/* ── Quest Step Complete ── */
.celeb-quest-step {
    animation: celebSlide 2.3s ease-out forwards;
    text-align: center;
}

.celeb-quest-step-title {
    font-family: var(--game-font);
    font-size: 48px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    margin-bottom: 6px;
}

.celeb-quest-step-sub {
    font-family: var(--game-font);
    font-size: 36px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

/* ── Reroll Credit Reward Icon (quests) ── */
.reroll-reward-icon {
    font-size: 32px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    font-family: var(--game-font);
}

/* ── Scroll Drop ── */
.celeb-scroll {
    animation: celebPulse 2.3s ease-out forwards;
    text-align: center;
}

.celeb-scroll-title {
    font-family: var(--game-font);
    font-size: 72px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 24px rgba(200,168,62,0.5);
    margin-bottom: 10px;
    animation: titleGlow 1.5s ease-in-out infinite;
}

.celeb-scroll-sub {
    font-family: var(--game-font);
    font-size: 40px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

/* ── Scroll Step Complete ── */
.celeb-scroll-step {
    animation: celebSlide 1.8s ease-out forwards;
    text-align: center;
}

.celeb-scroll-step-title {
    font-family: var(--game-font);
    font-size: 48px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    margin-bottom: 6px;
}

.celeb-scroll-step-sub {
    font-family: var(--game-font);
    font-size: 36px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

/* ── Scroll Complete — Treasure Chest ── */
.celeb-scroll-complete {
    animation: celebPulse 3.2s ease-out forwards;
    text-align: center;
}

.celeb-scroll-complete-title {
    font-family: var(--game-font);
    font-size: 80px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 30px rgba(255,215,0,0.6);
    margin-bottom: 10px;
    animation: titleGlow 1.5s ease-in-out infinite;
}

.celeb-scroll-complete-sub {
    font-family: var(--game-font);
    font-size: 44px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

/* ══════════════════════════════
   XP MILESTONE (10M, 20M…)
   ══════════════════════════════ */
.celeb-milestone {
    animation: celebPulse 3s ease-out forwards;
    text-align: center;
}

.celeb-milestone-title {
    font-family: var(--game-font);
    font-size: 72px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 20px rgba(200,168,62,0.6);
    animation: titleGlowGold 1.5s ease-in-out infinite;
}

/* ══════════════════════════════
   TOTAL LEVEL MILESTONE
   ══════════════════════════════ */
.celeb-total {
    animation: celebPulse 3s ease-out forwards;
    text-align: center;
}

/* ══════════════════════════════
   SKILL CAPE / TRIMMED CAPE
   ══════════════════════════════ */
.celeb-cape {
    animation: celebPulse 3.5s ease-out forwards;
    text-align: center;
}

.celeb-cape-icon {
    width: 72px;
    height: 72px;
    image-rendering: pixelated;
    margin-bottom: 8px;
    filter: drop-shadow(1px 1px 0 #000);
}

.celeb-cape-text {
    font-family: var(--game-font);
    font-size: 52px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 18px rgba(200,168,62,0.5);
}

.celeb-cape-text-gold {
    font-family: var(--game-font);
    font-size: 52px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 24px rgba(255,255,0,0.8);
}

/* ══════════════════════════════
   PET OBTAINED
   ══════════════════════════════ */
.celeb-pet {
    animation: petBounce 4s ease-out forwards;
    text-align: center;
}

.celeb-pet-icon {
    width: 72px;
    height: 72px;
    image-rendering: pixelated;
    animation: petSpin 2s ease-in-out;
    filter: drop-shadow(1px 1px 0 #000);
}

.celeb-pet-text {
    font-family: var(--game-font);
    font-size: 52px;
    color: #9b59b6;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 18px rgba(155,89,182,0.5);
}

.celeb-pet-text-shiny {
    font-family: var(--game-font);
    font-size: 52px;
    background: linear-gradient(45deg, #ff0000,#ff7f00,#ffff00,#00ff00,#0000ff,#4b0082,#9400d3);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    animation: rainbowShift 2s linear infinite;
}

/* ══════════════════════════════
   LUCKY TOOL / SHINY LUCKY TOOL
   ══════════════════════════════ */
.celeb-lucky {
    animation: petBounce 4s ease-out forwards;
    text-align: center;
}

.celeb-lucky-icon {
    width: 72px;
    height: 72px;
    image-rendering: pixelated;
    animation: petSpin 2s ease-in-out;
    filter: drop-shadow(1px 1px 0 #000);
}

.celeb-lucky-text {
    font-family: var(--game-font);
    font-size: 52px;
    color: #f1c40f;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 18px rgba(241,196,15,0.6);
}

.celeb-lucky-text-shiny {
    font-family: var(--game-font);
    font-size: 52px;
    background: linear-gradient(45deg, #ff0000,#ff7f00,#ffff00,#00ff00,#0000ff,#4b0082,#9400d3);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    animation: rainbowShift 2s linear infinite;
}

/* Type subtitle under a lucky-tool celebration so it is never mistaken
   for a pet drop (which shares the shiny rainbow treatment). */
.celeb-lucky-tag {
    font-family: var(--game-font);
    font-size: 26px;
    color: #f1c40f;
    letter-spacing: 2px;
    text-transform: uppercase;
    text-shadow: 1px 1px 0 #000, 0 0 12px rgba(241,196,15,0.6);
    margin-top: 2px;
}

/* ══════════════════════════════
   MAX CAPE / TRIMMED MAX
   ══════════════════════════════ */
.celeb-max {
    animation: maxCeleb 5s ease-out forwards;
    text-align: center;
}

.celeb-congrats {
    font-family: var(--game-font);
    font-size: 68px;
    color: var(--text-accent);
    margin-bottom: 14px;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
}

.celeb-congrats-big {
    font-family: var(--game-font);
    font-size: 80px;
    color: var(--text-bright);
    margin-bottom: 14px;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 30px rgba(255,255,0,0.8);
    animation: titleGlow 1.5s ease-in-out infinite;
}

.celeb-max-icon {
    width: 88px;
    height: 88px;
    image-rendering: pixelated;
    margin-bottom: 8px;
    filter: drop-shadow(1px 1px 0 #000);
}

.celeb-max-text {
    font-family: var(--game-font);
    font-size: 68px;
    color: #e74c3c;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 28px rgba(231,76,60,0.8);
}

.celeb-max-text-gold {
    font-family: var(--game-font);
    font-size: 68px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 34px rgba(255,255,0,1);
}

/* ══════════════════════════════
   FIREWORKS
   ══════════════════════════════ */
.fireworks, .fireworks-small {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
}

.fw-burst {
    position: absolute;
    width: 4px; height: 4px;
    animation: fwBurst 1.5s ease-out forwards;
}

.fw-particle {
    position: absolute;
    width: 5px; height: 5px;
    background: radial-gradient(circle, var(--text-bright) 0%, var(--text-accent) 50%, transparent 100%);
    border-radius: 50%;
    animation: fwShoot 1.5s ease-out forwards;
}

.fireworks-small .fw-burst { animation-duration: 1.2s; }
.fireworks-small .fw-particle {
    width: 4px; height: 4px;
    animation: fwShootSmall 1.2s ease-out forwards;
}

.fireworks-cape .fw-particle {
    background: radial-gradient(circle, var(--text-accent) 0%, var(--text-bright) 50%, transparent 100%);
}

.fireworks-shiny .fw-particle {
    background: radial-gradient(circle, #ff0000 0%, #00ff00 25%, #0000ff 50%, var(--text-bright) 75%, transparent 100%);
    animation: fwShootRainbow 1.5s ease-out forwards;
}

.fireworks-epic .fw-burst { animation-duration: 2s; }
.fireworks-epic .fw-particle {
    width: 7px; height: 7px;
    background: radial-gradient(circle, var(--text-bright) 0%, var(--text-accent) 30%, #9400d3 60%, transparent 100%);
    animation: fwShootEpic 2s ease-out forwards;
}

/* ══════════════════════════════
   NEW KEYFRAMES (Layer 16C)
   ══════════════════════════════ */
@keyframes titleGlowGold {
    0%, 100% {
        text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 20px rgba(200,168,62,0.5);
    }
    50% {
        text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6), 0 0 40px rgba(200,168,62,0.8);
    }
}

@keyframes petBounce {
    0%   { transform: scale(0) rotate(0deg);     opacity: 0; }
    20%  { transform: scale(1.3) rotate(360deg); opacity: 1; }
    40%  { transform: scale(0.9) rotate(350deg); }
    60%  { transform: scale(1.1) rotate(370deg); }
    80%  { transform: scale(1) rotate(360deg);   opacity: 1; }
    100% { transform: scale(1) rotate(360deg);   opacity: 0; }
}

@keyframes petSpin {
    0%   { transform: rotate(0deg); }
    100% { transform: rotate(720deg); }
}

@keyframes maxCeleb {
    0%   { transform: scale(0) rotate(-180deg); opacity: 0; }
    20%  { transform: scale(1.2) rotate(20deg); opacity: 1; }
    30%  { transform: scale(0.95) rotate(-10deg); }
    40%  { transform: scale(1.05) rotate(5deg); }
    50%  { transform: scale(1) rotate(0deg); }
    90%  { transform: scale(1) rotate(0deg); opacity: 1; }
    100% { transform: scale(1) rotate(0deg); opacity: 0; }
}

@keyframes rainbowShift {
    0%   { filter: hue-rotate(0deg); }
    100% { filter: hue-rotate(360deg); }
}

@keyframes fwBurst {
    0%   { transform: scale(0); opacity: 1; }
    100% { transform: scale(1); opacity: 0; }
}

@keyframes fwShoot {
    0%   { transform: translateX(0); opacity: 1; }
    100% { transform: translateX(110px); opacity: 0; }
}

@keyframes fwShootSmall {
    0%   { transform: translateX(0); opacity: 1; }
    100% { transform: translateX(65px); opacity: 0; }
}

@keyframes fwShootRainbow {
    0%   { transform: translateX(0); opacity: 1; filter: hue-rotate(0deg); }
    100% { transform: translateX(130px); opacity: 0; filter: hue-rotate(360deg); }
}

@keyframes fwShootEpic {
    0%   { transform: translateX(0) scale(1);   opacity: 1; }
    100% { transform: translateX(160px) scale(0.5); opacity: 0; }
}

/* ═══════════════════════════════════════════════════════════════
   Treasure Chest Opening Overlay (UI Rendering Layer 3)
   Matches mocks/treasure_chest_opening.html
   Z-index above all other modals (2200)
   ═══════════════════════════════════════════════════════════════ */

.chest-overlay {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0, 0, 0, 0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2200;
    transition: opacity 0.4s ease;
}
.chest-overlay.fade-out {
    opacity: 0;
    pointer-events: none;
}

.chest-overlay .chest-panel {
    background: linear-gradient(168deg,
        color-mix(in srgb, var(--bg-panel) 97%, transparent) 0%,
        color-mix(in srgb, var(--bg-darkest) 98%, transparent) 100%);
    border: 2px solid color-mix(in srgb, var(--text-gold) 45%, transparent);
    border-radius: 6px;
    padding: 28px 36px 24px;
    width: 480px;
    text-align: center;
    position: relative;
    box-shadow: 0 0 30px rgba(0,0,0,0.6),
                inset 0 1px 0 color-mix(in srgb, var(--text-gold) 10%, transparent),
                0 0 80px color-mix(in srgb, var(--text-accent) 6%, transparent);
}

/* Expanded panel — only for big hauls (overlay gets .multi when >20 reward
   slots). Fixed large size as a flex column so the loot grid takes the
   remaining space and scrolls, keeping the header pinned and the Collect
   button on-screen. */
.chest-overlay.multi .chest-panel {
    width: 1820px;
    height: 980px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* Corner accents */
.chest-overlay .chest-panel::before,
.chest-overlay .chest-panel::after {
    content: '';
    position: absolute;
    width: 12px; height: 12px;
    border-color: color-mix(in srgb, var(--text-gold) 60%, transparent);
    border-style: solid;
}
.chest-overlay .chest-panel::before { top: 4px; left: 4px; border-width: 2px 0 0 2px; }
.chest-overlay .chest-panel::after { top: 4px; right: 4px; border-width: 2px 2px 0 0; }
.chest-overlay .corner-bl,
.chest-overlay .corner-br {
    position: absolute; width: 12px; height: 12px;
    border-color: color-mix(in srgb, var(--text-gold) 60%, transparent); border-style: solid;
}
.chest-overlay .corner-bl { bottom: 4px; left: 4px; border-width: 0 0 2px 2px; }
.chest-overlay .corner-br { bottom: 4px; right: 4px; border-width: 0 2px 2px 0; }

/* Header */
.chest-overlay .chest-title {
    font-family: var(--game-font);
    font-size: 40px;
    color: var(--text-gold);
    text-shadow: 0 0 8px color-mix(in srgb, var(--text-accent) 40%, transparent), 2px 2px 0 #000;
    letter-spacing: 3px;
    line-height: 1;
}
.chest-overlay .chest-tier {
    font-size: 32px;
    color: color-mix(in srgb, var(--text-gold) 60%, transparent);
    margin-top: 4px;
    letter-spacing: 1px;
    font-family: var(--game-font);
}
.chest-overlay .chest-xp {
    font-size: 28px;
    color: #8ef08e;
    text-shadow: 1px 1px 0 #000;
    margin-top: 6px;
    font-family: var(--game-font);
}

/* Divider */
.chest-overlay .chest-divider {
    width: 80%; height: 1px;
    margin: 14px auto 16px;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--text-gold) 35%, transparent), transparent);
}

/* Loot grid — compact by default (wraps to the panel width). In the
   expanded .multi panel it fills the remaining height and scrolls so the
   Collect button below it never falls off the bottom. */
.chest-overlay .chest-loot-grid {
    display: flex;
    gap: 6px;
    justify-content: center;
    flex-wrap: wrap;
    min-height: 56px;
    margin-bottom: 18px;
}
.chest-overlay.multi .chest-loot-grid {
    align-content: flex-start;
    flex: 1 1 auto;
    width: 100%;
    overflow-y: auto;
}

.chest-overlay .inv-slot.chest-pending {
    visibility: hidden;
}

/* Collect button */
.chest-overlay .chest-btn {
    font-family: var(--game-font);
    font-size: 30px;
    /* Never shrink/scroll away — stays pinned below the scrolling grid. */
    flex: 0 0 auto;
    padding: 8px 36px;
    color: var(--text-gold);
    background: color-mix(in srgb, var(--text-gold) 8%, transparent);
    border: 2px solid color-mix(in srgb, var(--text-gold) 50%, transparent);
    border-radius: 3px;
    cursor: pointer;
    letter-spacing: 2px;
    transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
}
.chest-overlay .chest-btn:hover {
    background: color-mix(in srgb, var(--text-gold) 18%, transparent);
    border-color: color-mix(in srgb, var(--text-gold) 80%, transparent);
    box-shadow: 0 0 12px color-mix(in srgb, var(--text-accent) 20%, transparent);
}
.chest-overlay .chest-btn:active {
    transform: scale(0.97);
}

/* ═══════════════════════════════════════════════════════════════
   Alms Modal (Tab 5)
   Matches mocks/group_of_modals_alms.html exactly.
   ═══════════════════════════════════════════════════════════════ */

.alms-layout {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0;
    padding: 40px 60px;
}

.alms-skill-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    margin-bottom: 32px;
}

.alms-skill-bubble {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    background: var(--bg-cell);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    padding: 10px 24px;
    min-width: 220px;
    justify-content: center;
}

.alms-skill-bubble img {
    width: 48px;
    height: 48px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.alms-skill-bubble .skill-level {
    font-family: var(--game-font);
    font-size: 40px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
}

.alms-skill-bubble .skill-progress {
    position: absolute;
    bottom: 3px;
    left: 8px;
    right: 8px;
    height: 4px;
    background: var(--bg-darkest);
    border-radius: 2px;
    overflow: hidden;
}

.alms-skill-bubble .skill-progress-fill {
    height: 100%;
    background: #4caf50;
    transition: width .3s;
}

.alms-xp-text {
    font-family: var(--game-font);
    font-size: 24px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
}

.alms-xp-text .xp-val {
    color: var(--text-bright);
}

.alms-divider {
    width: 500px;
    height: 1px;
    background: var(--border-primary);
    margin: 16px 0;
}

.alms-gold-display {
    font-family: var(--game-font);
    font-size: 28px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 20px;
}

.alms-gold-display .gold-val {
    color: var(--text-bright);
}

.alms-input-section {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    margin-bottom: 20px;
}

.alms-input-label {
    font-family: var(--game-font);
    font-size: 26px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
}

.alms-input-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.alms-nudge-btn {
    padding: 6px 12px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    color: var(--text-light);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
    transition: all 0.1s;
    flex-shrink: 0;
}
.alms-nudge-btn:hover {
    background: var(--bg-cell);
    color: var(--text-bright);
    border-color: var(--text-accent);
}

.alms-gold-input {
    background: var(--bg-dark);
    border: 2px solid var(--border-primary);
    border-radius: 4px;
    padding: 8px 14px;
    font-family: var(--game-font);
    font-size: 32px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    width: 260px;
    text-align: center;
    outline: none;
    flex-shrink: 1;
    min-width: 0;
}

.alms-gold-input:focus {
    border-color: var(--text-accent);
}

.alms-gold-input::placeholder {
    color: var(--border-primary);
}

.alms-presets {
    display: flex;
    gap: 8px;
}

.alms-preset-btn {
    padding: 6px 16px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    color: var(--text-light);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
    transition: all 0.1s;
}

.alms-preset-btn:hover {
    background: var(--bg-cell);
    color: var(--text-bright);
    border-color: var(--text-accent);
}

.alms-preview {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    margin: 16px 0;
    padding: 16px 32px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 6px;
    min-width: 440px;
}

.alms-preview-title {
    font-family: var(--game-font);
    font-size: 24px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
}

.alms-preview-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    font-family: var(--game-font);
    font-size: 24px;
    text-shadow: 1px 1px 0 #000;
}

.alms-preview-row .preview-label {
    color: var(--text-muted);
}

.alms-preview-row .preview-val {
    color: var(--text-light);
}

.alms-preview-row .preview-val.gold {
    color: var(--text-accent);
}

.alms-preview-row .preview-val.xp {
    color: var(--text-bright);
}

.alms-preview-row .preview-val.level-up {
    color: #4caf50;
}

.alms-preview .preview-bar-bg {
    width: 100%;
    height: 6px;
    background: var(--bg-darkest);
    border-radius: 2px;
    overflow: hidden;
    margin-top: 4px;
}

.alms-preview .preview-bar-fill {
    height: 100%;
    background: #4caf50;
    transition: width .3s;
}

.alms-confirm-btn {
    padding: 12px 48px;
    background: #3a6a3a;
    border: 2px solid #4caf50;
    border-radius: 6px;
    color: var(--text-bright);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 32px;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    transition: all 0.15s;
    margin-top: 12px;
}

.alms-confirm-btn:hover {
    background: #4a8a4a;
    border-color: #66cc66;
}

.alms-confirm-btn:active {
    background: #2a5a2a;
}

.alms-confirm-btn.disabled {
    background: var(--bg-panel);
    border-color: var(--border-primary);
    color: var(--border-primary);
    cursor: not-allowed;
}

.alms-confirm-btn.disabled:hover {
    background: var(--bg-panel);
    border-color: var(--border-primary);
}

.alms-info {
    font-family: var(--game-font);
    font-size: 20px;
    color: var(--border-primary);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
    margin-top: 16px;
    max-width: 500px;
    line-height: 1.3;
}

/* ═══════════════════════════════════════════════════════════════
   Brew Enhancement Modal (Tab 4)
   Matches mocks/group_of_modals_brew_modal.html card grid layout.
   ═══════════════════════════════════════════════════════════════ */

.brew-layout {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* ── Style Filter Tabs ── */
.brew-style-filters {
    display: flex;
    gap: 4px;
    margin-left: auto;
}

.brew-style-tab {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 14px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.1s;
}
.brew-style-tab:hover { background: var(--bg-cell); border-color: var(--border-secondary); }
.brew-style-tab.active { background: var(--bg-cell); border-color: var(--text-accent); }

.brew-style-tab-name {
    font-family: var(--game-font);
    font-size: 22px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
}
.brew-style-tab.active .brew-style-tab-name { color: var(--text-bright); }

/* ── Recipes Area ── */
.brew-recipes-area {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 8px;
}

.brew-recipes-header {
    display: flex;
    align-items: center;
    padding: 6px 10px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px 4px 0 0;
    flex-shrink: 0;
    gap: 10px;
}

/* Amount control sits at the left of the brew header. It comes after the
   style filters in the DOM, and the filters carry margin-left:auto, so
   without this the control gets pushed to the right along with them.
   order:-1 lays it out first (far left) while the filters keep their
   auto margin and stay right-aligned. */
.brew-recipes-header .proc-amount-control {
    order: -1;
}

.brew-recipes-scroll {
    flex: 1;
    overflow-y: auto;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-top: none;
    border-radius: 0 0 4px 4px;
    padding: 10px;
}

.brew-recipes-scroll::-webkit-scrollbar { width: 8px; }
.brew-recipes-scroll::-webkit-scrollbar-track { background: var(--bg-dark); }
.brew-recipes-scroll::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }

/* ── Tier Dividers ── */
.brew-tier-divider {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0 4px 0;
    margin-top: 6px;
}
.brew-tier-divider:first-child { margin-top: 0; }

.brew-tier-level {
    font-family: var(--game-font);
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    flex-shrink: 0;
}
.brew-tier-level.has { color: #4caf50; }
.brew-tier-level.needs { color: #e74c3c; }

.brew-tier-line {
    flex: 1;
    height: 1px;
    background: var(--border-primary);
}

/* ── Recipe Grid ── */
.brew-recipes-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, 344px);
    gap: 8px;
    margin-bottom: 8px;
}

/* ── Recipe Card ── */
.brew-recipe-card {
    width: 344px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    transition: border-color 0.15s;
}
.brew-recipe-card:hover { border-color: var(--border-secondary); }
.brew-recipe-card.brewable { border-color: #4caf50; }
.brew-recipe-card.brewable:hover { border-color: #6fcf70; }
/* Locked recipes stay dimmed but remain hover-accessible so tooltips
   work on every slot. The Brew button has its own pointer-events:none
   via .brew-btn.disabled so a locked card still can't be clicked. */
.brew-recipe-card.locked { opacity: 0.35; }

.brew-card-top {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Brew item slots — borderless, integrated into card */
.brew-recipe-card .inv-slot {
    background: none;
    border-color: transparent;
    flex-shrink: 0;
}

.brew-cost-slot.inv-slot {
    width: 56px; height: 56px;
}

.brew-card-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

.brew-card-name {
    font-family: var(--game-font);
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.brew-card-sub {
    font-family: var(--game-font);
    font-size: 16px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
}

/* Style colors — shared with style dots */
.style-melee      { background: #3a2020; color: #ff6b6b; border: 1px solid #8b3030; }
.style-ranged     { background: #2a3a20; color: #6bff6b; border: 1px solid #308b30; }
.style-magic      { background: #20203a; color: #6b8bff; border: 1px solid #30308b; }
.style-defensive  { background: #3a3a20; color: #ffff6b; border: 1px solid #8b8b30; }
.style-movement   { background: #203a3a; color: #6bffff; border: 1px solid #308b8b; }
.style-life       { background: #3a2e10; color: #ffc733; border: 1px solid #8b6620; }
.style-discovery  { background: #2e2040; color: #b66bff; border: 1px solid #5a308b; }

.style-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.dot-melee     { background: #ff6b6b; }
.dot-ranged    { background: #6bff6b; }
.dot-magic     { background: #6b8bff; }
.dot-defensive { background: #ffff6b; }
.dot-movement  { background: #6bffff; }
.dot-life      { background: #ffc733; }
.dot-discovery { background: #b66bff; }

/* ── Card Details ── */
.brew-card-details {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 6px 0 2px 0;
    border-top: 1px solid var(--bg-cell);
}

.brew-detail-row {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
}

.brew-detail-value { color: #ffffff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.brew-detail-xp { color: var(--text-accent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.brew-btn {
    padding: 4px 14px;
    background: #2a3a20;
    border: 2px solid #4caf50;
    border-radius: 4px;
    color: #4caf50;
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
    transition: all 0.15s;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.brew-btn:hover { background: #3a4a2a; color: #6fcf70; border-color: #6fcf70; }
/* "[icon] Brew" / "[icon] Smith": the collection-log icon shown in front of
   the action label while the output is not yet in the Creating section. */
.collect-hint-icon {
    width: 18px;
    height: 18px;
    margin-right: 5px;
    vertical-align: -3px;
    image-rendering: pixelated;
}
.brew-btn.disabled .collect-hint-icon,
.proc-craft-btn.disabled .collect-hint-icon { opacity: 0.45; }
.brew-btn.disabled { background: var(--bg-panel); border-color: var(--border-primary); color: var(--border-primary); cursor: default; pointer-events: none; }

/* ── Brew Flash Animation ── */
@keyframes brewFlash {
    0% { background: #4a6a30; }
    100% { background: var(--bg-panel); }
}
.brew-recipe-card.flash { animation: brewFlash 0.4s ease-out; }

/* ═══════════════════════════════════════════════════════════════
   Active Potions Panel — HUD (top-right, auto-sizing)
   ═══════════════════════════════════════════════════════════════ */

.active-potions-panel {
    position: absolute;
    /* Sits below the top-right window controls (12px top, 36px tall buttons)
       so it doesn't overlap the fullscreen toggle and exit buttons. */
    top: 44px;
    right: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 6px;
    /* Render BEHIND the bottom-right panels (which sit higher) so it never
       covers them; the panels must avoid creating a stacking context. */
    z-index: -1;
    pointer-events: auto;
}

.active-potions-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* The whole panel is the collapse target - clicking anywhere hides
   it, so a dedicated collapse button is no longer needed. Cursor
   pointer hints at the clickability. */
.active-potions-panel { cursor: pointer; }

/* Collapsed-state pill - takes the panel's spot when the body is
   hidden so the user can always re-expand. Includes a small potion
   icon next to the chevron so it reads as "show potions" at a glance.
   Right-click opens the filter menu so users can change visibility
   without expanding first. */
.active-potions-pill {
    position: absolute;
    top: 60px;
    right: 0;
    padding: 6px 10px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-right: none;
    border-radius: 6px 0 0 6px;
    color: var(--text-light);
    font-size: 14px;
    cursor: pointer;
    user-select: none;
    z-index: 10;
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: 6px;
}
.active-potions-pill:hover {
    background: var(--bg-hover);
    color: var(--text-bright);
    border-color: var(--text-accent);
}

.active-potions-pill-chev { display: inline-block; }
.active-potions-pill-icon {
    width: 24px;
    height: 24px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* Filter menu - one card, two columns. Header chip in each column
   uses an icon (combat / skillcustom) so the side is obvious at a
   glance. Reuses chat-category-check styling for the checkboxes. */
.potions-filter-menu {
    position: absolute;
    z-index: 2300;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    padding: 8px 0;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);
    font-family: var(--game-font);
    pointer-events: auto;
}
.potions-filter-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 12px 8px;
    border-bottom: 1px solid var(--border-primary);
    margin-bottom: 6px;
}
.potions-filter-title {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 15px;
    font-weight: 600;
    color: var(--text-accent);
}
.potions-filter-title-text { flex-shrink: 0; }
/* Combat/spirit potion on-off toggles, pushed to the right of the title. */
.potions-combat-use {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-light);
}
.potions-combat-use-label { color: var(--text-muted); }
.potions-combat-use-toggle {
    display: flex;
    align-items: center;
    gap: 5px;
    cursor: pointer;
}
.potions-combat-use-toggle:hover { color: var(--text-bright); }
.potions-filter-reset {
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    cursor: pointer;
    padding: 0;
    transition: background 0.1s, color 0.1s, border-color 0.1s;
}
.potions-filter-reset:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
    color: var(--text-bright);
}
.potions-filter-cols {
    display: grid;
    /* Four columns: two visibility filters + food eligibility + auto-eat
       sliders. Auto-eat is widest because its rows carry a slider + value
       + hint stacked vertically. */
    grid-template-columns: 1fr 1fr 1.2fr 1.5fr;
    gap: 0;
}
.potions-filter-col {
    padding: 4px 8px;
}
/* Food eligibility column - ~22 registry foods, so its rows scroll
   while the header stays put. The two visibility columns are short
   (8 rows) and don't need this. */
.potions-filter-food-list {
    max-height: 280px;
    overflow-y: auto;
}
.potions-filter-col + .potions-filter-col {
    border-left: 1px solid var(--border-primary);
}
.potions-filter-col-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 6px 8px;
    border-bottom: 1px solid var(--bg-cell);
    margin-bottom: 4px;
    color: var(--text-bright);
    font-size: 14px;
    font-weight: 600;
}
.potions-filter-col-icon {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.potions-filter-col-subnote {
    color: var(--text-muted);
    font-size: 12px;
    font-weight: normal;
}
.potions-filter-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 8px;
    cursor: pointer;
    font-size: 13px;
    color: var(--text-light);
    border-radius: 3px;
    transition: background 0.1s;
}
.potions-filter-row:hover { background: var(--bg-hover); }
/* Fixed-width slot so every label lines up at the same x even when an
   icon fails to load or the highest-tier representative changes size. */
.potions-filter-row-icon {
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.potions-filter-row-icon img {
    max-width: 24px;
    max-height: 24px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.potions-filter-row-label { flex: 1; }
/* Effective heal shown on each food row in the Food Active column. */
.potions-filter-food-heal {
    display: flex;
    align-items: center;
    gap: 3px;
    color: #5cbf60;
    font-weight: 600;
    flex-shrink: 0;
}
.potions-filter-food-heal .potion-row-stat-icon {
    width: 14px;
    height: 14px;
    image-rendering: pixelated;
}
.potions-filter-check {
    width: 16px;
    height: 16px;
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    background: var(--bg-darkest);
    flex-shrink: 0;
    position: relative;
}
.potions-filter-check.checked {
    background: var(--text-accent);
    border-color: var(--text-accent);
}
.potions-filter-check.checked::after {
    content: '\2713';
    position: absolute;
    top: -1px;
    left: 2px;
    font-size: 12px;
    color: var(--bg-dark);
    font-weight: bold;
}

/* Auto-eat column: three threshold sliders stacked vertically. Each row
   carries label, slider+value, and a hint line. */
.potions-filter-autoeat-body {
    padding: 4px 4px 8px;
}
.potions-filter-autoeat-row {
    padding: 6px 4px;
    border-radius: 3px;
}
.potions-filter-autoeat-row + .potions-filter-autoeat-row {
    border-top: 1px solid var(--bg-cell);
    margin-top: 2px;
}
.potions-filter-autoeat-label {
    color: var(--text-bright);
    font-size: 12px;
    font-weight: 600;
    margin-bottom: 4px;
}
.potions-filter-autoeat-sliderrow {
    display: flex;
    align-items: center;
    gap: 8px;
}
.potions-filter-autoeat-slider {
    flex: 1;
    height: 14px;
    cursor: pointer;
    accent-color: var(--text-accent);
}
.potions-filter-autoeat-value {
    min-width: 56px;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--text-light);
    font-size: 12px;
    font-weight: 600;
}
.potions-filter-autoeat-hint {
    margin-top: 3px;
    color: var(--text-muted, #9aa);
    font-size: 11px;
    line-height: 1.3;
}

.potion-row {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 280px;
    height: 62px;
    padding: 4px 10px;
    background: var(--bg-cell);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    cursor: default;
    position: relative;
    box-sizing: border-box;
}

.potion-row-icon-wrap {
    position: relative;
    display: inline-block;
    flex-shrink: 0;
    width: 32px;
    height: 32px;
}
.potion-row-icon {
    transform: scale(1.5);
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.potion-row-stat {
    display: flex;
    align-items: center;
    gap: 3px;
    flex-shrink: 0;
}
.potion-row-stat-val {
    font-family: var(--game-font);
    font-size: 18px;
    color: #4caf50;
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
}
.potion-row-stat-icon {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.potion-row[data-style="food"] .potion-row-stat-val {
    color: #e07b6c;
}
.potion-row-stat-name {
    font-family: var(--game-font);
    font-size: 16px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

.potion-row-count {
    display: flex;
    align-items: baseline;
    gap: 4px;
    margin-left: auto;
    flex-shrink: 0;
}
.potion-row-count-num {
    font-family: var(--game-font);
    font-size: 18px;
    color: var(--text-bright);
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
}
.potion-row-count-unit {
    font-family: var(--game-font);
    font-size: 13px;
    color: var(--text-bright);
    opacity: 0.75;
    text-shadow: 1px 1px 0 #000;
}

.potion-tt-grid {
    display: grid;
    grid-template-columns: auto auto auto auto auto;
    column-gap: 14px;
    row-gap: 4px;
    align-items: center;
}

.potion-tt-line {
    display: contents;
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
}

.potion-tt-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.potion-tt-tier {
    font-family: var(--game-font);
    font-size: 20px;
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
}
.potion-tt-name {
    font-family: var(--game-font);
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}
.potion-tt-stat {
    display: inline-flex;
    align-items: center;
    gap: 3px;
}
.potion-tt-stat-val {
    font-family: var(--game-font);
    font-size: 20px;
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
    color: #4caf50;
}
.potion-row[data-style="food"] .potion-tt-stat-val {
    color: #e07b6c;
}
.potion-tt-stat-icon {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.potion-tt-count {
    font-family: var(--game-font);
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}

/* Whole-stash summary line at the top of the multi-food tooltip. Spans
   the full grid width as a flex row (label left, +total HP and total
   remaining at the right) with a divider separating it from the per-food
   list below. */
.potion-tt-line.potion-tt-total {
    display: flex;
    align-items: center;
    gap: 14px;
    grid-column: 1 / -1;
    padding-bottom: 7px;
    margin-bottom: 3px;
    border-bottom: 1px solid var(--border-secondary);
}
.potion-tt-total-label {
    flex: 1;
    font-family: var(--game-font);
    font-size: 22px;
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}

/* ═══════════════════════════════════════════════════════════════
   Skill Customize - tab content for the GroupOfModals 'skillcustom' tab.
   Renders inside .tab-content; the GoM modal-header is hidden for this
   tab so this wrapper provides its own header + close button.
   Scoped under .skill-custom-tab to avoid GroupOfModals conflicts.
   ═══════════════════════════════════════════════════════════════ */

.skill-custom-tab {
    width: 100%;
    height: 100%;
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Skill-custom overlay reuses the .modal-close aesthetic but at a
   smaller size and positioned absolutely in the corner. No
   margin-right override needed — this overlay sits inside the GoM
   and doesn't approach the global window-controls. */
.skill-custom-tab .modal-close {
    position: absolute;
    top: 8px;
    right: 10px;
    width: 36px;
    height: 36px;
    font-size: 24px;
    margin-right: 0;
    z-index: 10;
}
.skill-custom-tab .modal-close:hover { color: var(--text-bright); }

/* ── Top nav bar (individual view only) ──
   Horizontal strip of 28 skill icons above the modal header, plus a
   leading "back to total" icon. Clicking a rollable skill (or slay)
   routes to that skill's individual page. Non-rollable skills are
   dimmed and inert, matching the total-page row behaviour. */
.skill-custom-tab .skill-custom-navbar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1px;
    padding: 6px 80px 6px 10px;
    background: var(--bg-dark);
    border-bottom: 1px solid var(--border-primary);
    flex-shrink: 0;
    flex-wrap: nowrap;
    overflow-x: auto;
    position: relative;
    z-index: 6;
}
.skill-custom-tab .skill-custom-nav-icon {
    position: relative;
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 4px;
    transition: all 0.15s;
}
.skill-custom-tab .skill-custom-nav-icon img {
    transform: scale(1.5);
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.skill-custom-tab .skill-custom-nav-icon.clickable { cursor: pointer; }
.skill-custom-tab .skill-custom-nav-icon.clickable:hover {
    background: var(--bg-cell);
    border-color: var(--text-accent);
    transform: scale(1.08);
}
.skill-custom-tab .skill-custom-nav-icon.active {
    background: var(--bg-cell);
    border-color: var(--text-bright);
    box-shadow: 0 0 8px rgba(200,168,62,0.4);
}
.skill-custom-tab .skill-custom-nav-icon.non-rollable {
    opacity: 0.4;
    cursor: default;
}
/* Credit badges sit at top-left of each cell on the individual-view
   nav bar AND the total-view skill-header row. Setting toggle hides
   them site-wide. Non-rollable cells never carry a badge in the
   first place since they have no credit pool. */
.skill-custom-tab .skill-custom-nav-icon .inv-qty,
.skill-custom-tab .grid-skill-header .inv-qty {
    top: 0;
    left: 2px;
    font-size: 18px;
}
body.hide-skillcustom-credits .skill-custom-tab .skill-custom-nav-icon .inv-qty,
body.hide-skillcustom-credits .skill-custom-tab .grid-skill-header .inv-qty {
    display: none;
}

/* ── Header ── */
.skill-custom-tab .modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 80px 10px 10px;
    background: var(--bg-dark);
    border-bottom: 2px solid var(--border-primary);
    flex-shrink: 0;
    position: relative;
    z-index: 5;
}

/* Header reset button — sits to the right of .header-right.
   Total view: resets all skill weight levers. Individual view:
   resets all activity + node levers for the current skill. Tooltip
   on .tooltip child explains. */
.skill-custom-tab .header-reset-btn {
    position: relative;
    width: 40px; height: 40px;
    margin-left: 12px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 50%;
    color: var(--text-light);
    font-size: 26px;
    line-height: 1;
    cursor: pointer;
    user-select: none;
    flex-shrink: 0;
    transition: border-color 0.1s ease, color 0.1s ease, transform 0.1s ease;
}
.skill-custom-tab .header-reset-btn:hover {
    border-color: var(--text-accent);
    color: var(--text-accent);
    transform: rotate(-30deg);
}

.skill-custom-tab .header-left {
    display: flex;
    align-items: center;
    gap: 12px;
}

.skill-custom-tab .header-mid-left {
    display: flex;
    align-items: center;
    gap: 8px;
}

.skill-custom-tab .header-mid-right {
    display: flex;
    align-items: center;
    gap: 6px;
}

.skill-custom-tab .header-icon {
    width: 56px; height: 56px;
    background: var(--bg-cell);
    border: 2px solid var(--text-accent);
    border-radius: 4px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.skill-custom-tab .header-icon img {
    width: 44px; height: 44px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.skill-custom-tab .header-info { display: flex; flex-direction: column; gap: 2px; }

.skill-custom-tab .header-name {
    font-size: 36px; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1; white-space: nowrap;
}

.skill-custom-tab .header-stats {
    display: flex; gap: 14px;
    font-size: 22px; color: #ffffff;
    text-shadow: 1px 1px 0 #000;
}

.skill-custom-tab .header-right {
    display: flex; flex-direction: column;
    align-items: flex-end; gap: 2px;
    margin-right: 30px;
}

.skill-custom-tab .cred-display {
    font-size: 26px; color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
}
.skill-custom-tab .cred-amount { color: var(--text-bright); }

.skill-custom-tab .tasks-completed-text {
    font-size: 22px; color: #ffffff;
    text-shadow: 1px 1px 0 #000;
}

/* ── Skill Weight Lever (header-mid-left) ── */
.skill-custom-tab .skill-weight-label {
    font-size: 22px; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}

.skill-custom-tab .lever-control { display: flex; align-items: center; gap: 4px; }

.skill-custom-tab .lever-btn {
    width: 28px; height: 28px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light); cursor: pointer;
    font-family: var(--game-font);
    font-size: 22px; line-height: 1;
    text-shadow: 1px 1px 0 #000;
}
.skill-custom-tab .lever-btn:hover { background: var(--bg-hover); color: var(--text-bright); border-color: var(--text-accent); }

.skill-custom-tab .lever-track { display: flex; gap: 2px; align-items: center; }

.skill-custom-tab .lever-pip {
    width: 14px; height: 14px;
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 2px;
    transition: all 0.15s;
}
.skill-custom-tab .lever-pip.active-pos { background: #4caf50; border-color: #6fcf70; box-shadow: 0 0 4px rgba(76,175,80,0.5); }
.skill-custom-tab .lever-pip.active-neg { background: #e74c3c; border-color: #f06050; box-shadow: 0 0 4px rgba(231,76,60,0.5); }
.skill-custom-tab .lever-pip.center { border-color: var(--text-accent); width: 16px; height: 16px; }

.skill-custom-tab .lever-value {
    font-size: 22px; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    width: 30px; text-align: center;
}
.skill-custom-tab .lever-value.positive { color: #4caf50; }
.skill-custom-tab .lever-value.negative { color: #e74c3c; }

.skill-custom-tab .lever-mult {
    font-size: 22px; color: #ffffff;
    text-shadow: 1px 1px 0 #000;
    margin-left: 4px; width: 62px; text-align: center;
}

/* ── Main Content Layout ── */
.skill-custom-tab .main-layout {
    display: flex; flex: 1;
    overflow: hidden;
    padding: 8px; gap: 8px;
}

/* ── History Sidebar ── */
.skill-custom-tab .history-sidebar {
    width: 140px; flex-shrink: 0;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    display: flex; flex-direction: column;
    overflow: hidden;
}

.skill-custom-tab .history-title {
    font-size: 24px; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    padding: 6px 8px; text-align: center;
    border-bottom: 1px solid var(--border-primary);
    background: var(--bg-cell); flex-shrink: 0;
}

.skill-custom-tab .history-stats {
    font-size: 20px; color: #ffffff;
    text-shadow: 1px 1px 0 #000;
    padding: 4px 8px; text-align: center;
    border-bottom: 1px solid var(--bg-panel); flex-shrink: 0;
}

.skill-custom-tab .history-scroll { flex: 1; overflow-y: auto; padding: 4px; }

.skill-custom-tab .history-row {
    display: flex; align-items: center; gap: 4px;
    padding: 3px 4px;
    font-size: 14px; color: var(--text-dim);
    text-shadow: 1px 1px 0 #000;
    border-bottom: 1px solid var(--bg-panel);
}
.skill-custom-tab .history-row:hover { background: var(--bg-cell); }

.skill-custom-tab .history-num { color: var(--text-muted); width: 28px; text-align: right; flex-shrink: 0; font-size: 14px; }
.skill-custom-tab .history-time { color: var(--text-dark); flex-shrink: 0; font-size: 13px; margin-left: auto; }

.skill-custom-tab .history-skill-icon {
    width: 16px; height: 16px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    flex-shrink: 0;
}

.history-tt-line {
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}
.history-tt-time { color: var(--text-dark); margin-left: 4px; }

/* ── Columns Container ── */
.skill-custom-tab .columns-container { flex: 1; display: flex; gap: 8px; overflow: hidden; }

.skill-custom-tab .column {
    flex: 1;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    display: flex; flex-direction: column;
    overflow: hidden;
}

.skill-custom-tab .column-header {
    display: flex; align-items: center;
    padding: 6px 8px;
    background: var(--bg-cell);
    border-bottom: 1px solid var(--border-primary);
    flex-shrink: 0;
}

.skill-custom-tab .column-title {
    font-size: 24px; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000; flex: 1;
}

.skill-custom-tab .column-subtitle {
    font-size: 22px; color: #ffffff;
    text-shadow: 1px 1px 0 #000;
}

/* ── Sub-headers ── */
.skill-custom-tab .activities-subheader,
.skill-custom-tab .nodes-subheader {
    display: flex; align-items: center;
    padding: 3px 6px;
    border-bottom: 1px solid var(--bg-panel);
    flex-shrink: 0;
    font-size: 20px; color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
}
.skill-custom-tab .sh-info-section {
    flex: 1; display: flex; align-items: center;
    gap: 6px; min-width: 0; overflow: hidden;
}
.skill-custom-tab .sh-ctrl-section {
    display: flex; align-items: center;
    gap: 2px; flex-shrink: 0;
}
.skill-custom-tab .sh-ctrl-label { margin-left: 10px; width: 78px; text-align: center; flex-shrink: 0; }
.skill-custom-tab .sh-lv { width: 40px; flex-shrink: 0; }
.skill-custom-tab .sh-name { flex: 1; }
.skill-custom-tab .sh-chance { width: 60px; text-align: left; flex-shrink: 0; margin-right: -8px; }
.skill-custom-tab .sh-qty { width: 70px; text-align: left; flex-shrink: 0; margin-right: 4px; }
.skill-custom-tab .sh-location { flex: 1; }
.skill-custom-tab .sh-bank { width: 120px; text-align: left; flex-shrink: 0; padding-left: 10px; }
.skill-custom-tab .sh-dist { width: 70px; text-align: right; flex-shrink: 0; margin-right: 10px; }
.skill-custom-tab .sh-nchance { width: 44px; text-align: center; flex-shrink: 0; margin-right: 8px; }
.skill-custom-tab .sh-sortable { cursor: pointer; user-select: none; }
.skill-custom-tab .sh-sortable:hover { color: var(--text-accent); }

.skill-custom-tab .column-scroll { flex: 1; overflow-y: auto; padding: 2px; }

/* ── Activity Row ── */
.skill-custom-tab .activity-row {
    display: flex; align-items: center;
    padding: 4px 6px;
    border-bottom: 1px solid var(--bg-panel);
    min-height: 38px;
    transition: background 0.1s;
    cursor: pointer;
}
.skill-custom-tab .activity-row:hover { background: var(--bg-cell); }
.skill-custom-tab .activity-row.locked { opacity: 0.4; }
.skill-custom-tab .activity-row.locked:hover { background: var(--bg-cell); }
.skill-custom-tab .activity-row.hl-green { background: #2a3a20; outline: 2px solid #4caf50; outline-offset: -4px; }
.skill-custom-tab .activity-row.hl-red { background: #3a2020; outline: 2px solid #e74c3c; outline-offset: -4px; }
.skill-custom-tab .activity-row.hidden { display: none; }

.skill-custom-tab .activity-info {
    flex: 1; display: flex; align-items: center;
    gap: 6px; min-width: 0; overflow: hidden;
}

.skill-custom-tab .activity-level { font-size: 20px; text-shadow: 1px 1px 0 #000; width: 40px; flex-shrink: 0; }
.skill-custom-tab .activity-level.has { color: #4caf50; }
.skill-custom-tab .activity-level.needs { color: #e74c3c; }

.skill-custom-tab .activity-item-icon {
    width: 22px; height: 22px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    flex-shrink: 0;
}

.skill-custom-tab .slay-mob-sprite {
    width: 64px; height: 64px;
    image-rendering: pixelated;
    image-rendering: crisp-edges;
    flex-shrink: 0;
}

.skill-custom-tab .activity-name { font-size: 22px; color: #ffffff; text-shadow: 1px 1px 0 #000; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.skill-custom-tab .activity-chance { font-size: 22px; color: var(--text-accent); text-shadow: 1px 1px 0 #000; width: 60px; text-align: right; flex-shrink: 0; }
.skill-custom-tab .activity-qty-range { font-size: 22px; color: #ffffff; text-shadow: 1px 1px 0 #000; width: 95px; text-align: center; flex-shrink: 0; }
.skill-custom-tab .lock-icon { font-size: 16px; color: #e74c3c; margin-right: 4px; }

/* Same requirement badges as the mob cards, laid out along the row instead
   of stacked in a sprite corner. */
.skill-custom-tab .req-inline { display: flex; gap: 4px; flex-shrink: 0; margin-right: 8px; }
.skill-custom-tab .req-inline .req-badge { height: 24px; }
.skill-custom-tab .req-inline .req-badge img { width: 20px; height: 20px; }
.skill-custom-tab .req-inline .req-badge b { font-size: 14px; }

/* ── Lever Controls in rows ── */
.skill-custom-tab .row-controls { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.skill-custom-tab .control-group { display: flex; align-items: center; gap: 2px; margin-left: 8px; }
.skill-custom-tab .control-emoji { font-size: 18px; margin-right: 2px; }

.skill-custom-tab .ctrl-btn {
    width: 28px; height: 28px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 2px;
    color: var(--text-light); cursor: pointer;
    font-family: var(--game-font);
    font-size: 22px; line-height: 1;
    text-shadow: 1px 1px 0 #000;
    position: relative; white-space: nowrap;
}
.skill-custom-tab .ctrl-btn:hover { background: var(--bg-hover); color: var(--text-bright); border-color: var(--text-accent); }
.skill-custom-tab .ctrl-btn.disabled { opacity: 0.3; cursor: default; pointer-events: none; }
.skill-custom-tab .ctrl-btn.has-value { font-size: 22px; }
.skill-custom-tab .ctrl-btn.val-pos { color: #4caf50; border-color: #4caf50; }
.skill-custom-tab .ctrl-btn.val-neg { color: #e74c3c; border-color: #e74c3c; }

/* ── Global Tooltip (positioned on overlay, escapes overflow containers) ── */
/* Skill-custom credit-button tooltip. Mounted on document.body (NOT
   inside .skill-custom-tab) so its z-index can beat the tutorial
   overlay's highlight ring. SkillCustomModal applies a scale transform
   matching the overlay so it visually aligns with the rest of the UI. */
.ctrl-global-tooltip {
    position: fixed;
    z-index: 99999;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 4px 8px;
    white-space: nowrap;
    pointer-events: none;
    font-size: 20px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    box-shadow: 0 2px 8px rgba(0,0,0,0.8);
    line-height: 1.4;
}
.ctrl-global-tooltip .tt-action { color: var(--text-bright); }
.ctrl-global-tooltip .tt-effect { color: #ffffff; }
.ctrl-global-tooltip .tt-cost { color: var(--text-accent); }

/* ── Node Row ── */
.skill-custom-tab .node-row {
    display: flex; align-items: center;
    padding: 4px 6px;
    border-bottom: 1px solid var(--bg-panel);
    min-height: 38px;
    transition: background 0.1s;
    cursor: pointer;
}
.skill-custom-tab .node-row:hover { background: var(--bg-cell); }
.skill-custom-tab .node-row.hl-green { background: #2a3a20; outline: 2px solid #4caf50; outline-offset: -2px; }
.skill-custom-tab .node-row.hl-red { background: #3a2020; outline: 2px solid #e74c3c; outline-offset: -2px; }
.skill-custom-tab .node-row.hidden { display: none; }

.skill-custom-tab .node-info {
    flex: 1; display: flex; align-items: center;
    gap: 6px; min-width: 0; overflow: hidden;
}
.skill-custom-tab .node-name { font-size: 22px; color: #ffffff; text-shadow: 1px 1px 0 #000; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; }
/* Name + diary free-weight badge share the flexible name column so the
   badge hugs the name text (name truncates first, badge never shrinks). */
.skill-custom-tab .node-name-wrap { flex: 1; display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; }
.skill-custom-tab .node-name-wrap .node-name { flex: 0 1 auto; min-width: 0; }
.skill-custom-tab .node-diary-free { flex: 0 0 auto; display: inline-flex; align-items: center; position: relative; cursor: help; }
.skill-custom-tab .node-diary-free img { width: 22px; height: 22px; display: block; image-rendering: pixelated; }
.skill-custom-tab .node-bank { font-size: 22px; color: var(--text-muted); text-shadow: 1px 1px 0 #000; white-space: nowrap; width: 120px; flex-shrink: 0; overflow: clip; }
.skill-custom-tab .node-dist { font-size: 22px; color: var(--text-muted); text-shadow: 1px 1px 0 #000; width: 70px; text-align: right; flex-shrink: 0; }
.skill-custom-tab .node-chance { font-size: 22px; color: var(--text-accent); text-shadow: 1px 1px 0 #000; width: 44px; text-align: right; flex-shrink: 0; }

/* ── Scrollbar ── */
.skill-custom-tab .column-scroll::-webkit-scrollbar,
.skill-custom-tab .history-scroll::-webkit-scrollbar { width: 8px; }
.skill-custom-tab .column-scroll::-webkit-scrollbar-track,
.skill-custom-tab .history-scroll::-webkit-scrollbar-track { background: var(--bg-dark); }
.skill-custom-tab .column-scroll::-webkit-scrollbar-thumb,
.skill-custom-tab .history-scroll::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }

/* ── Unlocks Row (header-mid-right in Individual view) ── */
.skill-custom-tab .unlocks-row {
    display: none;
}

/* ── Unlock items (shared) ── */
.skill-custom-tab .unlock-item {
    position: relative;
    width: 56px; height: 56px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    cursor: default;
}
.skill-custom-tab .unlock-item img {
    transform: scale(1.5);
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.skill-custom-tab .unlock-item.locked { opacity: 0.3; }
.skill-custom-tab .unlock-item.unlocked { border-color: var(--text-accent); }
.skill-custom-tab .unlock-item.selected { border-color: var(--text-bright); cursor: pointer; }
.skill-custom-tab .unlock-item.unlocked.pet-selectable { cursor: pointer; }

/* Lucky / Shiny Lucky tool cells: gold and hot-pink borders so the
   one-time XP-roll drops read distinctly from the T1-T5 row. Border
   is part of the static class list, kept in sync via the `.locked`
   opacity (so a locked lucky cell still hints at the colour). The
   "unlocked" rules win on specificity for owned cells. */
.skill-custom-tab .unlock-item.lucky-cell {
    border: 2px solid #ffd24a;
    box-shadow: 0 0 4px rgba(255, 210, 74, 0.5);
}
.skill-custom-tab .unlock-item.shiny-lucky-cell {
    border: 2px solid #ff6ad5;
    box-shadow: 0 0 4px rgba(255, 106, 213, 0.55);
}
.skill-custom-tab .unlock-item.lucky-cell.unlocked {
    border-color: #ffd24a;
    box-shadow: 0 0 6px rgba(255, 210, 74, 0.85);
}
.skill-custom-tab .unlock-item.shiny-lucky-cell.unlocked {
    border-color: #ff6ad5;
    box-shadow: 0 0 6px rgba(255, 106, 213, 0.9);
}
/* Collections view mirrors of the same treatment. The
   `.collections-slot` wrapper sits OUTSIDE the inner `.inv-slot`, so
   target both so any styling that lands on either edge picks up the
   colour. */
.collections-slot.lucky-cell .inv-slot {
    border: 2px solid #ffd24a;
    box-shadow: 0 0 4px rgba(255, 210, 74, 0.55);
}
.collections-slot.shiny-lucky-cell .inv-slot {
    border: 2px solid #ff6ad5;
    box-shadow: 0 0 4px rgba(255, 106, 213, 0.6);
}
.collections-slot.lucky-cell.unlocked .inv-slot {
    box-shadow: 0 0 7px rgba(255, 210, 74, 0.9);
}
.collections-slot.shiny-lucky-cell.unlocked .inv-slot {
    box-shadow: 0 0 7px rgba(255, 106, 213, 0.95);
}

.skill-custom-tab .unlock-tooltip {
    display: none;
    pointer-events: none;
}

.global-tooltip.unlock-style {
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}
/* Bonus descriptions from ItemBonusDescriptions are '\n'-joined and
   copied into the global tooltip as a single <div>. The tooltip base
   `white-space: nowrap` (inherited) would collapse those newlines into
   one line; pre-line makes each effect its own row — matching the
   per-line-div perk tooltips (Collector, Combat Modifiers, etc.). Only
   scopes the unlock-style global tooltip so other tooltips are untouched. */
.global-tooltip.unlock-style div {
    white-space: pre-line;
}

/* ══════════════════════════════════════════════════════════════
   TOTAL VIEW — Section A (Unlocks Grid) & Section B (Skill Columns)
   ══════════════════════════════════════════════════════════════ */

.skill-custom-tab .total-content {
    flex: 1; display: flex; flex-direction: column;
    gap: 8px; overflow: hidden;
}

/* Section A: Unlocks Grid */
.skill-custom-tab .unlocks-grid-section {
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    flex-shrink: 0;
}

.skill-custom-tab .unlocks-grid-header {
    display: flex; align-items: center;
    padding: 4px 8px;
    background: var(--bg-cell);
    border-bottom: 1px solid var(--border-primary);
}

.skill-custom-tab .unlocks-grid-title {
    font-size: 30px; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

.skill-custom-tab .unlocks-grid {
    display: grid;
    grid-template-columns: repeat(31, 52px);
    gap: 2px; padding: 6px;
    justify-content: center;
}

.skill-custom-tab .grid-skill-header {
    width: 56px; height: 56px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    position: relative;
}
.skill-custom-tab .grid-skill-header.clickable { cursor: pointer; }
.skill-custom-tab .grid-skill-header.clickable:hover { border-color: var(--text-accent); background: var(--bg-cell); }
.skill-custom-tab .unlock-item.clickable { cursor: pointer; }
.skill-custom-tab .unlock-item.clickable:hover { border-color: var(--text-accent); }
.skill-custom-tab .skill-weight-row.clickable { cursor: pointer; }

.skill-custom-tab .grid-skill-header img {
    transform: scale(1.5);
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* Section B: Skill Weighting Columns */
.skill-custom-tab .skill-columns-section {
    flex: 1;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    display: flex; flex-direction: column;
    overflow: hidden;
}

.skill-custom-tab .skill-columns-header {
    display: flex; align-items: center;
    padding: 4px 8px;
    background: var(--bg-cell);
    border-bottom: 1px solid var(--border-primary);
    flex-shrink: 0;
}

.skill-custom-tab .skill-columns-title {
    font-size: 30px; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000; flex: 1;
}

.skill-custom-tab .skill-columns-subtitle {
    font-size: 20px; color: #ffffff;
    text-shadow: 1px 1px 0 #000;
}

.skill-custom-tab .skill-columns-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    gap: 6px; flex: 1;
    overflow: hidden; padding: 6px;
}

.skill-custom-tab .skill-col {
    display: flex; flex-direction: column;
    /* overflow: visible so col 1's Task Automaters row can extend
       its pair-groups horizontally past the column's right edge
       into the area visually occupied by cols 2 + 3. */
    overflow: visible;
    border: 1px solid var(--bg-panel);
    border-radius: 3px;
}

.skill-custom-tab .skill-col-header {
    display: flex; align-items: center;
    padding: 3px 6px;
    border-bottom: 1px solid var(--bg-panel);
    font-size: 18px; color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    background: var(--bg-panel);
    flex-shrink: 0;
}

.skill-custom-tab .sch-lv { width: 68px; flex-shrink: 0; }
.skill-custom-tab .sch-skill { flex: 1; }
.skill-custom-tab .sch-pct { width: 40px; text-align: center; flex-shrink: 0; margin-right: 4px; }
.skill-custom-tab .sch-weight { width: 100px; text-align: center; flex-shrink: 0; }

.skill-custom-tab .skill-col-body { flex: 1; overflow: visible; }

.skill-custom-tab .skill-weight-row {
    display: flex; align-items: center;
    padding: 3px 6px;
    border-bottom: 1px solid var(--bg-panel);
    min-height: 34px;
}
.skill-custom-tab .skill-weight-row:hover { background: var(--bg-cell); }
.skill-custom-tab .skill-weight-row.non-rollable { opacity: 0.7; }

.skill-custom-tab .swr-level {
    font-size: 30px; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    width: 76px; flex-shrink: 0;
}

.skill-custom-tab .swr-skill {
    flex: 1; display: flex; align-items: center; gap: 4px;
    min-width: 0; overflow: hidden;
}

.skill-custom-tab .swr-skill-icon {
    width: 36px; height: 36px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    flex-shrink: 0;
}

.skill-custom-tab .swr-skill-name {
    font-size: 30px; color: #ffffff;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.skill-custom-tab .swr-pct {
    font-size: 28px; color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    width: 40px; text-align: right; flex-shrink: 0; margin-right: 12px;
}

/* Relic toggle icons: shared shape for the Task Automater cells
   and the UnlocksModal perk row icons. Three opacity states. */
.swr-relic-toggle {
    position: relative;
    width: 36px; height: 36px;
    flex-shrink: 0;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    border-radius: 4px;
    transition: transform 0.1s ease;
}
.swr-relic-toggle img {
    width: 32px; height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    transition: opacity 0.15s ease;
}
.swr-relic-toggle.relic-on img { opacity: 1; }
.swr-relic-toggle.relic-off img { opacity: 0.5; }
.swr-relic-toggle.relic-locked img { opacity: 0.3; }
.swr-relic-toggle.relic-locked { cursor: default; }
.swr-relic-toggle:not(.relic-locked):hover { transform: scale(1.1); }
.swr-relic-toggle.relic-on {
    background: rgba(255, 215, 0, 0.15);
    box-shadow: 0 0 0 1px rgba(255, 215, 0, 0.4);
}

/* Task Automaters row in SkillCustomModal — lives inside col 1's
   body as a normal .skill-weight-row.non-rollable. The standard
   label area renders to col 1's width; the pair-group cells trail
   off rightward past col 1's right edge thanks to skill-col +
   skill-col-body being overflow: visible. The row itself stays the
   same height + width as the surrounding rows (life, spirit, etc).
   Compact pair-group cells used here so the cells fit within the
   standard row height. */
.skill-custom-tab .swr-automater-row {
    /* Hold the row's flex container to 400px so the in-column
       layout (icon + name) reads tidily; the pair-groups inside
       .swr-automater-cells overflow rightward past this 400px and
       past col 1's edge thanks to overflow: visible on the col. */
    max-width: 400px;
    overflow: visible;
}
/* Skip the empty pct + weight placeholders in this row so the
   label/icon and the trailing cells aren't competing with hidden
   slot widths. swr-level stays so the row aligns with the others
   in the column. */
.skill-custom-tab .swr-automater-row .swr-pct,
.skill-custom-tab .swr-automater-row .swr-weight {
    display: none;
}
/* Lock the swr-skill area so the icon + "Task Automaters" name
   stay visible even when the trailing cells exist. flex: none
   gives it natural width; overflow: visible undoes the default
   overflow: hidden on .swr-skill which can hide the label when
   the row is constrained. */
.skill-custom-tab .swr-automater-row .swr-skill {
    flex: none;
    overflow: visible;
}
.skill-custom-tab .swr-automater-cells {
    display: flex;
    flex-shrink: 0;
    flex-wrap: nowrap;
    align-items: center;
    gap: 12px;
    margin-left: 40px;
    white-space: nowrap;
}

/* Reset-to-defaults button in the Task Automaters row's swr-level
   slot. Themed circle with a clockwise arrow glyph, hover-lifts
   to the accent color. Tooltip handled via the standard .tooltip
   child the TooltipManager picks up. */
.skill-custom-tab .swr-automater-reset {
    position: relative;
    width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 50%;
    color: var(--text-light);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    user-select: none;
    transition: border-color 0.1s ease, color 0.1s ease, transform 0.1s ease;
}
.skill-custom-tab .swr-automater-reset:hover {
    border-color: var(--text-accent);
    color: var(--text-accent);
    transform: rotate(-30deg);
}

/* Compact pair-group sizing for the SkillCustomModal context. The
   UnlocksModal version keeps its larger 56x56 cells; this one
   shrinks to ~32x32 so the row height matches other skill rows. */
.skill-custom-tab .automater-pair-group {
    padding: 2px 4px;
    gap: 0;
}
.skill-custom-tab .automater-pair-group .automater-pair-label {
    font-size: 12px;
    line-height: 1;
}
.skill-custom-tab .automater-pair-group .automater-pair-row {
    gap: 0;
}
.skill-custom-tab .automater-pair-group .unlock-item.perk-icon-cell,
.skill-custom-tab .automater-pair-group .automater-icon-cell {
    width: 30px;
    height: 30px;
    border-width: 1px;
}
.skill-custom-tab .automater-pair-group .unlock-item img {
    transform: scale(0.85);
}
.skill-custom-tab .automater-pair-group .automater-pair-link {
    width: 6px;
    height: 2px;
}
.skill-custom-tab .swr-automater-cell {
    position: relative;
    display: flex; flex-direction: column; align-items: center;
    padding: 4px 6px;
    background: var(--bg-cell, #2a2a2a);
    border: 2px solid var(--border-secondary, #555);
    border-radius: 6px;
    cursor: grab;
    user-select: none;
    transition: border-color 0.1s ease, opacity 0.1s ease;
    touch-action: none;
}
.skill-custom-tab .swr-automater-cell:hover { border-color: var(--text-accent, #ffd24a); }
.skill-custom-tab .swr-automater-cell:active { cursor: grabbing; }
.skill-custom-tab .swr-automater-cell.swr-automater-dragging { opacity: 0.4; }
.skill-custom-tab .swr-automater-cell.swr-automater-drop-before {
    box-shadow: inset 4px 0 0 0 var(--text-bright, #fff);
}
.skill-custom-tab .swr-automater-cell.swr-automater-drop-after {
    box-shadow: inset -4px 0 0 0 var(--text-bright, #fff);
}
.skill-custom-tab .swr-automater-icons {
    display: flex;
    gap: 2px;
    margin-bottom: 2px;
}
.skill-custom-tab .swr-automater-label {
    font-size: 14px; color: var(--text-light, #ddd);
    text-align: center;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}

/* (Telescope cells are not shown in SkillCustomModal — see
   UnlocksModal Telescopes perk row instead.) */

/* Task Automaters row's reset-to-default-priority button. Sits at
   the end of the perk-row-label. Circular themed button with the
   same ↻ glyph used by the SkillCustomModal header reset and the
   inline reset in col 1's Task Automaters row. */
.automater-reset-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px; height: 28px;
    margin-left: 10px;
    vertical-align: middle;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 50%;
    color: var(--text-light);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    user-select: none;
    transition: border-color 0.1s ease, color 0.1s ease, transform 0.1s ease;
}
.automater-reset-btn:hover {
    border-color: var(--text-accent);
    color: var(--text-accent);
    transform: rotate(-30deg);
}

/* Task Automaters: each variant (Novice / Adept / Expert) is a real
   .unlock-item.perk-icon-cell (same 56x56 shape as Compass T1 / T2
   cells). All three sit side-by-side joined by visible connector
   lines so the trio reads as one linked unit. A small label sits
   above naming the kind ("Luck", "Quests", "Highest Tier", etc).
   The group wrapper has no border of its own — it just captures
   pointerdown anywhere on the group (cells + connectors + label)
   for the drag-reorder. */
.automater-pair-group {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    cursor: grab;
    user-select: none;
    touch-action: none;
    /* Subtle theme-variable border by default; switches to the
       accent color when all 3 variants of the kind are owned —
       matches how .unlock-item.unlocked highlights ownership. */
    padding: 4px 6px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
}
.automater-pair-group.all-unlocked {
    border-color: var(--text-accent);
}
/* Toggle-off state — kind is disabled (player turned the group off).
   Dim the border so the visual matches the off-cells inside. Placed
   AFTER .all-unlocked so a fully-owned-but-disabled group still
   reads as "off" rather than "completed". */
.automater-pair-group.kind-disabled {
    border-color: var(--text-dim);
    background: var(--bg-darker, var(--bg-dark));
}
.automater-pair-group:active { cursor: grabbing; }
.automater-pair-group.automater-pair-dragging { opacity: 0.4; }
.automater-pair-group.automater-pair-drop-before {
    box-shadow: -4px 0 0 0 var(--text-bright, #fff);
}
.automater-pair-group.automater-pair-drop-after {
    box-shadow: 4px 0 0 0 var(--text-bright, #fff);
}

/* Small label above the cell row. ~14px so it doesn't compete. */
.automater-pair-label {
    font-size: 14px;
    color: var(--text-dim, #999);
    text-align: center;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    line-height: 1.1;
}

/* Horizontal row that holds [novice] [link] [adept] [link] [expert]. */
.automater-pair-row {
    display: flex;
    align-items: center;
    gap: 0;
}

/* The chain links between the cells. 3px tall, ~10px wide, light
   color with a 1px outline so they read against any background. */
.automater-pair-link {
    width: 10px; height: 3px;
    background: var(--text-light, #ddd);
    box-shadow: 0 0 0 1px #000;
    flex-shrink: 0;
}

/* Inner cells reuse the perk-icon-cell shape so they size identically
   to a Compass slot. We don't need extra rules — just a small
   distinguishing class hook for hover-pairing if needed later. */
.automater-icon-cell { /* visual identical to .unlock-item.perk-icon-cell */ }

.skill-custom-tab .swr-weight {
    width: 100px;
    display: flex; align-items: center; justify-content: center;
    gap: 2px; flex-shrink: 0;
}

.skill-custom-tab .swr-weight .ctrl-btn {
    width: 36px; height: 36px;
    font-size: 24px;
}

/* Skill description tooltip line (skill-weight-row hover). Allows wrapping
   so longer descriptions fit; parent .tooltip width follows this max-width. */
.tooltip .swr-tt-desc {
    white-space: normal;
    max-width: 360px;
    margin-top: 2px;
}

/* Paired-skill icons appended to the description for gathering/processing pairs. */
.swr-tt-pair-icon {
    width: 22px;
    height: 22px;
    vertical-align: middle;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* ═══════════════════════════════════════════════════════════════
   Processing Modal — Tab 3: Smith / Craft / Imbue
   Equipment crafting from processed materials.
   ═══════════════════════════════════════════════════════════════ */

/* ── Layout wrapper ── */
.proc-layout {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* ── Main Layout ── */
.proc-main-layout {
    display: flex;
    flex: 1;
    overflow: hidden;
    padding: 8px;
    gap: 8px;
}

/* ── Tier Sidebar ── */
.proc-tier-sidebar {
    width: 300px;
    flex-shrink: 0;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.proc-tier-sidebar-title {
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    padding: 6px 8px;
    text-align: center;
    border-bottom: 1px solid var(--border-primary);
    background: var(--bg-cell);
    flex-shrink: 0;
}

.proc-tier-sidebar-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 4px;
}

.proc-tier-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px 6px 2px;
    border-bottom: 1px solid var(--bg-panel);
    cursor: pointer;
    border-radius: 3px;
    transition: background 0.1s;
}
.proc-tier-row:hover { background: var(--bg-cell); }
.proc-tier-row.active { background: var(--bg-cell); outline: 2px solid var(--text-accent); outline-offset: -2px; }
.proc-tier-row.locked { opacity: 0.35; }

.proc-tier-badge {
    font-size: 18px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    width: 32px;
    text-align: center;
    flex-shrink: 0;
}

/* Tier sidebar material icon — inv-slot sized for sidebar */
.proc-tier-mat-icon.inv-slot {
    width: 36px; height: 36px;
    background: none;
    border-color: transparent;
    flex-shrink: 0;
}

.proc-tier-info { display: flex; flex-direction: column; flex: 1; min-width: 0; }

.proc-tier-mat-name {
    font-size: 20px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.proc-tier-level {
    white-space: pre-line;
    font-size: 16px;
    text-shadow: 1px 1px 0 #000;
}
.proc-tier-level.has { color: #4caf50; }
.proc-tier-level.needs { color: #e74c3c; }

.proc-tier-bank-qty {
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    flex-shrink: 0;
    text-align: right;
    min-width: 40px;
}

.proc-lock-icon { font-size: 14px; color: #e74c3c; }

/* ── Recipes Area ── */
.proc-recipes-area {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.proc-recipes-header {
    display: flex;
    align-items: center;
    padding: 6px 10px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px 4px 0 0;
    flex-shrink: 0;
    gap: 10px;
}

.proc-recipes-material-display {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    height: 56px;
}
/* Material inv-slot in recipes header */
.proc-mat-slot.inv-slot {
    width: 56px; height: 56px;
    flex-shrink: 0;
}
.proc-recipes-material-display .proc-mat-label {
    font-size: 22px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000;
}
.proc-recipes-material-display .proc-mat-bank {
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

/* ── Craft Amount Control ── */
.proc-amount-control {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    height: 56px;
}
.proc-amount-label {
    font-size: 22px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}
.proc-amount-input {
    width: 3ch;
    max-width: 500px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-bright);
    font-family: var(--game-font);
    font-size: 22px;
    text-align: center;
    padding: 2px 8px;
    text-shadow: 1px 1px 0 #000;
    outline: none;
}
.proc-amount-input:focus { border-color: var(--text-accent); }
.proc-amount-input::-webkit-inner-spin-button { -webkit-appearance: none; }
.proc-amount-input[type=number] { -moz-appearance: textfield; }

.proc-amount-max-btn {
    padding: 2px 10px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 22px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
    transition: all 0.15s;
}
.proc-amount-max-btn:hover { border-color: var(--text-accent); color: var(--text-bright); }
.proc-amount-max-btn.active { background: rgba(200, 168, 62, 0.2); border-color: var(--text-accent); color: var(--text-accent); }

.proc-amount-reset-btn {
    padding: 2px 10px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 22px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
    transition: all 0.15s;
}
.proc-amount-reset-btn:hover { border-color: var(--text-accent); color: var(--text-bright); }

.proc-recipes-grid-scroll {
    flex: 1;
    overflow-y: auto;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-top: none;
    border-radius: 0 0 4px 4px;
    padding: 10px;
}

.proc-recipes-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 8px;
}

/* ── Recipe Card ── */
.proc-recipe-card {
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    transition: border-color 0.15s;
    height: 232px;
    width: 242px;
}
.proc-recipe-card { position: relative; }
/* [i] requirements button + popup */
.proc-recipe-info-btn {
    position: absolute; top: 4px; right: 6px;
    width: 22px; height: 22px; line-height: 20px;
    border: 1px solid var(--border-primary); border-radius: 50%;
    background: var(--bg-dark); color: var(--text-accent);
    font-size: 16px; font-weight: bold; text-align: center;
    cursor: pointer; z-index: 3;
}
.proc-recipe-info-btn:hover { border-color: var(--text-accent); color: var(--text-bright); }
/* Mounted on #ui-container (container coordinate space) so it floats
   over the modal's scroll areas; the item slots inside are the bank's
   1.5x slots and carry the normal hover tooltip. */
.proc-recipe-info-pop {
    position: absolute; z-index: 9000;
    min-width: 520px; max-width: 720px;
    background: var(--bg-dark); border: 1px solid var(--border-primary); border-radius: 4px;
    padding: 10px 14px; box-shadow: 0 2px 8px rgba(0,0,0,0.8);
    font-size: 22px; text-align: left; white-space: normal;
    text-shadow: 1px 1px 0 #000;
}
.proc-recipe-info-title { color: var(--text-bright); font-size: 26px; margin-bottom: 6px; }
.proc-recipe-info-line { color: var(--text-light); font-size: 22px; line-height: 1.3; }
.proc-recipe-info-line.ok { color: #6fcf70; }
.proc-recipe-info-line.missing { color: #e74c3c; }
.proc-recipe-info-head { color: var(--text-accent); margin-top: 8px; margin-bottom: 4px; }
.proc-recipe-info-row { display: flex; align-items: center; gap: 12px; padding: 3px 0; white-space: nowrap; }
.proc-recipe-info-row .inv-slot { flex: 0 0 auto; }
.proc-recipe-info-name { flex: 1; color: var(--text-light); font-size: 22px; }
.proc-recipe-info-qty { font-size: 22px; }
.proc-recipe-info-row.ok .proc-recipe-info-qty { color: #6fcf70; }
.proc-recipe-info-row.missing .proc-recipe-info-qty { color: #e74c3c; }
/* God-tier cape requirement slot (required, never consumed) */
.proc-cape-req img { width: 32px; height: 32px; image-rendering: pixelated; }
.proc-cape-req.proc-cape-req-missing img { filter: grayscale(1) brightness(0.6); }
.proc-recipe-card:hover { border-color: var(--border-secondary); }
.proc-recipe-card.craftable { border-color: #4caf50; }
.proc-recipe-card.craftable:hover { border-color: #6fcf70; }

.proc-recipe-card-top {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Processing recipe item slots — borderless, integrated into card */
.proc-recipe-card .inv-slot {
    background: none;
    border-color: transparent;
    flex-shrink: 0;
}

.proc-recipe-item-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

.proc-recipe-item-name {
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.proc-recipe-slot-label {
    font-size: 16px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
}

.proc-recipe-details {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 6px 0 2px 0;
    border-top: 1px solid var(--bg-cell);
}

.proc-recipe-detail-row {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
}

/* Cost inv-slot in recipe card detail row */
.proc-cost-slot.inv-slot {
    width: 56px; height: 56px;
}

.proc-gem-cost-slot.inv-slot {
    margin-left: -50px;
}
.proc-gem-cost-slot-tight.inv-slot {
    margin-left: -51px;
}
/* Stacked recipe components after the "+" read as plain icons: no tier
   label (the quantity badge is simply not created for them). */
.proc-stack-plain-tier { display: none; }
.proc-cost-plus {
    color: #aaa;
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
    align-self: center;
}
.proc-detail-value { color: #ffffff; overflow-x: hidden; }
.proc-detail-xp { color: var(--text-accent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.proc-craft-btn {
    padding: 4px 14px;
    background: #2a3a20;
    border: 2px solid #4caf50;
    border-radius: 4px;
    color: #4caf50;
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
    transition: all 0.15s;
    white-space: nowrap;
    overflow-x: clip;
}
.proc-craft-btn:hover { background: #3a4a2a; color: #6fcf70; border-color: #6fcf70; }
.proc-craft-btn.disabled { background: var(--bg-panel); border-color: var(--border-primary); color: var(--border-primary); cursor: default; pointer-events: none; }

/* ── Scrollbar ── */
.proc-tier-sidebar-scroll::-webkit-scrollbar,
.proc-recipes-grid-scroll::-webkit-scrollbar { width: 8px; }
.proc-tier-sidebar-scroll::-webkit-scrollbar-track,
.proc-recipes-grid-scroll::-webkit-scrollbar-track { background: var(--bg-dark); }
.proc-tier-sidebar-scroll::-webkit-scrollbar-thumb,
.proc-recipes-grid-scroll::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }

/* ── Craft Flash ── */
@keyframes procCraftFlash {
    0% { background: #4a6a30; }
    100% { background: var(--bg-panel); }
}
.proc-recipe-card.flash { animation: procCraftFlash 0.4s ease-out; }

/* ══════════════════════════════════════════════════════════════════
   MOB SELECTION MODAL (Tab 2 — Layer 13B)
   ══════════════════════════════════════════════════════════════════ */

.mob-layout {
    flex: 1;
    display: flex;
    gap: 0;
    overflow: hidden;
}

/* ── Mob List (Left Side) ── */
.mob-list-side {
    width: 390px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-right: 2px solid var(--border-primary);
}

.mob-list-toolbar {
    display: flex;
    align-items: center;
    padding: 6px 10px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border-primary);
    gap: 8px;
    flex-shrink: 0;
}

.mob-search {
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 4px 8px;
    font-family: var(--game-font);
    font-size: 20px;
    color: var(--text-bright);
    width: 180px;
    outline: none;
}
.mob-search::placeholder { color: var(--border-primary); }
.mob-search:focus { border-color: var(--text-accent); }

.mob-filter-btn {
    padding: 4px 10px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
}
.mob-filter-btn:hover { background: var(--bg-cell); color: var(--text-bright); border-color: var(--text-accent); }
.mob-filter-btn.active { color: var(--text-bright); border-color: var(--text-accent); background: var(--bg-cell); }

/* ── Mob List Sub-header ── */
.mob-list-subheader {
    display: flex;
    align-items: center;
    padding: 3px 8px;
    border-bottom: 1px solid var(--border-primary);
    flex-shrink: 0;
    font-size: 18px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    background: var(--bg-panel);
}
.mlsh-icon { width: 64px; flex-shrink: 0; text-align: center; }
.mlsh-name { flex: 1; padding-left: 4px; }

/* ── Mob List Scroll ── */
.mob-list-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 2px;
}

/* ── Mob Row ── */
.mob-row {
    /* relative so .mob-row-map-icon can anchor to the full row's
       top-right corner via position: absolute. */
    position: relative;
    display: flex;
    align-items: center;
    padding: 4px 8px;
    border-bottom: 1px solid var(--bg-panel);
    min-height: 72px;
    cursor: pointer;
    transition: background 0.1s;
}

/* Map indicator in the top-right of every .mob-row. Same visual
   recipe as .mob-slay-task-icon but anchored to the full row. */
.mob-row-map-icon {
    position: absolute;
    top: 4px;
    right: 4px;
    z-index: 2;
    /* Clickable: closes the modal + pans the world map to the mob's
       node. stopPropagation on the JS handler keeps the row's
       _selectMob click intact. */
    pointer-events: auto;
    cursor: pointer;
    filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.8));
}
.mob-row-map-icon img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.mob-row:hover { background: var(--bg-cell); }
.mob-row.selected { background: #2a3a20; outline: 2px solid #4caf50; outline-offset: -2px; }
.mob-row.locked { opacity: 0.4; }
.mob-row.locked:hover { background: #3a2020; }

.mob-row-icon {
    width: 128px;
    height: 128px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
}
.mob-row.selected .mob-row-icon { border-color: #4caf50; }
.mob-row-icon img, .mob-row-icon canvas {
    width: 128px;
    height: 128px;
    image-rendering: pixelated;
    image-rendering: crisp-edges;
    filter: drop-shadow(1px 1px 0 #000);
}

.mob-row-name {
    flex: 1;
    padding-left: 8px;
    overflow: hidden;
    min-width: 0;
}

.mob-row-name-text {
    font-size: 24px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Three-line mob row: tier prefix (colored), rest of name, slay/level. */
.mob-row-tier {
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.15;
    font-weight: 600;
}
.mob-row-tier.tier-feeble  { color: #4caf50; }
.mob-row-tier.tier-dire    { color: #4fc3f7; }
.mob-row-tier.tier-savage  { color: #ff9800; }
.mob-row-tier.tier-fell    { color: #f44336; }
.mob-row-tier.tier-ancient { color: #9c27b0; }
.mob-row-tier.tier-chaos {
    background: linear-gradient(90deg, #ff4444, #ff8800, #ffdd00, #44ff44, #4488ff, #8844ff);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    text-shadow: none;
    filter: drop-shadow(1px 1px 0 #000);
}
.mob-row-subname {
    font-size: 22px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.15;
}

.mob-row-level {
    font-size: 20px;
    color: var(--text-dim);
    text-shadow: 1px 1px 0 #000;
    margin-top: 2px;
}

.lock-icon { font-size: 16px; color: #e74c3c; margin-right: 2px; }

/* ── Detail Side (Right) ── */
.mob-detail-side {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.mob-detail-top {
    flex: 1;
    display: flex;
    overflow: hidden;
}

/* ── Mob Info Panel ── */
.mob-info-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 12px 16px;
    gap: 10px;
}

/* ── Encounter Header ── */
.mob-encounter-name {
    font-size: 36px;
    font-weight: 700;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
    margin-bottom: 4px;
}

.mob-encounter-level {
    font-size: 20px;
    color: var(--text-dim);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 8px;
}

/* ── Mob Unit Row (clickable portraits) ── */
.mob-unit-row {
    display: flex;
    gap: 10px;
    margin-bottom: 8px;
    height: 180px;
}
.mob-unit-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    cursor: pointer;
    padding: 4px;
    border-radius: 6px;
    border: 2px solid var(--border-primary);
    transition: border-color 0.15s;
    width: 128px;
    height: 128px;
}
.mob-unit-item:hover {
    border-color: var(--text-accent);
}
.mob-unit-item.active {
    border-color: var(--text-bright);
    background: rgba(58, 50, 38, 0.5);
}
.mob-unit-item canvas {
    width: 128px;
    height: 128px;
    image-rendering: pixelated;
    image-rendering: crisp-edges;
    filter: drop-shadow(2px 2px 0 #000);
}
.mob-unit-name {
    font-size: 16px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-top: 2px;
    text-align: center;
}
.mob-unit-level {
    font-size: 13px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
}

.mob-info-meta {
    display: flex;
    gap: 14px;
    font-size: 22px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
}
.mob-info-meta .val-red { color: #ff4444; }
.mob-info-meta .val-gold { color: var(--text-accent); }
.mob-info-meta .val-green { color: #88cc88; }
.mob-info-meta .val-blue { color: #66aaff; }

/* ── Mob Combat Stats Table ── */
.mob-stats-section {
    flex: 1;
    overflow-y: auto;
}

.mob-stats-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
}

.mob-stats-table th {
    color: var(--text-accent);
    font-weight: normal;
    padding: 3px 8px;
    text-align: center;
    border-bottom: 1px solid var(--bg-cell);
    background: var(--bg-panel);
}
.mob-stats-table th:first-child { text-align: left; width: 80px; }

.mob-stats-table td {
    padding: 2px 8px;
    text-align: center;
    color: var(--text-light);
    border-bottom: 1px solid var(--bg-panel);
}
.mob-stats-table td:first-child { text-align: left; color: var(--text-muted); }

.mob-stats-table .stat-pos { color: #4caf50; }
.mob-stats-table .stat-zero { color: var(--border-primary); }

.stat-section-label {
    font-size: 22px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-top: 8px;
    margin-bottom: 2px;
    padding-bottom: 2px;
    border-bottom: 1px solid var(--bg-cell);
}

/* ── Mob Detail: Panel Header + Derived Grid + Two-Column Layout ── */
.mob-panel-header { text-align: center; margin-bottom: 6px; }
.mob-panel-name { font-size: 28px; font-weight: 700; color: var(--text-bright); text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6); }
.mob-panel-level { font-size: 22px; color: #ffffff; text-shadow: 1px 1px 0 #000; }

.mob-derived-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    gap: 6px;
    margin-bottom: 10px;
}
.mob-derived-item {
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 6px 5px;
    text-align: center;
}
.mob-derived-label {
    font-size: 16px;
    color: var(--text-bright);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 2px;
}
.mob-derived-value {
    font-size: 22px;
    font-weight: 700;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000;
}

.mob-two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 56px;
    margin-bottom: 10px;
}

.mob-section-header {
    font-size: 20px;
    font-weight: 700;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    margin: 0 0 6px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--bg-cell);
}

/* Skill grid (left column) */
.mob-skill-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2px 10px;
}
.mob-skill-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 5px;
    border-radius: 3px;
}
.mob-skill-icon {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.mob-skill-name {
    font-size: 20px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    flex: 1;
}
.mob-skill-val {
    font-size: 20px;
    font-weight: 600;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    min-width: 28px;
    text-align: right;
}

/* Equipment bonuses (right column) — table layout, visually matched to Combat Skills */
.mob-col-right {
    min-width: 0;
}
.mob-equip-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
}
/* Header row: match .mob-section-header style
   padding-bottom 10px + first td padding-top 4px = 14px gap,
   matching section-header's 4px pad + 1px border + 6px margin + 3px row pad */
.mob-equip-table th {
    font-size: 20px;
    font-weight: 700;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    padding: 0 5px 10px;
    border-bottom: 1px solid var(--bg-cell);
    text-align: center;
}
.mob-equip-table th:first-child {
    text-align: left;
    width: 100px;
}
/* Data rows: match .mob-skill-row spacing
   4px top + 4px bottom = 8px between rows, matching grid gap 2px + 3px pad each side */
.mob-equip-table td {
    padding: 4px 5px;
    text-align: center;
    font-size: 20px;
    font-weight: 600;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
}
/* Label cell: match .mob-skill-name */
.mob-equip-table td:first-child {
    text-align: left;
    font-weight: normal;
    color: var(--text-accent);
    width: 120px;
}
.mob-equip-table .stat-pos { color: #4caf50; }
.mob-equip-table .stat-zero { color: var(--border-primary); }
.mob-equip-table .stat-neg { color: #ff4444; }
/* Strength cell: label left, value right */
.mob-equip-table .str-cell {
    text-align: left;
    font-weight: normal;
    color: var(--text-light);
}
.mob-equip-table .str-label { color: var(--text-accent); }
.mob-equip-table .str-val {
    float: right;
    font-weight: 600;
}
/* Icon inside label cell: 32×32 matching .mob-skill-icon */
.mob-equip-table .mob-equip-icon-wrap {
    position: relative;
    display: inline-block;
    vertical-align: middle;
    width: 32px;
    height: 32px;
    margin-right: 6px;
}
.mob-equip-table .mob-equip-icon-wrap img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* ── Loot Table Preview ── */
.loot-section {
    border-top: 1px solid var(--border-primary);
    padding-top: 8px;
}

.loot-label {
    font-size: 20px;
    font-weight: 700;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    margin: 0 0 6px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--bg-cell);
}

.loot-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
}
.loot-table th {
    font-size: 20px;
    font-weight: 700;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    padding: 0 5px 8px;
    border-bottom: 1px solid var(--bg-cell);
    text-align: left;
}
.loot-table th:nth-child(3),
.loot-table th:nth-child(4) {
    text-align: center;
}
.loot-table td {
    padding: 3px 5px;
    font-size: 20px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    vertical-align: middle;
}
.loot-table td:nth-child(3),
.loot-table td:nth-child(4) {
    text-align: center;
    font-weight: 600;
}
/* Item icon cell */
.loot-table .loot-item-cell {
    width: 56px;
    padding: 2px;
}
.loot-table .loot-item-cell .inv-slot {
    width: 48px;
    height: 48px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
}
.loot-table .loot-item-cell .inv-slot img {
    transform: none;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.loot-table .loot-item-cell .inv-qty {
    font-size: 18px;
}
/* Name cell */
.loot-table .loot-name-cell {
    font-weight: normal;
    color: var(--text-accent);
}
/* Drop rate coloring */
.loot-table .loot-rate-cell {
    color: var(--text-light);
}

/* Loot-table banner rows. Two flavours:
     .loot-slay-banner   → above rare drops; rares are slayer-task only.
     .loot-common-banner → above normal drops; always available, 2x on slay.
   Both use the same layout: 32x32 icon + 20px caption, theme-variable backed.
   .on-slay-task lifts the common banner color to the accent green to flag
   the active 2x bonus. */
.loot-table tr.loot-banner td,
.guide-loot-table tr.loot-banner td {
    padding: 8px 10px;
    background: var(--bg-cell);
    border-top: 1px solid var(--border-primary);
    border-bottom: 1px solid var(--border-primary);
    font-weight: 600;
    font-size: 20px;
    letter-spacing: 0.3px;
    vertical-align: middle;
}
.loot-table tr.loot-slay-banner td,
.guide-loot-table tr.loot-slay-banner td {
    color: var(--text-accent);
}
.loot-table tr.loot-common-banner td,
.guide-loot-table tr.loot-common-banner td {
    color: var(--text-light);
}
.loot-table tr.loot-common-banner.on-slay-task td,
.guide-loot-table tr.loot-common-banner.on-slay-task td {
    color: var(--text-accent);
}
.loot-table tr.loot-banner .loot-banner-icon,
.guide-loot-table tr.loot-banner .loot-banner-icon {
    width: 32px;
    height: 32px;
    vertical-align: middle;
    image-rendering: pixelated;
    margin-right: 10px;
}
.loot-table tr.loot-banner .loot-banner-text,
.guide-loot-table tr.loot-banner .loot-banner-text {
    vertical-align: middle;
}

/* Rare-drop slot states, driven by ClientState.collections + slayTask:
   .rare-obtained        → green ✓ overlay; item shown dimmed.
   .rare-locked-offtask  → red ✕ + slay icon overlay; item shown dimmed. */
.rare-slot {
    position: relative;
}
.rare-slot.rare-obtained img,
.rare-slot.rare-locked-offtask img {
    opacity: 0.5;
}
.rare-slot.rare-obtained {
    border-color: var(--text-accent) !important;
}
.rare-slot.rare-locked-offtask {
    border-color: #884444 !important;
}
.rare-mark {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 3;
    font-weight: 900;
    text-shadow: 0 0 3px #000, 1px 1px 0 #000;
}
.rare-mark-check {
    inset: auto;
    top: 1px;
    left: 1px;
    width: auto;
    height: auto;
    display: block;
    color: #5cbf60;
    font-size: 20px;
    line-height: 1;
}

/* Inline slay icon prefix used in rare-drop tooltip state lines. */
.tt-line-slay-icon {
    width: 14px;
    height: 14px;
    vertical-align: -2px;
    margin-right: 4px;
    image-rendering: pixelated;
}
.rare-mark-lock {
    flex-direction: column;
    gap: 1px;
}
.rare-mark-lock .rare-mark-x {
    color: #ff6666;
    font-size: 20px;
    line-height: 1;
}
.rare-mark-lock img {
    width: 16px;
    height: 16px;
    image-rendering: pixelated;
    opacity: 1 !important;
}

/* ── Right Config Panel ── */
.mob-config-panel {
    width: 444px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    border-left: 2px solid var(--border-primary);
}

.config-section {
    padding: 10px 14px;
    border-bottom: 1px solid var(--border-primary);
    position: relative;
}

.config-label {
    font-size: 24px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 6px;
    text-align: center;
    position: relative;
}

/* Top-right shortcut icon inside a .config-label. Click opens the
   relevant Settings section (e.g. Combat Defaults for the Gear
   Loadout label). Tooltip via .window-control-tooltip styling. */
.config-label-shortcut {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border-radius: 4px;
    transition: background 0.15s;
}
.config-label-shortcut:hover {
    background: var(--bg-hover);
}
.config-label-shortcut img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.loadout-buttons {
    display: flex;
    gap: 4px;
}

.loadout-btn {
    flex: 1;
    padding: 6px 4px;
    text-align: center;
    font-family: var(--game-font);
    font-size: 20px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    cursor: pointer;
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    background: var(--bg-panel);
    transition: all 0.1s;
}
.loadout-btn:hover { background: var(--bg-cell); color: var(--text-light); }
.loadout-btn.active {
    color: var(--text-bright);
    border-color: var(--text-accent);
    background: var(--bg-cell);
}
.loadout-btn .style-icon { font-size: 18px; margin-right: 2px; }

.loadout-btn-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    vertical-align: middle;
    margin-right: 4px;
}

/* ── Paperdoll Grid (3×5, matches bank modal) ── */
.mob-config-panel .paperdoll {
    display: grid;
    grid-template-columns: repeat(3, 73px);
    grid-template-rows: repeat(5, 57px);
    gap: 4px;
    justify-content: center;
    align-content: center;
    margin-top: 8px;
}

.mob-config-panel .paperdoll .inv-slot {
    width: 56px;
    height: 56px;
    background: var(--bg-cell);
    border-color: var(--border-primary);
}
.mob-config-panel .paperdoll .inv-slot:hover { border-color: var(--text-accent); background: var(--bg-hover); }
.mob-config-panel .paperdoll .inv-slot:not(.empty) { border-color: var(--border-secondary); }
.mob-config-panel .paperdoll .inv-slot:not(.empty):hover { border-color: var(--text-accent); }
.mob-config-panel .paperdoll .inv-slot.empty { background: var(--bg-panel); }

.mob-config-panel .paperdoll .inv-slot img {
    transform: scale(1.5);
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* Silhouette for empty slots */
.mob-config-panel .paperdoll .equip-silhouette {
    opacity: 0.5;
    transform: scale(1.5);
}
.mob-config-panel .paperdoll .inv-slot:not(.empty) .equip-silhouette { display: none; }

/* Paperdoll grid positions */
.mob-config-panel .slot-head     { grid-column: 2; grid-row: 1; }
.mob-config-panel .slot-cape     { grid-column: 1; grid-row: 2; }
.mob-config-panel .slot-neck     { grid-column: 2; grid-row: 2; }
.mob-config-panel .slot-ammo     { grid-column: 3; grid-row: 2; }
.mob-config-panel .slot-mainhand { grid-column: 1; grid-row: 3; }
.mob-config-panel .slot-body     { grid-column: 2; grid-row: 3; }
.mob-config-panel .slot-offhand  { grid-column: 3; grid-row: 3; }
.mob-config-panel .slot-hands    { grid-column: 1; grid-row: 4; }
.mob-config-panel .slot-belt     { grid-column: 2; grid-row: 4; }
.mob-config-panel .slot-special  { grid-column: 3; grid-row: 4; }
.mob-config-panel .slot-ring1    { grid-column: 1; grid-row: 5; }
.mob-config-panel .slot-legs     { grid-column: 2; grid-row: 5; }
.mob-config-panel .slot-ring2    { grid-column: 3; grid-row: 5; }

/* ── Equipment Stats Panel ── */
.mob-config-panel .equip-stats-panel {
    background: var(--bg-dark);
    border-top: 1px solid var(--border-primary);
    padding: 8px 14px 10px;
}

.mob-config-panel .stats-weapon-line {
    text-align: center;
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

.mob-config-panel .stats-style-line {
    text-align: center;
    font-size: 22px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
}
.mob-config-panel .stats-style-line .style-val { color: var(--text-accent); }
.mob-config-panel .stats-style-line .speed-val { color: #88cc88; }
.mob-config-panel .stats-style-line .maxhit-val { color: #ff4444; }

.mob-config-panel .stats-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
}
.mob-config-panel .stats-table th {
    color: var(--text-accent);
    font-weight: normal;
    padding: 2px 6px;
    text-align: center;
    border-bottom: 1px solid var(--bg-cell);
}
.mob-config-panel .stats-table th:first-child { text-align: left; width: 70px; }
.mob-config-panel .stats-table td {
    padding: 1px 6px;
    text-align: center;
    color: var(--text-light);
}
.mob-config-panel .stats-table td:first-child { text-align: left; color: var(--text-accent); width: 104px; }
.mob-config-panel .stats-table .stat-pos { color: #4caf50; }
.mob-config-panel .stats-table .stat-zero { color: var(--border-primary); }
.mob-config-panel .stats-table .stat-neg { color: #ff4444; }
.mob-config-panel .stats-table .str-cell { display: flex; justify-content: space-between; color: var(--text-light); }
.mob-config-panel .stats-table .str-label { color: var(--text-muted); }

/* ── XP Toggle ── */
.xp-toggle-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.xp-toggle-btn {
    flex: 1;
    padding: 0px 4px;
    text-align: center;
    font-family: var(--game-font);
    font-size: 22px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    cursor: pointer;
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    background: var(--bg-panel);
    transition: all 0.1s;
    height: 38px;
}
.xp-toggle-btn:hover { background: var(--bg-cell); color: var(--text-light); }
.xp-toggle-btn.active {
    color: var(--text-bright);
    border-color: var(--text-accent);
    background: var(--bg-cell);
}

.xp-toggle-icon {
    width: 24px;
    height: 24px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    vertical-align: middle;
    margin-right: 4px;
}

/* ── Potion Display ── */
.potion-display {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.potion-icon {
    transform: scale(1.5);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.potion-icon img {
    width: 28px;
    height: 28px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.potion-info {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.potion-name {
    font-size: 20px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000;
    line-height: 1;
}

.potion-effect {
    font-size: 16px;
    color: #4caf50;
    text-shadow: 1px 1px 0 #000;
    line-height: 1;
}

.potion-remaining {
    font-size: 20px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    flex-shrink: 0;
}

.potion-inactive {
    font-size: 18px;
    color: var(--border-primary);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
    padding: 4px;
}

/* ── Fight Button ── */
.fight-section {
    margin-top: auto;
    padding: 12px 14px;
    border-top: 2px solid var(--border-primary);
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.fight-btn {
    width: 100%;
    height: 52px;
    font-family: var(--game-font);
    font-size: 32px;
    color: var(--text-bright);
    text-shadow: 2px 2px 0 #000;
    background: linear-gradient(180deg, #4a6a2a 0%, #3a5a1a 100%);
    border: 2px solid #6a8a3a;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.15s;
    text-align: center;
}
.fight-btn:hover { background: linear-gradient(180deg, #5a7a3a 0%, #4a6a2a 100%); border-color: #8aaa5a; }
.fight-btn:active { background: linear-gradient(180deg, #3a5a1a 0%, #2a4a0a 100%); }
.fight-btn.disabled {
    background: linear-gradient(180deg, #3a2020 0%, #2a1515 100%);
    border-color: #5a3030;
    color: #884444;
    cursor: not-allowed;
}

/* A requirement sentence naming two skills ("Requires Cook and Fish level
   90") measures 462px at the button's 32px, and the button has 410px of
   usable width. Requirement labels get their own size and may wrap; the
   button grows rather than clipping. */
.fight-btn.req-label {
    font-size: 22px;
    line-height: 1.15;
    white-space: normal;
    height: auto;
    min-height: 52px;
    padding: 6px 10px;
}

.fight-warning {
    font-size: 18px;
    color: #e74c3c;
    text-shadow: 1px 1px 0 #000;
    text-align: center;
}

/* ── No Selection Placeholder ── */
.no-selection {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 12px;
}
.no-selection-icon { font-size: 80px; opacity: 0.3; }
.no-selection-text {
    font-size: 28px;
    color: var(--border-primary);
    text-shadow: 1px 1px 0 #000;
}

/* ── Mob Selection Scrollbars ── */
.mob-stats-section {
    scrollbar-width: none;
}
.mob-stats-section::-webkit-scrollbar { display: none; }
.mob-list-scroll::-webkit-scrollbar,
.mob-config-panel::-webkit-scrollbar { width: 8px; }
.mob-list-scroll::-webkit-scrollbar-track,
.mob-config-panel::-webkit-scrollbar-track { background: var(--bg-dark); }
.mob-list-scroll::-webkit-scrollbar-thumb,
.mob-config-panel::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }

/* ═══════════════════════════════════════════════════════════════
   COMBAT ENCOUNTER — Floating Side Panels (Reworked)
   No longer a full-screen overlay. Panels float at screen edges,
   triggered by clicking units in the world via CombatWorldRenderer.
   All sprites, bars, and hitsplats are canvas-drawn.
   ═══════════════════════════════════════════════════════════════ */

.combat-encounter {
    position: absolute;
    inset: 0;
    z-index: 150;
    font-family: var(--game-font);
    color: #ffffff;
    transition: opacity 0.4s ease;
    pointer-events: none;
    /* NO background, NO backdrop */
}
.combat-encounter.fade-out { opacity: 0; pointer-events: none; }

/* Panel Wrappers — floating side panels */
.combat-encounter .panel-wrapper {
    width: 400px;
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
}
.combat-encounter .panel-wrapper.player-side {
    left: 0;
    pointer-events: auto;
}
.combat-encounter .panel-wrapper.mob-side {
    right: 0;
    pointer-events: auto;
}

/* Tab Bar (on panel wrappers) */
.combat-encounter .panel-tab-bar {
    display: none;
    flex-direction: column;
    gap: 4px;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 1;
    pointer-events: auto;
    height: 76px;
    width: 38px;
}
.combat-encounter .panel-tab-bar.visible { display: flex; }
.combat-encounter .panel-tab-bar.player-tabs { right: -38px; }
.combat-encounter .panel-tab-bar.mob-tabs { left: -38px; }

.combat-encounter .panel-tab {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 26px;
    line-height: 1;
    cursor: pointer;
    background: var(--bg-dark);
    border: 2px solid var(--bg-cell);
    border-radius: 6px;
    transition: all 0.15s;
    user-select: none;
    padding: 0;
}
.combat-encounter .panel-tab:hover { background: var(--bg-panel); border-color: var(--border-secondary); }
.combat-encounter .panel-tab.active {
    background: var(--bg-panel);
    border-color: var(--text-accent);
    box-shadow: 0 0 8px rgba(200,168,62,0.2);
}

/* Stat Panel */
.combat-encounter .combat-panel {
    width: 400px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    box-shadow: 0 0 40px rgba(0,0,0,0.7), inset 0 1px 0 rgba(200,168,62,0.08);
    display: flex;
    flex-direction: column;
    padding: 14px;
    pointer-events: auto;
    height: 640px;
    overflow-y: auto;
    transition: height 0.3s ease, padding 0.3s ease, opacity 0.25s ease;
}
.combat-encounter .combat-panel.panel-hidden {
    height: 0;
    padding: 0 14px;
    overflow: hidden;
    opacity: 0;
    border-width: 0;
    box-shadow: none;
    pointer-events: none;
}
.combat-encounter .combat-panel.panel-dead {
    border-color: #cc3333;
    box-shadow: 0 0 40px rgba(0,0,0,0.7), inset 0 1px 0 rgba(204,51,51,0.08);
}
.combat-encounter .combat-panel::-webkit-scrollbar { width: 5px; }
.combat-encounter .combat-panel::-webkit-scrollbar-track { background: var(--bg-panel); }
.combat-encounter .combat-panel::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 3px; }

.combat-encounter .panel-content { display: none; }
.combat-encounter .panel-content.active { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.combat-encounter .panel-content > .equip-stats-panel { margin-top: auto; }

/* Panel Header */
.combat-encounter .panel-header { text-align: center; margin-bottom: 8px; }
.combat-encounter .panel-name { font-size: 20px; font-weight: 700; color: var(--text-bright); text-shadow: 1px 1px 0 #000; }
.combat-encounter .panel-name.dead-name { color: #ff6666; text-decoration: line-through; opacity: 0.7; }
.combat-encounter .panel-level { font-size: 18px; color: #ffffff; text-shadow: 1px 1px 0 #000; }

.combat-encounter .section-header {
    font-size: 14px; font-weight: 700; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000; text-transform: uppercase;
    letter-spacing: 1.2px; margin: 12px 0 6px; padding-bottom: 4px;
    border-bottom: 1px solid var(--bg-cell);
}

/* Derived Grid */
.combat-encounter .derived-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 5px; margin-bottom: 8px; }
.combat-encounter .derived-item { background: var(--bg-cell); border: 1px solid var(--border-primary); border-radius: 3px; padding: 5px 4px; text-align: center; }
.combat-encounter .derived-label { font-size: 10px; color: var(--text-bright); text-transform: uppercase; letter-spacing: 0.6px; text-shadow: 1px 1px 0 #000; margin-bottom: 2px; }
.combat-encounter .derived-value { font-size: 16px; font-weight: 700; color: #ffffff; text-shadow: 1px 1px 0 #000; }

/* Skill Grid */
.combat-encounter .skill-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 10px; }
.combat-encounter .skill-row { display: flex; align-items: center; gap: 6px; padding: 3px 5px; border-radius: 3px; border: 1px solid transparent; }
.combat-encounter .skill-icon { width: 32px; height: 32px; flex-shrink: 0; image-rendering: pixelated; filter: drop-shadow(1px 1px 0 #000); }
.combat-encounter .skill-name { font-size: 14px; color: var(--text-accent); text-shadow: 1px 1px 0 #000; flex: 1; }
.combat-encounter .skill-val { font-size: 16px; font-weight: 600; color: var(--text-accent); text-shadow: 1px 1px 0 #000; min-width: 24px; text-align: right; }

.combat-encounter .skill-row.selectable { cursor: pointer; transition: border-color 0.15s, background 0.15s; }
.combat-encounter .skill-row.selectable:hover { border-color: var(--border-secondary); background: rgba(200,168,62,0.06); }
.combat-encounter .skill-row.selectable.chosen { border-color: var(--text-accent); background: rgba(200,168,62,0.12); }
.combat-encounter .skill-row.selectable.chosen .skill-name,
.combat-encounter .skill-row.selectable.chosen .skill-val { color: var(--text-bright); }


/* Equipment Stats Panel (inside combat encounter stats tab) */
.combat-encounter .equip-stats-panel {
    background: none;
    border-top: 2px solid var(--border-primary);
    padding: 8px 10px 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 6px;
}
.combat-encounter .equip-stats-panel .stats-weapon-line {
    text-align: center;
    font-size: 16px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}
.combat-encounter .equip-stats-panel .stats-style-line {
    text-align: center;
    font-size: 14px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 2px;
}
.combat-encounter .equip-stats-panel .stats-style-line .style-val { color: var(--text-accent); }
.combat-encounter .equip-stats-panel .stats-style-line .speed-val { color: #88cc88; }
.combat-encounter .equip-stats-panel .stats-style-line .maxhit-val { color: #ff6644; }
.combat-encounter .equip-stats-panel .stats-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
    text-shadow: 1px 1px 0 #000;
}
.combat-encounter .equip-stats-panel .stats-table th {
    color: var(--text-accent);
    font-weight: normal;
    padding: 1px 4px;
    text-align: center;
    border-bottom: 1px solid var(--bg-cell);
}
.combat-encounter .equip-stats-panel .stats-table th:first-child {
    text-align: left;
    width: 70px;
}
.combat-encounter .equip-stats-panel .stats-table td {
    padding: 1px 4px;
    text-align: center;
    color: var(--text-light);
}
.combat-encounter .equip-stats-panel .stats-table td:first-child {
    text-align: left;
    color: var(--text-accent);
    width: 80px;
}
.combat-encounter .equip-stats-panel .stats-table .stat-pos { color: #4caf50; }
.combat-encounter .equip-stats-panel .stats-table .stat-zero { color: var(--border-primary); }
.combat-encounter .equip-stats-panel .stats-table .stat-neg { color: #ff4444; }
.combat-encounter .equip-stats-panel .stats-table .str-cell { text-align: center; color: var(--text-light); }
.combat-encounter .equip-stats-panel .stats-table .str-label { color: var(--text-muted); }
.combat-encounter .equip-stats-panel .stats-icon-wrap {
    display: inline-block;
    vertical-align: middle;
    width: 16px;
    height: 16px;
    margin-right: 3px;
}
.combat-encounter .equip-stats-panel .stats-icon-wrap img {
    width: 16px;
    height: 16px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

/* Loadout Dropdown */
.combat-encounter .loadout-dropdown {
    position: relative;
    margin-bottom: 10px;
}
.combat-encounter .loadout-dropdown-trigger {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 16px;
    font-weight: 700;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    text-transform: uppercase;
    letter-spacing: 1px;
    transition: background 0.15s;
}
.combat-encounter .loadout-dropdown-trigger:hover { background: rgba(200, 168, 62, 0.1); }
.combat-encounter .loadout-dropdown.open .loadout-dropdown-trigger { background: rgba(200, 168, 62, 0.15); }
.combat-encounter .loadout-dropdown-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.combat-encounter .loadout-dropdown-arrow {
    font-size: 10px;
    color: var(--text-muted);
    transition: transform 0.15s;
}
.combat-encounter .loadout-dropdown.open .loadout-dropdown-arrow { transform: rotate(180deg); }
.combat-encounter .loadout-dropdown-menu {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 4px 0;
    min-width: 210px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.6);
}
.combat-encounter .loadout-dropdown-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    cursor: pointer;
    font-size: 15px;
    font-weight: 700;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    text-transform: uppercase;
    letter-spacing: 1px;
    transition: background 0.1s;
}
.combat-encounter .loadout-dropdown-option:hover { background: rgba(200, 168, 62, 0.15); }
.combat-encounter .loadout-dropdown-option.active { background: rgba(200, 168, 62, 0.25); }
.combat-encounter .paperdoll {
    display: grid; grid-template-columns: repeat(3, 56px); grid-template-rows: repeat(5, 56px);
    gap: 4px; justify-content: center; align-content: center; margin: 0 auto;
}
.combat-encounter .paperdoll .inv-slot {
    width: 56px; height: 56px;
    border-color: var(--bg-hover); background: var(--bg-darkest);
    cursor: default; justify-self: center; align-self: center;
}
.combat-encounter .paperdoll .inv-slot.empty { border-color: var(--bg-cell); background: #151510; }
.combat-encounter .paperdoll .inv-slot img { transform: scale(1.5); }

/* Loot Tab */
.combat-encounter .loot-tab-header { text-align: center; margin-bottom: 10px; }
.combat-encounter .loot-tab-title { font-size: 16px; font-weight: 700; color: var(--text-accent); text-shadow: 1px 1px 0 #000; text-transform: uppercase; letter-spacing: 1px; }
.combat-encounter .loot-grid { display: grid; grid-template-columns: repeat(5, 56px); gap: 4px; justify-content: center; margin: 0 auto; }
.combat-encounter .loot-sub-tabs { display: flex; gap: 4px; margin-bottom: 8px; justify-content: center; }
.combat-encounter .loot-sub-tab {
    background: var(--bg-cell); border: 1px solid var(--border-primary); color: #b8a070; padding: 4px 12px;
    font-family: inherit; font-size: 12px; cursor: pointer; border-radius: 3px;
    text-transform: uppercase; letter-spacing: 0.5px;
}
.combat-encounter .loot-sub-tab:hover { border-color: var(--text-accent); color: #e0d0a0; }
.combat-encounter .loot-sub-tab.active { background: var(--bg-hover); border-color: var(--text-accent); color: var(--text-accent); }
.combat-encounter .loot-table { width: 100%; margin-top: 4px; }
.combat-encounter .loot-drop-scroll { overflow-y: auto; }

/* Combat HUD — floating kill count + end button at bottom center */
.combat-encounter .combat-hud {
    position: absolute;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
}

/* End Combat Button */
.btn-end-combat {
    padding: 10px 32px; pointer-events: auto;
    background: rgba(43,34,22,0.95); border: 2px solid var(--text-accent);
    color: var(--text-accent); font-family: var(--game-font);
    font-size: 20px; font-weight: 700; border-radius: 4px;
    cursor: pointer; text-shadow: 1px 1px 0 #000;
    transition: all 0.2s; letter-spacing: 0.8px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.5);
}
.btn-end-combat:hover {
    background: rgba(200,168,62,0.15); border-color: #e0c060; color: #e0c060;
    box-shadow: 0 0 12px rgba(200,168,62,0.3), 0 4px 16px rgba(0,0,0,0.5);
}
.float-end-combat-btn {
    position: absolute;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100;
}
/* Gauntlet End / Leave button: bottom-center of the play area, mirroring
   the combat raid's End Combat button (the gauntlet has no combat modal,
   so it mounts straight onto the UI container). Reuses .btn-end-combat
   for the look. */
.gauntlet-leave-btn {
    position: absolute;
    bottom: 24px;
    left: var(--playable-center-x, 50%);
    transform: translateX(-50%);
    z-index: 505;
}
body.login-active .gauntlet-leave-btn { display: none !important; }

/* Kill Count */
.combat-encounter .ce-kill-count {
    pointer-events: auto;
    font-size: 20px; font-weight: 700; color: var(--text-accent);
    text-shadow: 1px 1px 0 #000; letter-spacing: 0.5px;
    transition: color 0.3s, text-shadow 0.3s;
}
.combat-encounter .ce-kill-count.kill-flash {
    color: var(--text-bright);
    text-shadow: 0 0 8px rgba(255,255,0,0.6), 1px 1px 0 #000;
    animation: ce-kill-pulse 0.6s ease-out;
}
@keyframes ce-kill-pulse {
    0% { transform: scale(1.3); }
    100% { transform: scale(1); }
}

/* Eat Indicator (inside combat HUD) */
.combat-encounter .eat-indicator {
    position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);
    font-size: 13px; font-weight: 700; color: #5cbf60;
    text-shadow: 1px 1px 0 #000; white-space: nowrap;
    display: flex; align-items: center; gap: 4px;
    pointer-events: none;
    opacity: 0; transition: opacity 0.3s ease, transform 0.3s ease;
    z-index: 2300;
    margin-bottom: 4px;
}
.combat-encounter .eat-indicator.visible { opacity: 1; transform: translateX(-50%) translateY(-4px); }
.combat-encounter .eat-indicator.fading { opacity: 0; transform: translateX(-50%) translateY(-16px); transition: opacity 0.6s ease, transform 0.6s ease; }

/* ═══════════════════════════════════════════════════════════════
   LOGIN SCREEN (Layer 14D)
   Full-screen overlay for login/register before the game loads.
   Animated map background, vignette, social links, patch notes.
   ═══════════════════════════════════════════════════════════════ */

.login-screen {
    position: absolute;
    inset: 0;
    z-index: 3000;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #1a1a2e;
    font-family: var(--game-font);
    overflow: hidden;
}

/* ── Background canvas ─────────────────────────────────────── */
.login-bg-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}

/* ── Vignette overlay ──────────────────────────────────────── */
.login-vignette {
    position: absolute;
    inset: -10px;
    background:
        radial-gradient(ellipse at center, rgba(0,0,0,0.25) 0%, rgba(0,0,0,0.6) 60%, rgba(0,0,0,0.9) 100%);
    pointer-events: none;
    z-index: 1;
}

/* ── Social links (top-left) — 1.1x scale ─────────────────── */
.login-social {
    position: absolute;
    top: 100px;
    left: 31px;
    display: flex;
    flex-direction: column;
    gap: 15px;
    z-index: 2;
    animation: loginFadeIn 0.8s ease-out 1.6s both;
}
.login-social-link {
    display: flex;
    align-items: center;
    gap: 11px;
    color: rgba(255,255,255,0.5);
    text-decoration: none;
    font-size: 17px;
    font-family: var(--game-font);
    letter-spacing: 0.55px;
    transition: color 0.25s, transform 0.2s;
}
.login-social-link:hover {
    color: rgba(255,255,255,0.95);
    transform: translateX(2px);
}
.login-social-link svg {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    opacity: 0.7;
    transition: opacity 0.25s;
}
.login-social-link:hover svg {
    opacity: 1;
}

/* ── Version block (top-left, above social links) ──────────── */
/* Two stacked rows: server version on top, client version below.
   Mismatch shows a yellow update message under both rows. */
.login-version-block {
    position: absolute;
    top: 26px;
    left: 31px;
    z-index: 2;
    font-family: var(--game-font);
    font-size: 13px;
    font-weight: 300;
    color: rgba(255,255,255,0.2);
    letter-spacing: 1.5px;
    text-transform: uppercase;
    line-height: 1.45;
    animation: loginFadeIn 0.6s ease-out 1.8s both;
}
.login-version-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
}
.login-version-label {
    min-width: 50px;
    color: rgba(255,255,255,0.18);
}
.login-version-value {
    color: rgba(255,255,255,0.32);
}
.login-version-value.mismatch {
    color: #f5c542;
}
.login-version-warning {
    margin-top: 6px;
    font-size: 11px;
    letter-spacing: 1.1px;
    color: #f5c542;
    max-width: 260px;
    line-height: 1.4;
    text-transform: none;
}
.login-version-warning-btn {
    margin-top: 6px;
    background: rgba(245, 197, 66, 0.12);
    border: 1px solid #f5c542;
    color: #f5c542;
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 1.1px;
    padding: 4px 10px;
    border-radius: 3px;
    cursor: pointer;
    text-transform: uppercase;
}
.login-version-warning-btn:hover {
    background: rgba(245, 197, 66, 0.22);
}

/* ── Online counter (top-right) — 1.1x scale ─────────────── */
/* Sits below the window-controls strip (which is top:12px height
   ~36px) so the extra buttons in the strip never overlap. */
.login-online {
    position: absolute;
    top: 60px;
    right: 31px;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 9px;
    font-family: var(--game-font);
    font-size: 17px;
    color: rgba(255,255,255,0.45);
    letter-spacing: 0.88px;
    animation: loginFadeIn 0.6s ease-out 1.4s both;
}
.login-online-dot {
    width: 9px;
    height: 9px;
    background: #4CAF50;
    border-radius: 50%;
    box-shadow: 0 0 9px rgba(76,175,80,0.6);
    animation: onlinePulse 2s ease-in-out infinite;
}
@keyframes onlinePulse {
    0%, 100% { box-shadow: 0 0 7px rgba(76,175,80,0.4); }
    50% { box-shadow: 0 0 15px rgba(76,175,80,0.8); }
}

/* ── Patch notes panel (top-right) — persistent across login/game ─ */
/* Default styling uses theme variables so it sits cleanly with the
   in-game chrome. body.login-active swaps to the original translucent
   look so it reads correctly over the bright animated map background.
   The panel itself is a sibling of the login screen inside
   #ui-container, so its visibility survives login state changes. */
.patch-notes-panel {
    position: absolute;
    top: 60px;
    right: 12px;
    width: 330px;
    max-height: 600px;
    overflow-y: auto;
    z-index: 9998;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 6px;
    padding: 16px 18px;
    color: var(--text-light);
}
body.login-active .patch-notes-panel {
    /* Login overrides: shift down to clear the bigger login button row
       and switch to the warm-translucent look that matches the rest of
       the login chrome. Keeps the original entrance animation. */
    top: 96px;
    right: 31px;
    max-height: 46vh;
    background: rgba(10,8,18,0.55);
    border: 1px solid rgba(200,168,62,0.12);
    border-radius: 8px;
    padding: 20px 22px;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
/* Match the rest of the in-game UI: when a fullscreen modal opens,
   hide the floating panel so it doesn't overlap modal chrome. The
   WindowControls strip already follows the same convention. */
body.modal-open .patch-notes-panel { display: none !important; }
@keyframes slideInRight {
    from { opacity: 0; transform: translateX(40px); }
    to   { opacity: 1; transform: translateX(0); }
}
/* Hide the scrollbar entirely (in both contexts) while keeping the
   overflow scrollable. Without this, the bar appears / disappears
   depending on which patch entry is selected and the prev/next
   arrows jump horizontally to make room. */
.patch-notes-panel {
    scrollbar-width: none;          /* Firefox */
    -ms-overflow-style: none;       /* legacy IE / old Edge */
}
.patch-notes-panel::-webkit-scrollbar {
    width: 0;
    height: 0;
    display: none;
}
.patch-notes-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 15px;
}
.patch-notes-title {
    font-size: 19px;
    color: var(--text-gold);
    margin: 0;
    font-weight: 600;
    letter-spacing: 1.1px;
    text-shadow: 1px 1px 0 #000;
}
.patch-notes-nav {
    display: flex;
    gap: 4px;
}
.patch-notes-arrow {
    width: 28px;
    height: 28px;
    background: rgba(200,168,62,0.10);
    border: 1px solid rgba(200,168,62,0.25);
    border-radius: 4px;
    color: var(--text-gold);
    font-size: 22px;
    line-height: 1;
    padding: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
    font-family: inherit;
}
.patch-notes-arrow:hover {
    background: rgba(200,168,62,0.22);
    border-color: rgba(200,168,62,0.55);
    color: #fff;
}
.patch-notes-arrow.disabled {
    opacity: 0.3;
    cursor: default;
    pointer-events: none;
}
.patch-note-version {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 8px;
}
.patch-note-ver {
    color: var(--text-accent);
    font-weight: 600;
    font-size: 15px;
    letter-spacing: 0.55px;
}
.patch-note-date {
    color: rgba(255,255,255,0.3);
    font-size: 13px;
}
.patch-note-item {
    color: rgba(255,255,255,0.6);
    font-size: 14px;
    padding-left: 7px;
    line-height: 1.6;
}

/* ── Center login area (logo top, button bottom) ──────────── */
/* Full-screen vertical flex — logo pinned near top, button near
   bottom. Padding controls how close they get to each edge.
   IMPORTANT: height must be 100% (not 100vh) so the layout matches
   the fixed 1080px #ui-container. vh is viewport-relative and would
   drift when the user toggles fullscreen. */
.login-area {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    height: 100%;
    padding: 100px 0 220px;
    box-sizing: border-box;
    pointer-events: none;
    /* No animation on the wrapper — keeps the logo statically
       positioned across the loading→login transition so it doesn't
       slide. The button fades in on its own (below). */
}
.login-area > * { pointer-events: auto; }

/* No glass — just hosts the button and inline error. */
.login-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
}

.login-form {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    /* Fade-in just the button area — logo stays in place. */
    animation: loginFadeIn 0.8s ease-out both;
}

.login-btn {
    flex: 1;
    padding: 13px 0;
    font-family: var(--game-font);
    font-size: 18px;
    font-weight: 700;
    border: 1px solid;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.25s;
    letter-spacing: 1px;
    text-transform: uppercase;
    text-shadow: 0 1px 3px rgba(0,0,0,0.5);
    position: relative;
    overflow: hidden;
}
.login-btn::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(255,255,255,0.06) 0%, transparent 50%);
    pointer-events: none;
}
.login-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.login-error {
    display: none;
    color: #ff4444;
    font-size: 18px;
    text-align: center;
    text-shadow: 1px 1px 0 #000;
    padding: 6px 0;
    margin-top: -14px;
    margin-bottom: -14px;
    height: 0;
    overflow: visible;
}

/* Clickable Steam store link inside the not-owner error message. */
.login-store-link {
    color: #ffd24d;
    text-decoration: underline;
    cursor: pointer;
}
.login-store-link:hover {
    color: #ffe08a;
}

/* ═══════════════════════════════════════════════════════════════
   Steam wishlist / demo-review prompt (SteamPromptModal.js)
   Lives inside #ui-container's fixed 1920x1080 grid so it scales
   with the rest of the UI. Backdrop + centered card.
   ═══════════════════════════════════════════════════════════════ */
.steam-prompt-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 1920px;
    height: 1080px;
    background: rgba(0, 0, 0, 0.72);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 6800;
}

.steam-prompt-card {
    width: 720px;
    max-width: 86%;
    background: var(--bg-panel);
    border: 2px solid var(--border-secondary);
    border-radius: 10px;
    box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.5), 0 18px 60px rgba(0, 0, 0, 0.6);
    padding: 40px 48px 36px;
    text-align: center;
    font-family: var(--game-font);
    color: var(--text-light);
}

/* Fun-but-tasteful entrance: fade + scale with a soft overshoot. */
.steam-prompt-animate-in {
    animation: steam-prompt-pop 420ms cubic-bezier(0.2, 0.9, 0.3, 1.25) both;
}
@keyframes steam-prompt-pop {
    0%   { opacity: 0; transform: scale(0.85) translateY(12px); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}

.steam-prompt-hero {
    margin-bottom: 14px;
}
.steam-prompt-hero img {
    width: 84px;
    height: 84px;
    image-rendering: pixelated;
    filter: drop-shadow(0 0 10px rgba(255, 210, 77, 0.45));
    animation: steam-prompt-bob 2.4s ease-in-out infinite;
}
@keyframes steam-prompt-bob {
    0%, 100% { transform: translateY(0) rotate(-2deg); }
    50%      { transform: translateY(-6px) rotate(2deg); }
}

.steam-prompt-headline {
    font-size: 30px;
    font-weight: 700;
    color: var(--text-gold);
    text-shadow: 2px 2px 0 #000;
    margin-bottom: 14px;
}
.steam-prompt-level {
    color: var(--text-bright);
}

.steam-prompt-deco {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-bottom: 18px;
}
.steam-prompt-deco img {
    width: 36px;
    height: 36px;
    image-rendering: pixelated;
    opacity: 0.92;
    animation: steam-prompt-bob 3s ease-in-out infinite;
}

.steam-prompt-note {
    font-size: 19px;
    line-height: 1.45;
    color: var(--text-light);
    margin: 0 0 10px;
    text-align: left;
}

.steam-prompt-signoff {
    font-size: 19px;
    font-style: italic;
    color: var(--text-gold);
    margin: 0 0 18px;
    text-align: left;
    padding-left: 24px;
}

.steam-prompt-line {
    font-size: 18px;
    line-height: 1.45;
    color: var(--text-dim);
    margin: 0 0 12px;
    text-align: left;
}

.steam-prompt-storelink {
    color: #ffd24d;
    font-weight: 600;
    text-decoration: underline;
    cursor: pointer;
    white-space: nowrap;
}
.steam-prompt-storelink:hover {
    color: #ffe08a;
}

.steam-prompt-buttons {
    display: flex;
    justify-content: center;
    gap: 16px;
    margin-top: 26px;
}
.steam-prompt-btn {
    font-family: var(--game-font);
    font-size: 18px;
    font-weight: 600;
    padding: 12px 28px;
    border-radius: 6px;
    cursor: pointer;
    border: 2px solid var(--border-primary);
    background: var(--bg-cell);
    color: var(--text-light);
    transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.steam-prompt-btn:hover {
    background: var(--bg-hover);
    border-color: var(--border-secondary);
}
.steam-prompt-btn-later {
    color: var(--text-gold);
}
.steam-prompt-btn-never {
    color: var(--text-muted);
}

/* ── Steam sign-in button — 1.1x scale ─────────────────────── */
.login-btn-steam {
    /* Override .login-btn flex:1 so the button sizes to its content. */
    flex: 0 0 auto;
    padding: 24px 62px;
    font-family: var(--game-font);
    font-size: 29px;
    font-weight: 700;
    letter-spacing: 2.2px;
    text-transform: uppercase;
    text-shadow: 0 1px 3px rgba(0,0,0,0.6);
    color: #d8e0ee;
    background: linear-gradient(180deg, rgba(60,90,140,0.55) 0%, rgba(28,52,92,0.7) 100%);
    border: 1px solid rgba(150,180,220,0.65);
    border-radius: 7px;
    cursor: pointer;
    transition: all 0.25s;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0;
}
.login-btn-steam svg { color: #d8e0ee; }
.login-btn-steam:hover:not(:disabled) {
    background: linear-gradient(180deg, rgba(80,118,180,0.55) 0%, rgba(40,72,124,0.65) 100%);
    border-color: rgba(170,200,240,0.85);
    box-shadow: 0 0 20px rgba(120,160,220,0.25), 0 0 60px rgba(120,160,220,0.08);
    transform: translateY(-1px);
}
.login-btn-steam:active:not(:disabled) {
    transform: translateY(0);
}
.login-btn-steam:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ── First-time signup: display-name picker ─────────────────── */
.login-signup {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding: 8px 0;
    min-width: 480px;
}
.login-signup-title {
    margin: 0;
    text-align: center;
    color: #FFD700;
    font-family: 'Cinzel', serif;
    font-size: 30px;
    font-weight: 700;
    letter-spacing: 2px;
    text-shadow: 0 2px 6px rgba(0,0,0,0.8);
}
.login-signup-blurb {
    margin: 0;
    text-align: center;
    color: rgba(220,220,235,0.85);
    font-family: var(--game-font);
    font-size: 16px;
    line-height: 1.45;
    text-shadow: 1px 1px 0 rgba(0,0,0,0.8);
}
.login-signup-input {
    background: rgba(20,20,32,0.7);
    border: 1px solid rgba(150,180,220,0.5);
    border-radius: 6px;
    color: #fff;
    font-family: var(--game-font);
    font-size: 22px;
    letter-spacing: 1px;
    padding: 14px 18px;
    text-align: center;
    outline: none;
    transition: border-color 0.2s, box-shadow 0.2s;
}
.login-signup-input:focus {
    border-color: rgba(255,215,0,0.7);
    box-shadow: 0 0 14px rgba(255,215,0,0.18);
}
.login-signup-feedback {
    min-height: 22px;
    text-align: center;
    font-family: var(--game-font);
    font-size: 16px;
    text-shadow: 1px 1px 0 rgba(0,0,0,0.8);
    color: rgba(200,200,215,0.65);
}
.login-signup-feedback[data-kind='ok']      { color: #6dd66d; }
.login-signup-feedback[data-kind='error']   { color: #ff6464; }
.login-signup-feedback[data-kind='pending'] { color: rgba(220,220,235,0.6); }
.login-btn-submit {
    /* Re-uses login-btn-steam visual; just a hook for any future tweaks. */
    margin-top: 4px;
}

/* "Sign in as a different Steam user" — secondary, smaller version
   shown below the primary Continue-as-X button when running inside
   the Steam wrapper. */
.login-btn-steam.login-btn-steam-alt {
    padding: 12px 28px;
    font-size: 16px;
    letter-spacing: 1.4px;
    background: rgba(40,60,90,0.35);
    border: 1px solid rgba(120,150,190,0.35);
    color: rgba(200,215,235,0.85);
    margin-top: 6px;
}
.login-btn-steam.login-btn-steam-alt svg {
    width: 20px;
    height: 20px;
    margin-right: 10px;
}
.login-btn-steam.login-btn-steam-alt:hover:not(:disabled) {
    background: rgba(60,90,130,0.45);
    border-color: rgba(160,190,225,0.55);
}

/* "Guest Mode" — secondary button below Sign in with Steam, shown only
   on dev/test builds (allowGuest from /api/version). */
.login-btn-steam.login-btn-guest {
    padding: 12px 28px;
    font-size: 16px;
    letter-spacing: 1.4px;
    background: rgba(40,60,90,0.35);
    border: 1px solid rgba(120,150,190,0.35);
    color: rgba(200,215,235,0.85);
    margin-top: 6px;
}
.login-btn-steam.login-btn-guest:hover:not(:disabled) {
    background: rgba(60,90,130,0.45);
    border-color: rgba(160,190,225,0.55);
}

/* ── Top-right window controls (fullscreen toggle + close) ── */
/* z-index pushed above everything — login screen (3000), loading
   screen (4000), modal overlays (2000), notification stacks (9999).
   Stays on top regardless of what's open. */
.window-controls {
    position: absolute;
    top: 12px;
    right: 12px;
    display: flex;
    gap: 6px;
    z-index: 99999;
}
/* Hide the top-right fullscreen+close buttons while a fullscreen
   modal is open. The Group of Modals has its own close button in the
   header; the window controls would overlap it. body.modal-open is
   toggled by GroupOfModals.open / .close. */
body.modal-open .window-controls {
    display: none;
}
.window-control-btn {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    cursor: pointer;
    padding: 0;
    pointer-events: auto;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    /* In-game default: theme variables. Login override below
       (body.login-active) keeps the original translucent-dark look. */
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    color: var(--text-light);
}
.window-control-btn:hover {
    background: var(--bg-hover);
    color: var(--text-bright);
    border-color: var(--border-secondary);
}
.window-control-btn-x:hover {
    background: rgba(120,28,28,0.7);
    border-color: rgba(220,80,80,0.85);
    color: #ffe0e0;
}

/* Login screen: keep the original translucent-dark variant so the
   buttons read cleanly over the bright animated map background. */
body.login-active .window-control-btn {
    background: rgba(20,16,28,0.75);
    border: 1px solid rgba(255,255,255,0.18);
    color: rgba(255,255,255,0.8);
}
body.login-active .window-control-btn:hover {
    background: rgba(40,32,56,0.85);
    color: rgba(255,255,255,0.95);
    border-color: rgba(255,255,255,0.3);
}

/* Mod Tool button: only visible to moderators (body.is-mod). Same
   36x36 icon shape as the other window controls so it sits cleanly in
   the strip; inherits theme styling from .window-control-btn. */
.window-control-btn-mod { display: none; }
body.is-mod .window-control-btn-mod { display: flex; }

/* Vote button (scapelikes): far-left icon in the strip. Hidden by
   default; shown only when the server marks the player eligible
   (.vote-eligible) AND they're in-game. The login-active rule has
   higher specificity than .vote-eligible, so it stays hidden on the
   login screen even if an eligible state lingers. */
.window-control-btn-vote { display: none; }
.window-control-btn-vote.vote-eligible { display: flex; }
body.login-active .window-control-btn-vote { display: none; }

/* World Map button: hidden on the login screen since there is no
   game world to view yet. Sits inline with the other window controls
   in-game. */
body.login-active .window-control-btn-map { display: none; }

/* Sleep button: same reasoning as the map button. There is no live
   session to park until the player is actually in-game. */
body.login-active .window-control-btn-sleep { display: none; }

/* ── Per-button visibility (Settings > Window Controls) ────────
   Driven by body classes from SettingsModal._applySettings. The Mod
   Tool button has no toggle on purpose: it is already gated on
   body.is-mod and staff shouldn't be able to lose it by accident.
   Specificity (0,2,1) clears the plain .window-control-btn display
   and ties with the body.login-active rules above, which are also
   hides, so the two compose rather than fight. */
/* Scoped to the strip on purpose: I18n.createPicker() also mounts a
   .sw-lang-picker in the Settings header and another in the settings
   search bar. Those are how you change language when the strip copy is
   hidden, so an unscoped selector would take away the very control this
   toggle is about. */
/* Master switch: hides the whole strip in one go, sleep screen
   included. Placed first so the per-button rules below read as
   refinements of it. */
body.hide-wc-all .window-controls { display: none; }

body.hide-wc-lang .window-controls .sw-lang-picker { display: none; }

/* Mod Tool. Must come AFTER the body.is-mod show rule above: the two
   have equal specificity (0,2,1), so source order decides and this hide
   has to be able to win. Default-on, so a newly promoted moderator gets
   the button without having to discover the setting first. */
body.hide-wc-mod .window-control-btn-mod { display: none; }

/* The Mod Tool row in Settings > Window Controls exists in the DOM for
   everyone but is only shown to moderators. CSS-gated rather than
   conditionally built because mod status lands on game_init, after the
   settings DOM is constructed. The search filter sets display:'' to
   reveal a row, which falls back to this cascade, so filtering can't
   leak the row to non-moderators. */
.settings-row-mod-only { display: none; }
body.is-mod .settings-row-mod-only { display: flex; }

body.hide-wc-kofi        .window-control-btn-kofi,
body.hide-wc-discord     .window-control-btn-discord,
body.hide-wc-map         .window-control-btn-map,
body.hide-wc-patch-notes .window-control-btn-patch-notes,
body.hide-wc-fullscreen  .window-control-btn-fullscreen,
body.hide-wc-sleep       .window-control-btn-sleep,
body.hide-wc-close       .window-control-btn-x { display: none; }

/* ── Sleep mode ────────────────────────────────────────────────
   Opaque panel covering the 1920x1080 game area, mounted as a direct
   child of #ui-container. It has to live there, not on <body>:
   #game-container has a transform and #ui-container has a z-index, so
   both open stacking contexts, and a body-level overlay could never be
   ordered against the window-controls strip trapped inside them. As
   siblings the two compare normally, which is what lets Sleep and Close
   stay clickable while asleep. The letterbox outside #game-container is
   already #000 from the html/body rule, so covering only the game area
   is seamless.

   Colours come from the theme variables rather than hardcoded slate so
   the screen still reads as this player's game, but the BACKGROUND
   stays pure black on purpose: it is the "off" signal, and it is the
   cheapest thing a display can show (meaningfully so on OLED). Accents
   are the normal theme colours pulled down with opacity.

   Deliberately no CSS filter: anywhere in here — filters force a
   composited layer and can pull work back onto the main thread, which
   is exactly what this screen exists to avoid. */
.sleep-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 18px;
    background: #000;
    /* Above .window-controls' normal 99999 so the strip is covered by
       default; body.sleeping then lifts the strip back over it. */
    z-index: 100000;
    user-select: none;
    cursor: default;
}

/* Hiding the panels is what actually buys the idle: a display:none
   subtree is skipped entirely by layout and paint, so the packet
   handlers that keep writing into these panels while the player sleeps
   cost nothing downstream of the DOM write itself.

   Every child of #ui-container goes EXCEPT the window-controls strip.
   We can't hide #ui-container itself and then re-show a descendant:
   display:none removes the whole subtree and no descendant rule can
   bring part of it back.

   The canvas goes too. It is already fully occluded by the opaque
   overlay, but display:none drops its 1920x1080 layer out of the
   compositor tree rather than leaving it there to be composited behind
   something nobody can see through. Safe because every reader of the
   canvas rect is a pointer handler on the canvas itself, and a
   display:none element receives no pointer events. The 2D context and
   its backing store survive, so waking needs no re-init.

   Four things survive the cull, listed in the :not() chain below:
     .sleep-overlay      the sleep screen itself
     .window-controls    so Sleep and Close stay reachable
     .ctx-confirm-overlay  the exit dialog those buttons open
     .ingame-hud         name / status / online count, all of which stay
                         accurate while asleep (state_update is never
                         suppressed, and online_summary is broadcast with
                         a raw ws.send that the sleep gate never sees) */
body.sleeping #ui-container > *:not(.window-controls):not(.sleep-overlay):not(.ctx-confirm-overlay):not(.ingame-hud),
body.sleeping #game-canvas { display: none; }

/* Info HUD on the sleep screen. Lifted over the overlay and nudged left
   into the space the (hidden) floating tab strip normally occupies. It
   costs nothing extra to show: IngameHUD.update() already runs while
   asleep because state_update still arrives, so the DOM writes happen
   either way and only the paint is added, and only when text changes.
   The container is pointer-events:none with the two disclosure rows
   re-enabled, so expand/collapse keeps working here. */
body.sleeping .ingame-hud {
    z-index: 100001;
    /* Deliberately NOT overriding `left`. An earlier version nudged it to
       12px to fill the gap left by the hidden tab strip, but that shifted
       it 60px from where it sits in game, and in windowed-panels mode the
       player may have placed it themselves (.panel-min-attached). Staying
       put is worth more than closing the gap.

       Shed the panel chrome and dim to sit with the rest of the sleep
       screen. The normal solid --bg-panel fill and 2px lit border read
       as a switched-on UI element against pure black. Keeping the
       border at transparent rather than removing it preserves the
       padding, so nothing shifts on wake. Container opacity dims the
       state colours (moving/acting/combat) uniformly, which is the same
       treatment the moon, clock and note get. */
    background: transparent;
    border-color: transparent;
    opacity: 0.6;
}

/* The logout/exit confirm dialog is appended to #ui-container, so the
   rule above would hide it outright — clicking X while asleep would
   look like nothing happened. Exempt it and lift it over both the sleep
   screen and the strip, since it is a modal answer to a click the
   player just made. */
body.sleeping .ctx-confirm-overlay { z-index: 100002; }

/* The strip stays, lifted above the overlay. Only Sleep and Close are
   kept: both are "I am done here" actions that shouldn't require waking
   up first. Everything else (language, Ko-fi, Discord, map, patch
   notes, fullscreen, mod, vote) is a browse-or-configure action that
   implies you're using the client again, at which point you should just
   wake. The per-button Settings toggles above still apply on top of
   this, so hiding Sleep or Close in Settings hides them here too. */
body.sleeping .window-controls { z-index: 100001; }
body.sleeping .window-controls > *:not(.window-control-btn-sleep):not(.window-control-btn-x) {
    display: none;
}

/* Moon + player character on one row. The character is a static 64x64
   bake scaled 3x with nearest-neighbour, matching how the game renders
   sprites everywhere else. Bottom-aligned so a seated pose sits on the
   same ground line as a standing one instead of floating. */
.sleep-scene {
    position: relative;
    width: 260px;
    height: 260px;
    flex: none;
    /* Own stacking context, so the moon/character order below is decided
       strictly inside this box and can't be reinterpreted against the
       overlay's context. Without it both children are positioned
       descendants of a z-index:auto parent, so they get ordered up in
       .sleep-overlay's context alongside unrelated things. */
    isolation: isolate;
}

/* Moon sits BEHIND the character, both centred on the same point. The
   crescent opens up-and-right, so a seated pose nests into its hollow
   and the two read as one picture rather than two icons sharing a row.

   inset:0 + flex centring rather than a translate, deliberately: the
   breathe animation below drives `transform`, and a positioning
   translate in the base rule would be wiped out by the keyframes'
   transform and fling the moon into the corner. Sizing the box to the
   scene instead means scale() pivots on the centre for free. */
.sleep-moon {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--border-secondary);
    /* Much dimmer than when it stood alone: it is backdrop now, and the
       character is the subject. */
    opacity: 0.35;
    line-height: 0;
    /* Explicit 0 rather than relying on `auto`. The animation below runs
       on transform, which promotes this element to its own compositor
       layer; a sibling left at auto can end up drawn against that layer
       in the wrong order. Spelling both z-indexes out removes the
       ambiguity. */
    z-index: 0;
    animation: sleep-moon-breathe 6s ease-in-out infinite;
}
/* Compositor-only properties (opacity + transform), so this costs no
   main-thread style or layout work. Verified against the sleep trace:
   UpdateLayoutTree tracked mouse input, not this animation. */
@keyframes sleep-moon-breathe {
    0%, 100% { opacity: 0.30; transform: scale(1); }
    50%      { opacity: 0.45; transform: scale(1.04); }
}

/* Character on top, nudged 20px below the moon's centre so the seated
   poses settle into the crescent's cup instead of floating in it. */
.sleep-char {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(calc(-50% + 20px));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1;
    /* Force this onto its own compositor layer too. The moon is promoted
       by its animation, and an unpromoted sibling that should paint on
       top has to be promoted as well or it can be composited underneath.
       Cheap here: one static 192px layer that never repaints. */
    will-change: transform;
}
/* Equipped pet, standing beside the player. Its own canvas rather than a
   composite onto the pose above: CharacterBaker caches and hands out that
   exact canvas element keyed by appearance, so drawing anything extra onto
   it would poison the cache for every later sleep.

   Absolutely positioned rather than a flex sibling — .sleep-char centres
   its children, so a second in-flow child would shove the player off the
   moon's centre. top:0 + this canvas being the same height as the pose
   means both share one coordinate space, which is what the alignment math
   in SleepMode._drawPet assumes. Width and height are set inline from that
   same math; only the placement lives here. */
.sleep-pet-canvas {
    position: absolute;
    left: 50%;
    top: 0;
    transform: translateX(-50%);
    image-rendering: pixelated;
    pointer-events: none;
}

.sleep-char-canvas {
    width: 192px;
    height: 192px;
    image-rendering: pixelated;
    /* The sprite has soft alpha at its outline. With a lit backdrop
       directly behind it those edge pixels blend toward the moon, which
       reads as the moon bleeding over the character. An opaque-ish
       shadow under the sprite would fight the art, so instead keep the
       moon dim (above) and let the sprite sit at full strength. */
    opacity: 1;
}

.sleep-timer {
    font-family: "Cinzel", serif;
    font-size: 34px;
    color: var(--text-accent);
    opacity: 0.85;
    letter-spacing: 1px;
}

.sleep-note {
    font-family: var(--game-font, sans-serif);
    font-size: 15px;
    color: var(--text-muted);
    opacity: 0.75;
    max-width: 420px;
    text-align: center;
    line-height: 1.5;
}

/* Connection trouble while asleep. The normal reconnect overlay lives
   inside #ui-container and is therefore hidden, so this line is the
   only signal the player gets. */
.sleep-status {
    font-family: var(--game-font, sans-serif);
    font-size: 14px;
    color: var(--text-gold);
    opacity: 0.8;
    min-height: 18px;
}

/* Same backdrop recipe as .window-control-btn so the one interactive
   element on the screen matches the player's theme. */
/* "Still stuck?" line (StuckHint.js) under the loading status, the login
   version warning and the Update Required box. Muted, so it reads as the
   next thing to try rather than an error of its own. */
.stuck-hint { margin-top: 12px; font-family: var(--game-font, sans-serif); font-size: 14px; line-height: 1.5; color: var(--text-muted, #9a8f7a); text-align: center; max-width: 460px; margin-left: auto; margin-right: auto; }
.login-version-warning .stuck-hint { margin-top: 8px; font-size: 13px; }

/* Waking: the screen stays black while the wake resync runs (the night
   receipt may take over from it, frame-for-frame); the button is spent
   but stays visible so that hand-off shows no change. */
.sleep-overlay.waking .sleep-wake-btn { pointer-events: none; }
/* Leaving (SleepMode.finishWake): timer, note and button drop away first,
   then the character and moon lift out as the black fades. ~1.5 s, the
   window the world gets to draw underneath. */
.sleep-overlay.leaving { opacity: 0; pointer-events: none; transition: opacity .6s ease .8s; }
.sleep-overlay.leaving .sleep-timer, .sleep-overlay.leaving .sleep-note, .sleep-overlay.leaving .sleep-status, .sleep-overlay.leaving .sleep-wake-btn { opacity: 0; transform: translateY(14px); transition: opacity .45s ease, transform .45s ease; }
.sleep-overlay.leaving .sleep-scene { transform: translateY(-90px) scale(1.08); opacity: 0; transition: transform .8s ease-in .45s, opacity .7s ease .5s; }

.sleep-wake-btn {
    margin-top: 10px;
    padding: 10px 30px;
    font-family: "Cinzel", serif;
    font-size: 18px;
    color: var(--text-light);
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 5px;
    cursor: pointer;
    opacity: 0.9;
    transition: background 0.15s, color 0.15s, border-color 0.15s, opacity 0.15s;
}
.sleep-wake-btn:hover {
    background: var(--bg-hover);
    color: var(--text-bright);
    border-color: var(--border-secondary);
    opacity: 1;
}

/* Patch Notes button: standard 36x36 icon button. Inherits theming
   from .window-control-btn (theme vars in-game, login override under
   body.login-active). Pencil glyph is fill: currentColor so it picks
   up the same white-on-dark look as the other window-control icons. */

/* Tooltip variant for the How to Play button. Two colorways: the
   theme-styled in-game default (matches the rest of the UI) and a
   translucent-dark login override for the bright login background.
   Applied by TooltipManager when the local tooltip carries the
   .window-control-tooltip class. */
.global-tooltip.window-control-style {
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 8px 12px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.6);
    font-family: var(--game-font, sans-serif);
    color: var(--text-light);
}
.global-tooltip.window-control-style .tt-name {
    color: var(--text-gold);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.4px;
    text-shadow: none;
    margin-bottom: 4px;
}
.global-tooltip.window-control-style .tt-line {
    color: var(--text-light);
    font-size: 13px;
    text-shadow: none;
}
body.login-active .global-tooltip.window-control-style {
    background: rgba(20,16,28,0.92);
    border-color: rgba(255,255,255,0.22);
    color: rgba(255,255,255,0.85);
}
body.login-active .global-tooltip.window-control-style .tt-name {
    color: rgba(255,255,255,0.95);
}
body.login-active .global-tooltip.window-control-style .tt-line {
    color: rgba(220,220,235,0.78);
}

/* ── In-game top-left HUD ─────────────────────────────────────
   DOM replacement for the old canvas drawCanvasHUD block. Four
   lines: online count, player name, location, current state.
   Hidden while LoginScreen is up (body.login-active). */
.ingame-hud {
    position: absolute;
    top: 8px;
    left: 72px; /* clears the floating tab strip */
    pointer-events: none;
    font-family: var(--game-font);
    text-shadow: 1px 1px 0 #000;
    z-index: 80;
    user-select: none;
    /* Same backdrop recipe as .float-task-inner / .window-control-btn:
       solid theme bg + 2px primary border + small radius. */
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    padding: 8px 12px 6px;
}
body.login-active .ingame-hud {
    display: none;
}
.ingame-hud-row {
    line-height: 1.15;
    font-size: 20px;
    white-space: nowrap;
}
.ingame-hud-online {
    color: var(--text-success);
    /* Subtle divider between the player block (above) and the online
       breakdown (revealed below it). */
    padding-top: 4px;
    border-top: 1px solid var(--border-primary);
    margin-top: 6px;
}
/* The HUD is click-through (pointer-events: none on the container);
   re-enable it only on the two interactive disclosure targets. */
.ingame-hud-info,
.ingame-hud-online-total {
    pointer-events: auto;
    cursor: pointer;
}
/* Expand/collapse caret. Points right when collapsed, rotates down
   when its row is expanded. */
.ingame-hud-caret {
    display: inline-block;
    font-size: 12px;
    color: var(--text-dim);
    margin-right: 6px;
    vertical-align: middle;
    transition: transform 0.12s;
}
.ingame-hud-caret::before {
    content: '\25B6'; /* right triangle */
}
.ingame-hud-info.expanded .ingame-hud-caret,
.ingame-hud-online-total.expanded .ingame-hud-caret {
    transform: rotate(90deg);
}
.ingame-hud-sep {
    color: var(--text-dim);
    margin: 0 6px;
}
.ingame-hud-name {
    color: var(--text-gold);
    font-weight: 600;
}
.ingame-hud-state {
    color: var(--text-dim);
}
.ingame-hud-state.state-moving { color: var(--text-success); }
.ingame-hud-state.state-banking { color: var(--text-gold); }
.ingame-hud-state.state-acting { color: var(--text-light); }
.ingame-hud-state.state-combat { color: var(--text-bright); }

/* ── Game logo (top of screen) ────────────────────────────── */
.login-logo {
    display: block;
    width: 512px;
    height: 512px;
    object-fit: contain;
    image-rendering: -webkit-optimize-contrast;
    filter: drop-shadow(0 8px 32px rgba(0,0,0,0.65))
            drop-shadow(0 0 60px rgba(255,215,0,0.1));
    user-select: none;
}

/* Logo + release banner as one unit. .login-area is space-between, so
   these have to be a single child or the banner floats mid-screen. */
.login-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* ── Release date banner (login screen, under the logo) ──────
   Text comes from Constants.RELEASE_DATE_DISPLAY; the block is not
   rendered at all once the date has passed. */
.login-release {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: -8px 0 18px;
    padding: 8px 22px;
    background: rgba(0, 0, 0, 0.45);
    border: 1px solid rgba(255, 210, 74, 0.35);
    border-radius: 6px;
    user-select: none;
}

.login-release-label {
    font-size: 18px;
    color: #ffcc66;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    text-shadow: 1px 1px 0 #000;
}

.login-release-date {
    font-size: 24px;
    color: #ffd24a;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}

/* ── Login animations ──────────────────────────────────────── */
@keyframes loginFadeIn {
    from {
        opacity: 0;
        transform: translateY(12px) scale(0.97);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* ── "Did you know?" tip (shared by login + loading screens) ── */
.screen-tip {
    position: absolute;
    bottom: 53px;
    left: 0;
    right: 0;
    margin: 0 auto;
    width: fit-content;
    max-width: 1900px;
    text-align: center;
    font-size: 15px;
    color: rgba(255,255,255,0.55);
    font-family: var(--game-font);
    letter-spacing: 0.44px;
    line-height: 1.5;
    text-shadow: 0 1px 3px rgba(0,0,0,0.6);
    padding: 9px 26px;
    background: rgba(16,12,8,0.55);
    border: 1px solid rgba(200,168,62,0.1);
    border-radius: 22px;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    animation: loginFadeIn 0.8s ease-out 2.0s both;
    opacity: 0;
    transition: opacity 0.4s ease;
    z-index: 2;
    pointer-events: none;
}

/* ══════════════════════════════════════════════
   HISCORES TAB (Layer 15B)
   ══════════════════════════════════════════════ */

.hiscores-layout {
    display: flex;
    width: 100%;
    height: 100%;
    padding: 14px;
    gap: 10px;
    overflow: hidden;
}

/* ── LEFT: Categories ── */
.hs-categories {
    width: 230px;
    flex-shrink: 0;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 8px;
    overflow-y: auto;
}

.hs-cat-title {
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 8px;
    text-align: center;
}

.hs-cat-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 6px;
    margin: 1px 0;
    cursor: pointer;
    font-size: 18px;
    color: var(--text-light);
    border-radius: 3px;
    text-shadow: 1px 1px 0 #000;
    border: 1px solid transparent;
}
.hs-cat-item:hover { background: var(--bg-cell); }
.hs-cat-item.active {
    background: var(--bg-cell);
    color: var(--text-bright);
    border: 1px solid var(--border-primary);
}
.hs-cat-item img {
    width: 20px; height: 20px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.hs-cat-item.disabled {
    opacity: 0.35;
    cursor: default;
    pointer-events: none;
}

.hs-cat-divider {
    border: none;
    border-top: 1px solid var(--border-primary);
    margin: 6px 0;
}

/* ── CENTER: Leaderboard ── */
.hs-leaderboard {
    flex: 1;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 10px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

.hs-lb-title-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-bottom: 10px;
}
.hs-lb-title-row img {
    width: 28px; height: 28px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.hs-lb-title {
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

/* ── Table ── */
.hs-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 18px;
}
.hs-table th {
    background: var(--bg-cell);
    padding: 6px 8px;
    text-align: left;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    border-bottom: 2px solid var(--border-primary);
}
.hs-table td {
    padding: 5px 8px;
    border-bottom: 1px solid var(--bg-panel);
    color: var(--text-light);
}
.hs-table tr:hover { background: var(--bg-cell); }

.hs-table .rank-col { width: 60px; text-align: center; color: var(--text-dim); }
/* Name cell now hosts two spans: a fixed-width clan-tag prefix
   followed by the clickable player name. The cell itself is no
   longer the click target - the tag and name each handle their
   own clicks (tag → clan profile, name → player profile). */
.hs-table .name-col {
    color: var(--text-light);
    white-space: nowrap;
}
.hs-row-tag {
    display: inline-block;
    width: 5.5ch;
    color: var(--text-accent);
    font-weight: 600;
    text-align: left;
}
.hs-row-tag-clickable { cursor: pointer; }
.hs-row-tag-clickable:hover { text-decoration: underline; }
.hs-row-name {
    color: #5dade2;
    cursor: pointer;
}
.hs-row-name:hover { text-decoration: underline; }
.hs-table .level-col { text-align: center; color: var(--text-bright); }
.hs-table .xp-col { text-align: right; color: var(--text-light); }

.hs-own-row { background: #3a2a1a !important; }

/* ── Pagination ── */
.hs-pagination {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 14px;
    margin-top: 10px;
    font-size: 18px;
}
.hs-pagination button {
    padding: 4px 12px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 18px;
}
.hs-pagination button:hover { background: var(--bg-hover); color: var(--text-bright); }
.hs-pagination button:disabled { opacity: 0.3; cursor: default; }
.hs-pagination button:disabled:hover { background: var(--bg-cell); color: var(--text-light); }
.hs-pagination span { color: var(--text-dim); }

/* ── RIGHT: Controls ── */
.hs-controls {
    width: 190px;
    flex-shrink: 0;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.hs-search-section label {
    display: block;
    font-size: 18px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
}

.hs-search-input {
    width: 100%;
    padding: 4px 6px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 18px;
    margin-bottom: 4px;
    outline: none;
}
.hs-search-input:focus { border-color: var(--text-accent); }

.hs-search-btn {
    width: 100%;
    padding: 5px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 18px;
}
.hs-search-btn:hover { background: var(--bg-hover); color: var(--text-bright); }

.hs-your-rank-btn {
    width: 100%;
    padding: 8px;
    background: var(--text-accent);
    border: none;
    border-radius: 3px;
    color: var(--bg-dark);
    font-weight: bold;
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 20px;
    text-shadow: none;
}
.hs-your-rank-btn:hover { background: #dabb4e; }

/* ── Player profile view ── */
.hs-profile-skill-cell {
    display: flex;
    align-items: center;
    gap: 8px;
}
.hs-profile-skill-cell img {
    width: 20px; height: 20px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.hs-profile-skill-link {
    color: #5dade2;
    cursor: pointer;
}
.hs-profile-skill-link:hover {
    text-decoration: underline;
}

.hs-back-btn {
    margin-top: 14px;
    padding: 8px 18px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 20px;
}
.hs-back-btn:hover { background: var(--bg-hover); color: var(--text-bright); }

/* ── Scrollbar styling ── */
.hs-categories::-webkit-scrollbar,
.hs-leaderboard::-webkit-scrollbar {
    width: 8px;
}
.hs-categories::-webkit-scrollbar-track,
.hs-leaderboard::-webkit-scrollbar-track {
    background: var(--bg-dark);
}
.hs-categories::-webkit-scrollbar-thumb,
.hs-leaderboard::-webkit-scrollbar-thumb {
    background: var(--border-primary);
    border-radius: 4px;
}

.hs-loading {
    text-align: center;
    color: var(--text-dim);
    font-size: 20px;
    padding: 40px 0;
}

.hs-no-results {
    text-align: center;
    color: var(--text-muted);
    font-size: 18px;
    padding: 20px 0;
}

/* ══════════════════════════════════════════════
   LOADING SCREEN (Layer 17A)
   ══════════════════════════════════════════════ */

.loading-screen {
    position: absolute;
    inset: 0;
    z-index: 4000;
    display: flex;
    flex-direction: column;
    /* Top-align the logo to match .login-area's padding-top so the
       image lands at the same pixel position when transitioning to
       the login screen. */
    align-items: center;
    padding-top: 100px;
    box-sizing: border-box;
    background-color: #0a0a1a;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    font-family: var(--game-font);
}

.loading-bottom {
    position: absolute;
    /* Sit well above the .screen-tip pill (which is anchored at
       bottom: 53px). The previous bottom: 60px caused the rounded
       tip pill to poke out behind the progress bar as the "notch". */
    bottom: 130px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.loading-bar-track {
    width: 420px;
    height: 18px;
    background: #2a2a3e;
    border: 2px solid #3a3a4e;
    border-radius: 4px;
    overflow: hidden;
}

.loading-bar-fill {
    height: 100%;
    width: 0%;
    background: var(--text-gold);
    border-radius: 2px;
    transition: width 0.15s ease-out;
}

.loading-status {
    font-size: 20px;
    color: var(--text-dim);
    text-shadow: 1px 1px 0 #000, 0 0 4px rgba(0,0,0,0.8);
    letter-spacing: 0.5px;
}

/* ═══════════════════════════════════════════════════════════════
   Settings Modal (Tab 7)
   ═══════════════════════════════════════════════════════════════ */

#tab-settings {
    flex-wrap: wrap;
    align-content: flex-start;
    justify-content: center;
    gap: 0 20px;
    padding: 10px;
}

.settings-section {
    width: 640px;
    margin-bottom: 28px;
    padding: 40px;
}

/* Sticky search bar at the top of the settings tab body. Pulled out
   of the header nav so it stays in view no matter how many section
   buttons wrap into the header strip above. */
.settings-search-bar {
    position: sticky;
    top: -12px;
    z-index: 5;
    width: 100%;
    padding: 8px 10px;
    background: var(--bg-dark);
    border-bottom: 1px solid var(--border-primary);
    margin: -10px -10px 10px;
    /* Flex row so the language picker sits BESIDE the search field and
       shares its baseline. Without this the picker is an inline element
       and .settings-search-wrap is a block, so the picker stacked above
       the field instead of sitting to its left. */
    display: flex;
    align-items: center;
    gap: 8px;
}
.settings-search-wrap {
    display: flex;
    align-items: center;
    position: relative;
    max-width: 640px;
    margin: 0 auto;
    /* Take the space the picker leaves; the auto margins above still
       centre it within that space. */
    flex: 1;
}
.settings-search-input {
    flex: 1;
    background: var(--bg-panel);
    border: 1px solid #444;
    color: var(--text-bright);
    padding: 6px 28px 6px 10px;
    border-radius: 4px;
    font-size: 13px;
    font-family: inherit;
    outline: none;
}
.settings-search-input:focus {
    border-color: var(--text-gold);
}
.settings-search-input::placeholder {
    color: var(--text-dim);
}
.settings-search-clear {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-dim);
    cursor: pointer;
    font-size: 14px;
    padding: 0 4px;
    user-select: none;
}
.settings-search-clear:hover { color: var(--text-bright); }

.settings-header-nav {
    display: flex;
    gap: 4px;
    flex: 1;
    justify-content: center;
    flex-wrap: wrap;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
}

.settings-nav-btn {
    background: var(--bg-panel);
    border: 1px solid #444;
    color: var(--text-dim);
    padding: 4px 10px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 18px;
    font-family: inherit;
    transition: border-color 0.15s, color 0.15s;
}

.settings-nav-btn:hover {
    border-color: var(--text-gold);
    color: var(--text-gold);
}

.settings-section-header {
    font-size: 30px;
    color: var(--text-gold);
    text-shadow: 1px 1px 0 #000;
    border-bottom: 1px solid #333;
    padding-bottom: 6px;
    margin-bottom: 14px;
    letter-spacing: 1px;
}

.settings-subheading {
    font-size: 30px;
    color: var(--text-dim);
    margin-top: 10px;
    margin-bottom: 6px;
    letter-spacing: 0.5px;
}

.settings-icon-size-control {
    display: flex;
    gap: 6px;
    align-items: center;
}

.settings-icon-size-btn {
    background: #222;
    border: 1px solid #444;
    color: var(--text-dim);
    padding: 4px 10px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 13px;
    font-family: inherit;
    transition: border-color 0.15s, color 0.15s;
}

.settings-icon-size-btn:hover {
    border-color: var(--text-dark);
    color: #CCC;
}

.settings-icon-size-btn.active {
    border-color: var(--text-gold);
    color: var(--text-gold);
}

.settings-icon-size-btn.disabled,
.settings-icon-size-btn:disabled {
    opacity: 0.35;
    cursor: not-allowed;
    pointer-events: none;
}

.settings-color-picker {
    width: 40px;
    height: 30px;
    border: 1px solid #444;
    border-radius: 4px;
    background: #222;
    cursor: pointer;
    padding: 2px;
    flex-shrink: 0;
}

.settings-color-picker::-webkit-color-swatch-wrapper {
    padding: 0;
}

.settings-color-picker::-webkit-color-swatch {
    border: none;
    border-radius: 2px;
}

.settings-theme-select {
    background: var(--bg-cell);
    color: var(--text-bright);
    border: 1px solid var(--border-primary);
    padding: 6px 10px;
    font-family: var(--game-font);
    font-size: 20px;
    cursor: pointer;
    outline: none;
}
.settings-theme-select:hover {
    border-color: var(--text-accent);
}
.settings-theme-select option {
    background: var(--bg-panel);
    color: var(--text-light);
}

/* Account info */
.settings-account-info {
    margin-bottom: 14px;
}

.settings-account-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 0;
}

.settings-account-label {
    font-size: 18px;
    color: var(--text-dim);
}

.settings-account-value {
    font-size: 18px;
    color: #ddd;
}

.settings-total-level {
    color: var(--text-gold);
}

/* Build section: server/client version mismatch styling. Yellow values
   plus a yellow warning row mirror the login screen's treatment. */
.settings-account-value.mismatch {
    color: #f5c542;
}
.settings-version-warning {
    margin-top: 10px;
    padding: 8px 10px;
    border-left: 3px solid #f5c542;
    background: rgba(245, 197, 66, 0.08);
    color: #f5c542;
    font-size: 14px;
    line-height: 1.4;
}
.settings-version-warning-btn {
    margin-top: 6px;
    background: rgba(245, 197, 66, 0.12);
    border: 1px solid #f5c542;
    color: #f5c542;
    font-family: inherit;
    font-size: 13px;
    padding: 5px 12px;
    border-radius: 3px;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 1px;
}
.settings-version-warning-btn:hover {
    background: rgba(245, 197, 66, 0.22);
}

.settings-account-checkbox {
    width: 20px;
    height: 20px;
    cursor: pointer;
    accent-color: var(--text-gold);
}

/* Logout button */
.settings-logout-btn {
    display: block;
    background: #8B0000;
    color: #fff;
    border: 1px solid #a33;
    border-radius: 4px;
    padding: 8px 24px;
    font-family: var(--game-font);
    font-size: 20px;
    cursor: pointer;
    letter-spacing: 1px;
    transition: background 0.15s;
    /* Stacks each button onto its own row instead of inline with the
       next one. Margin-bottom gives the stack breathing room without
       needing a wrapper element per button. */
    margin-bottom: 10px;
}

.settings-logout-btn:hover {
    background: #a30000;
}

.settings-reset-btn {
    display: block;
    background: #333;
    color: var(--text-dim);
    border: 1px solid var(--text-disabled);
    border-radius: 4px;
    padding: 8px 24px;
    font-family: var(--game-font);
    font-size: 20px;
    cursor: pointer;
    letter-spacing: 0.5px;
    transition: background 0.15s, color 0.15s;
    /* On its own row beneath the logout button. */
    margin-bottom: 10px;
}

.settings-reset-btn:hover {
    background: #444;
    color: var(--text-gold);
}

/* Toggle rows */
.settings-toggle-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 0;
    border-bottom: 1px solid #222;
}

.settings-toggle-text {
    flex: 1;
    margin-right: 16px;
}

.settings-toggle-label {
    font-size: 18px;
    color: #ddd;
}

.settings-toggle-desc {
    font-size: 14px;
    color: var(--text-muted);
    margin-top: 2px;
}

/* CSS-only toggle switch */
.settings-switch {
    width: 44px;
    height: 24px;
    background: #333;
    border-radius: 12px;
    cursor: pointer;
    position: relative;
    flex-shrink: 0;
    transition: background 0.2s;
    border: 1px solid var(--text-disabled);
}

.settings-switch.on {
    background: #5a4a00;
    border-color: var(--text-gold);
}

.settings-switch-knob {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--text-muted);
    position: absolute;
    top: 2px;
    left: 2px;
    transition: left 0.2s, background 0.2s;
}

.settings-switch.on .settings-switch-knob {
    left: 22px;
    background: var(--text-gold);
}

/* Map quality slider */
.settings-quality-control {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

.settings-quality-slider {
    -webkit-appearance: none;
    appearance: none;
    width: 140px;
    height: 6px;
    border-radius: 3px;
    background: #333;
    outline: none;
    cursor: pointer;
}

.settings-quality-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--text-gold);
    cursor: pointer;
    border: 2px solid #5a4a00;
}

.settings-quality-slider::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--text-gold);
    cursor: pointer;
    border: 2px solid #5a4a00;
}

.settings-quality-badge {
    min-width: 28px;
    height: 28px;
    line-height: 28px;
    text-align: center;
    background: #5a4a00;
    border: 1px solid var(--text-gold);
    border-radius: 4px;
    color: var(--text-gold);
    font-size: 18px;
    font-family: var(--game-font);
    cursor: default;
    position: relative;
}

/* ── Audio section ──
   One row per sound: label, a play button to audition it, and its
   switch. The play button matches the quality badge so the right-hand
   column lines up with the sliders above it. */
.settings-sound-controls {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

.settings-sound-preview {
    width: 28px;
    height: 28px;
    line-height: 26px;
    padding: 0;
    text-align: center;
    background: #2a2a2a;
    border: 1px solid var(--text-disabled);
    border-radius: 4px;
    color: var(--text-muted);
    font-size: 13px;
    font-family: var(--game-font);
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.settings-sound-preview:hover {
    background: #5a4a00;
    border-color: var(--text-gold);
    color: var(--text-gold);
}

.settings-sound-preview:active {
    background: #7a6400;
}

.settings-audio-blurb {
    font-size: 14px;
    color: var(--text-muted);
    padding: 4px 0 8px;
}

/* Global / Music / Sounds: one slider per row, each about half the row. */
.settings-volume-control {
    flex: 0 0 50%;
    max-width: 50%;
}

.settings-volume-slider {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
}

.settings-audio-unsupported {
    font-size: 14px;
    color: var(--text-warn, #e0a050);
    padding: 4px 0 8px;
}

/* Credits list — used in Settings → Credits section and in the
   LPC-credit popup launched from the Customize modal header. */
.settings-credits-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 4px 0;
}
.credits-entry {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.credits-title {
    font-size: 13px;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 600;
}
.credits-body {
    font-size: 14px;
    color: var(--text-bright);
    line-height: 1.45;
}
.credits-links {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
    margin-top: 3px;
}
/* Classic click-here blue link styling so credit URLs read as
   obvious hyperlinks rather than the gold text-accent we use
   elsewhere in chrome. */
.credits-link {
    font-size: 13px;
    color: #6ea8ff;
    text-decoration: underline;
}
.credits-link:hover { color: #9bc4ff; }
.credits-link:visited { color: #b389ff; }

/* ══════════════════════════════════════════════
   CHARACTER CREATOR (Layer 18A)
   ══════════════════════════════════════════════ */

.character-creator.creator-layout {
    flex: 1;
    display: flex;
    overflow: hidden;
}

/* ── Category Sidebar ── */
.character-creator .creator-sidebar {
    width: 78px;
    flex-shrink: 0;
    background: var(--bg-dark);
    border-left: 2px solid var(--border-primary);
    border-right: 2px solid var(--border-primary);
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 6px 0;
    overflow-y: auto;
}

.character-creator .cat-btn {
    width: 72px;
    height: 56px;
    background: var(--bg-panel);
    border: none;
    border-left: 3px solid transparent;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    color: var(--text-muted);
    transition: all .15s;
    position: relative;
    font-family: var(--game-font);
}
.character-creator .cat-btn:hover { background: var(--bg-cell); color: var(--text-light); }
.character-creator .cat-btn.active { background: var(--bg-cell); border-left: 3px solid var(--text-accent); color: var(--text-bright); }
.character-creator .cat-btn .icon { font-size: 22px; }
.character-creator .cat-btn .lbl { font-size: 15px; line-height: 1; text-shadow: 1px 1px 0 #000; }
.character-creator .cat-btn .dot {
    position: absolute;
    top: 5px;
    right: 7px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--text-accent);
}
.character-creator .cat-btn .cat-tooltip {
    display: none;
    position: absolute;
    left: calc(100% + 8px);
    top: 50%;
    transform: translateY(-50%);
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 4px 10px;
    white-space: nowrap;
    pointer-events: none;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    box-shadow: 0 2px 8px rgba(0,0,0,0.8);
    z-index: 100;
}
.character-creator .cat-btn:hover .cat-tooltip { display: block; }

/* ── Center: Slots Area ── */
.character-creator .creator-center {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    min-width: 0;
}

.character-creator .cc-slots-area {
    flex: 1;
    overflow-y: auto;
    padding: 12px 16px;
}

.character-creator .cc-slot-group {
    margin-bottom: 12px;
}

.character-creator .cc-slot-label {
    font-size: 20px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
    text-transform: uppercase;
    letter-spacing: .5px;
}

.character-creator .cc-slot-row {
    display: flex;
    gap: 6px;
    align-items: center;
    margin-bottom: 2px;
}

.character-creator .cc-slot-row select {
    flex: 1;
    min-width: 100px;
    background: var(--bg-dark);
    color: var(--text-bright);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 5px 8px;
    font-family: var(--game-font);
    font-size: 20px;
    cursor: pointer;
    outline: none;
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-slot-row select:hover,
.character-creator .cc-slot-row select:focus { border-color: var(--text-accent); }

/* ── Prev/next arrows beside the slot + variant dropdowns ── */
.character-creator .cc-slot-arrow {
    flex-shrink: 0;
    padding: 4px 10px;
    font-size: 20px;
    line-height: 1;
    border-radius: 3px;
    cursor: pointer;
    background: var(--bg-panel);
    color: var(--text-muted);
    border: 1px solid var(--border-primary);
    font-family: var(--game-font);
    text-shadow: 1px 1px 0 #000;
    transition: all .1s;
}
.character-creator .cc-slot-arrow:hover {
    background: var(--bg-cell);
    color: var(--text-light);
    border-color: var(--text-accent);
}

/* ── Chat Badge picker ───────────────────────────────────────── */
.character-creator .cc-badge-intro {
    font-size: 18px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 10px;
    line-height: 1.3;
}
/* Collapsible category header */
.character-creator .cc-badge-cat-header {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 10px 0 4px;
    padding: 4px 6px;
    cursor: pointer;
    border-bottom: 1px solid var(--border-primary);
    user-select: none;
}
.character-creator .cc-badge-cat-header:hover { border-color: var(--text-accent); }
.character-creator .cc-badge-cat-chevron {
    font-size: 14px;
    color: var(--text-accent);
    width: 14px;
    flex: 0 0 auto;
}
.character-creator .cc-badge-cat-title {
    font-size: 20px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    text-transform: uppercase;
    letter-spacing: .5px;
}
.character-creator .cc-badge-cat-body { margin-bottom: 6px; }

.character-creator .cc-badge-row {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 4px;
    padding: 4px 6px;
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    background: var(--bg-dark);
}
/* Name label sits on the LEFT, fixed width; icon then dropdown follow. */
.character-creator .cc-badge-row .cc-badge-name {
    flex: 0 0 200px;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* No-badge row: let the label flex so the Clear/Selected button hugs the right. */
.character-creator .cc-badge-none .cc-badge-name { flex: 1 1 auto; }

/* Creator badge rows: handle input + Save + Show buttons. */
.character-creator .cc-creator-input {
    flex: 1;
    min-width: 100px;
    background: var(--bg-darker, var(--bg-darkest));
    color: var(--text-bright);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 5px 8px;
    font-family: var(--game-font);
    font-size: 18px;
    outline: none;
}
.character-creator .cc-creator-input:focus { border-color: var(--text-accent); }
.character-creator .cc-creator-btn {
    flex: 0 0 auto;
    background: var(--bg-darker, var(--bg-darkest));
    color: var(--text-light);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 5px 12px;
    font-family: var(--game-font);
    font-size: 18px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-creator-btn:hover:not(:disabled) { border-color: var(--text-accent); }
.character-creator .cc-creator-btn:disabled { opacity: 0.5; cursor: default; }
.character-creator .cc-creator-btn.active { border-color: var(--text-accent); color: var(--text-bright); }
.character-creator .cc-creator-error {
    font-size: 16px;
    color: #ff6b6b;
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 8px;
}

/* Clickable creator chat badge + leave-the-game confirm. */
.chat-staff-crown-wrap.chat-staff-crown-link { cursor: pointer; }
.chat-extlink-overlay {
    position: absolute;
    inset: 0;
    z-index: 3500;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.6);
}
.chat-extlink-box {
    background: var(--bg-panel, #20232a);
    border: 2px solid var(--border-secondary, var(--border-primary));
    border-radius: 8px;
    padding: 20px 24px;
    max-width: 520px;
    text-align: center;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
}
.chat-extlink-title {
    font-size: 26px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 10px;
}
.chat-extlink-msg {
    font-size: 20px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    line-height: 1.35;
    margin-bottom: 10px;
}
.chat-extlink-url {
    font-size: 16px;
    color: var(--text-accent);
    word-break: break-all;
    margin-bottom: 16px;
}
.chat-extlink-btns { display: flex; gap: 12px; justify-content: center; }
.chat-extlink-btn {
    background: var(--bg-darker, var(--bg-darkest));
    color: var(--text-light);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 8px 20px;
    font-family: var(--game-font);
    font-size: 20px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
}
.chat-extlink-btn:hover { border-color: var(--text-accent); }
.chat-extlink-btn-go { border-color: var(--text-accent); color: var(--text-bright); }
.character-creator .cc-badge-row.active {
    border-color: var(--text-accent);
    box-shadow: inset 0 0 0 1px var(--text-accent);
}
.character-creator .cc-badge-row.cc-badge-locked {
    opacity: 0.45;
}
.character-creator .cc-badge-icon {
    width: 32px;
    height: 32px;
    object-fit: contain;
    image-rendering: pixelated;
    flex: 0 0 auto;
}
.character-creator .cc-badge-row.cc-badge-locked .cc-badge-icon {
    filter: grayscale(1);
}
.character-creator .cc-badge-name {
    flex: 1;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-badge-lock-hint {
    flex: 1;
    font-size: 16px;
    color: var(--text-muted, #888);
    text-shadow: 1px 1px 0 #000;
    text-align: right;
}
.character-creator .cc-badge-select {
    flex: 1;
    min-width: 120px;
    background: var(--bg-darker, var(--bg-darkest));
    color: var(--text-bright);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 5px 8px;
    font-family: var(--game-font);
    font-size: 20px;
    cursor: pointer;
    outline: none;
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-badge-select:hover,
.character-creator .cc-badge-select:focus { border-color: var(--text-accent); }
.character-creator .cc-badge-none-btn {
    background: var(--bg-darker, var(--bg-darkest));
    color: var(--text-light);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 5px 12px;
    font-family: var(--game-font);
    font-size: 18px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-badge-none-btn:hover:not(:disabled) { border-color: var(--text-accent); }
.character-creator .cc-badge-none-btn:disabled { opacity: 0.5; cursor: default; }

.character-creator .cc-slot-clear {
    background: none;
    border: 1px solid transparent;
    color: var(--border-primary);
    cursor: pointer;
    font-size: 22px;
    padding: 2px 6px;
    border-radius: 3px;
    font-family: var(--game-font);
}
.character-creator .cc-slot-clear:hover { color: #ff0000; background: rgba(255,0,0,.1); border-color: var(--border-primary); }

/* ── Variant (2nd) Dropdown Row ── */
.character-creator .cc-variant-row {
    display: flex;
    gap: 6px;
    align-items: center;
    margin-top: 2px;
}

.character-creator .cc-variant-row select {
    flex: 1;
    min-width: 100px;
    background: var(--bg-dark);
    color: var(--text-light);
    border: 1px solid var(--bg-cell);
    border-radius: 3px;
    padding: 5px 8px;
    font-family: var(--game-font);
    font-size: 18px;
    cursor: pointer;
    outline: none;
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-variant-row select:hover,
.character-creator .cc-variant-row select:focus { border-color: var(--text-accent); color: var(--text-bright); }

.character-creator .cc-variant-label {
    font-size: 16px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    min-width: 56px;
    flex-shrink: 0;
}

/* ── Preview Panel (Left) ── */
.character-creator .creator-preview {
    width: 240px;
    flex-shrink: 0;
    background: var(--bg-dark);
    border-right: 2px solid var(--border-primary);
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 16px;
    gap: 12px;
}

.character-creator .creator-preview h3 {
    font-size: 26px;
    font-weight: normal;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
}

.character-creator .cc-canvas-wrap {
    background: var(--border-primary);
    border-radius: 4px;
    border: 2px solid var(--border-primary);
    image-rendering: pixelated;
    overflow: hidden;
}

/* ── Direction Buttons ── */
.character-creator .cc-dir-btns {
    display: flex;
    gap: 4px;
}
.character-creator .cc-dir-btns button {
    padding: 5px 14px;
    font-size: 22px;
    border-radius: 3px;
    cursor: pointer;
    background: var(--bg-panel);
    color: var(--text-muted);
    border: 1px solid var(--border-primary);
    font-family: var(--game-font);
    text-shadow: 1px 1px 0 #000;
    transition: all .1s;
}
.character-creator .cc-dir-btns button:hover { background: var(--bg-cell); color: var(--text-light); border-color: var(--text-accent); }
.character-creator .cc-dir-btns button.active { background: var(--bg-cell); color: var(--text-bright); border-color: var(--text-accent); }

/* ── Play Button ── */
.character-creator .cc-play-btn {
    padding: 6px 16px;
    font-size: 20px;
    border-radius: 3px;
    cursor: pointer;
    background: var(--bg-panel);
    color: var(--text-light);
    border: 1px solid var(--border-primary);
    font-family: var(--game-font);
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-play-btn:hover { background: var(--bg-cell); border-color: var(--text-accent); color: var(--text-bright); }

/* ── Save Button ── */
.character-creator .cc-save-area {
    border-top: 1px solid var(--border-primary);
    width: 100%;
    padding-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.character-creator .cc-save-btn {
    width: 100%;
    padding: 14px;
    font-size: 30px;
    font-weight: normal;
    border-radius: 4px;
    cursor: pointer;
    border: 2px solid #6a8a3a;
    font-family: var(--game-font);
    text-shadow: 2px 2px 0 #000;
    background: linear-gradient(180deg, #4a6a2a 0%, #3a5a1a 100%);
    color: var(--text-bright);
    transition: all .15s;
    text-align: center;
}
.character-creator .cc-save-btn:hover { background: linear-gradient(180deg, #5a7a3a 0%, #4a6a2a 100%); border-color: #8aaa5a; }
.character-creator .cc-save-btn:active { background: linear-gradient(180deg, #3a5a1a 0%, #2a4a0a 100%); }

/* ── Layers Summary ── */
.character-creator .cc-layers-summary {
    border-top: 1px solid var(--border-primary);
    width: 100%;
    padding-top: 8px;
    max-height: 332px;
    overflow-y: auto;
}

.character-creator .cc-ls-title {
    font-size: 18px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
}

.character-creator .cc-ls-row {
    font-size: 16px;
    color: var(--text-muted);
    padding: 2px 0;
    display: flex;
    gap: 4px;
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-ls-row .z { color: var(--text-accent); min-width: 32px; text-align: right; }

.character-creator .cc-loading-msg {
    color: var(--border-primary);
    font-size: 22px;
    padding: 8px 0;
    text-shadow: 1px 1px 0 #000;
}

/* ── Sleep pose picker (Customize > Sleep) ──
   Three static previews rendered from the player's live selections, so
   an outfit that loses layers in a sitting pose shows that here rather
   than surprising them on the sleep screen. */
.character-creator .cc-sleep-picker {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 8px 0;
}
.character-creator .cc-sleep-blurb {
    color: var(--text-light);
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-sleep-note {
    color: var(--text-muted);
    font-size: 15px;
    line-height: 1.4;
    max-width: 560px;
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-sleep-row {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
}
.character-creator .cc-sleep-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 8px 10px 6px;
    background: var(--bg-cell);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}
.character-creator .cc-sleep-tile:hover {
    background: var(--bg-hover);
    border-color: var(--border-secondary);
}
.character-creator .cc-sleep-tile.active {
    border-color: var(--text-gold);
    background: var(--bg-hover);
}
.character-creator .cc-sleep-canvas {
    width: 128px;
    height: 128px;
    image-rendering: pixelated;
}
.character-creator .cc-sleep-label {
    color: var(--text-light);
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
}
.character-creator .cc-sleep-tile.active .cc-sleep-label { color: var(--text-gold); }

/* ── Actions picker: one row of tiles per skill group ── */
/* Three rows of full-size tiles would push the last one off the panel,
   so the action tiles are smaller than the single-row sleep ones. */
.character-creator .cc-anim-canvas {
    width: 96px;
    height: 96px;
}
.character-creator .cc-anim-row {
    gap: 10px;
    margin-bottom: 2px;
}
.character-creator .cc-anim-group {
    display: flex;
    align-items: center;
    gap: 4px;
    color: var(--text-light);
    font-size: 17px;
    text-shadow: 1px 1px 0 #000;
    margin-top: 4px;
}
/* A little air between the group name and the run of skill icons. */
.character-creator .cc-anim-group-name {
    margin-right: 4px;
}
/* Divider inside an unlock tooltip: separates the total, the source
   breakdown and the potion lines without a heading to translate. */
/* The one line a movement-speed cell stands for, plus its title. Both
   take the same accent so four identical tooltips still say which cell
   you are on. */
.unlock-tooltip-accent {
    color: var(--text-gold);
}

.unlock-tooltip-divider {
    height: 1px;
    margin: 7px 0 3px;
    background: var(--border-primary);
    opacity: 0.7;
}

.character-creator .cc-anim-group-icon {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
    /* One skill without an icon must not leave a gap the others line up
       around, so a broken image collapses instead of reserving space. */
    max-width: 20px;
}
/* The group whose choice the big preview is currently running. */
.character-creator .cc-anim-group.focused {
    color: var(--text-gold);
}

/* ── Body Type Select (in header) ── */
.cc-header-controls {
    display: flex;
    align-items: center;
    gap: 10px;
}

.cc-header-controls label {
    font-size: 22px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
}

.cc-body-select {
    background: var(--bg-dark);
    color: var(--text-bright);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 4px 8px;
    font-family: var(--game-font);
    font-size: 22px;
    cursor: pointer;
    outline: none;
    text-shadow: 1px 1px 0 #000;
}
.cc-body-select:hover,
.cc-body-select:focus { border-color: var(--text-accent); }

/* Outfit presets — sits left of the Body select in the Customize
   header. Save/load/delete looks stored in localStorage. */
.cc-outfit-controls {
    display: flex;
    align-items: center;
    gap: 6px;
}

.cc-outfit-select {
    background: var(--bg-dark);
    color: var(--text-bright);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 4px 8px;
    font-family: var(--game-font);
    font-size: 22px;
    cursor: pointer;
    outline: none;
    text-shadow: 1px 1px 0 #000;
    max-width: 200px;
}
.cc-outfit-select:hover,
.cc-outfit-select:focus { border-color: var(--text-accent); }

.cc-outfit-btn {
    background: var(--bg-dark);
    color: var(--text-bright);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 4px 8px;
    font-family: var(--game-font);
    font-size: 18px;
    cursor: pointer;
    outline: none;
    line-height: 1;
}
.cc-outfit-btn:hover { border-color: var(--text-accent); }

/* LPC credit link in the Customize header — small underlined text
   that opens the credits popup. Required by the LPC license. */
.cc-lpc-credit {
    font-size: 16px;
    color: var(--text-accent);
    text-decoration: underline;
    cursor: pointer;
    margin-left: 12px;
    text-shadow: 1px 1px 0 #000;
}
.cc-lpc-credit:hover { filter: brightness(1.2); }

/* Credits popup launched from the Customize modal. Floats over the
   active modal; reuses the Settings credits-list layout for the body.
   z-index 2000 keeps it above the modal container's overlay. */
.cc-credits-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.65);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2000;
}
.cc-credits-dialog {
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 6px;
    width: 560px;
    max-width: calc(100% - 40px);
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
}
.cc-credits-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border-primary);
}
.cc-credits-title {
    font-size: 18px;
    color: var(--text-accent);
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
}
.cc-credits-close {
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-dim);
    cursor: pointer;
    font-size: 18px;
}
.cc-credits-close:hover { color: var(--text-bright); }
.cc-credits-body {
    padding: 16px 18px;
    overflow-y: auto;
}

/* ── Gear Calc in-game modal (iframe wrapper) ── */
/* Sized in the logical 1920x1080 coordinate space, NOT viewport units.
   #ui-container is fixed at 1920x1080 and CSS-transformed to fit the
   viewport, so a vw/vh-sized modal would jump out of the scaled area
   on non-16:9 windows. Matching the Group of Modals pattern keeps the
   calc inside the playable area at every aspect ratio. */
.gc-modal-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 1920px;
    height: 1080px;
    background: rgba(0, 0, 0, 0.65);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2200;
}
.gc-modal-dialog {
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 6px;
    width: 1820px;
    height: 1000px;
    display: flex;
    flex-direction: column;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
    overflow: hidden;
}
.gc-modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 16px;
    border-bottom: 1px solid var(--border-primary);
    flex: 0 0 auto;
}
.gc-modal-title {
    font-size: 18px;
    color: var(--text-accent);
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
}
.gc-modal-close {
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-dim);
    cursor: pointer;
    font-size: 20px;
    border-radius: 4px;
}
.gc-modal-close:hover { color: var(--text-bright); background: rgba(255, 255, 255, 0.05); }
.gc-modal-body {
    flex: 1 1 auto;
    overflow: hidden;
    background: var(--bg-dark);
}
.gc-modal-iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
    background: var(--bg-dark);
}

/* ── Scrollbars (game style) ── */
.character-creator .cc-slots-area::-webkit-scrollbar,
.character-creator .cc-layers-summary::-webkit-scrollbar,
.character-creator .creator-sidebar::-webkit-scrollbar { width: 8px; }
.character-creator .cc-slots-area::-webkit-scrollbar-track,
.character-creator .cc-layers-summary::-webkit-scrollbar-track,
.character-creator .creator-sidebar::-webkit-scrollbar-track { background: var(--bg-dark); }
.character-creator .cc-slots-area::-webkit-scrollbar-thumb,
.character-creator .cc-layers-summary::-webkit-scrollbar-thumb,
.character-creator .creator-sidebar::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }

/* ═══════════════════════════════════════════════════════════════
   Slay Masters Tab (Phase 4)
   ═══════════════════════════════════════════════════════════════ */

#tab-slay { flex-direction: column; }

/* ── Info Bar (current task + slay stats) ── */
.slay-info-bar {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 8px 14px;
    background: var(--bg-panel);
    border-bottom: 2px solid var(--border-primary);
    flex-shrink: 0;
    height: 64px;
}

.slay-current-task {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 12px;
}

.slay-current-task .task-label {
    font-size: 20px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
}

.slay-current-task .task-name {
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

.task-progress {
    display: flex;
    align-items: center;
    gap: 8px;
}

.task-progress-bar {
    width: 200px;
    height: 18px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    overflow: hidden;
}

.task-progress-fill {
    height: 100%;
    background: linear-gradient(180deg, #4caf50 0%, #2e7d32 100%);
    transition: width 0.3s;
}

.task-progress-text {
    font-size: 20px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
}

.slay-stats {
    display: flex;
    align-items: center;
    gap: 16px;
}

.auto-slay-btn {
    height: 38px;
    font-family: var(--game-font);
    font-size: 20px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
    min-width: 160px;
    text-align: center;
}
.auto-slay-btn:hover { background: var(--bg-cell); color: var(--text-light); border-color: var(--text-accent); }
.auto-slay-btn.active { color: var(--text-bright); border-color: var(--text-accent); background: var(--bg-cell); }

.skip-task-btn {
    padding: 6px 20px;
    font-family: var(--game-font);
    font-size: 20px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
    min-width: 160px;
    text-align: center;
}
.skip-task-btn:hover { border-color: var(--text-accent); color: var(--text-bright); }

/* ── Unlocks Bar ── */
.slay-unlocks-bar {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 6px 14px;
    background: var(--bg-dark);
    border-bottom: 1px solid var(--border-primary);
    flex-shrink: 0;
    font-size: 18px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
}

.unlock-item { display: flex; align-items: center; gap: 6px; }
.unlock-item .val { color: var(--text-gold); }

/* ── Tier Rows Container ── */
.slay-tiers-container {
    flex: 1;
    overflow-y: auto;
    padding: 0;
}

.slay-tiers-container::-webkit-scrollbar { width: 8px; }
.slay-tiers-container::-webkit-scrollbar-track { background: var(--bg-dark); }
.slay-tiers-container::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }

/* ── Single Tier Row ── */
.tier-row {
    display: flex;
    align-items: stretch;
    border-bottom: 2px solid var(--border-primary);
    min-height: 220px;
}
.tier-row:last-child { border-bottom: none; }

/* ── Master Panel ── */
.master-panel {
    width: 200px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 8px;
    border-right: 2px solid var(--border-primary);
    background: var(--bg-dark);
}

/* Currently-selected slay master: future queue rolls go through this one. */
.master-panel.selected-master {
    background: var(--bg-cell);
    box-shadow: inset 0 0 0 2px var(--text-accent);
}

.master-name-line {
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
    text-align: center;
}
.master-name-line .range { font-size: 20px; color: var(--text-dim); }

.master-portrait {
    width: 128px;
    height: 128px;
    background: var(--bg-cell);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 56px;
    image-rendering: pixelated;
}

.get-task-btn {
    margin-top: 2px;
    padding: 6px 24px;
    font-family: var(--game-font);
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.15s;
}
.get-task-btn:hover { background: var(--bg-hover); border-color: var(--text-accent); }
.get-task-btn.disabled {
    background: var(--bg-dark);
    border-color: var(--border-primary);
    color: var(--text-disabled);
    cursor: not-allowed;
}

/* ── Mob Cards Scroll Area ── */
.mob-cards-scroll {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 12px;
    overflow-x: auto;
    overflow-y: hidden;
}

.mob-cards-scroll::-webkit-scrollbar { height: 6px; }
.mob-cards-scroll::-webkit-scrollbar-track { background: var(--bg-dark); }
.mob-cards-scroll::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 3px; }

/* ── Individual Mob Card ── */
.mob-card {
    width: 140px;
    min-width: 140px;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 6px 4px 8px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.15s;
    position: relative;
}
.mob-card:hover { background: var(--bg-hover); border-color: var(--text-accent); }
.mob-card.locked { opacity: 0.75; background: none; }
.mob-card.locked:hover { background: var(--bg-dark); border-color: var(--border-primary); }

.mob-card-level {
    font-size: 18px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 2px;
}

.mob-card-name {
    font-size: 18px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
    line-height: 1.1;
    min-height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 4px;
}

.mob-card-sprite {
    position: relative;
    width: 128px;
    height: 128px;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    image-rendering: pixelated;
    overflow: hidden;
}

.mob-card-sprite canvas {
    image-rendering: pixelated;
    image-rendering: crisp-edges;
}

.mob-card-style {
    position: absolute;
    top: 4px;
    left: 4px;
    z-index: 2;
    filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.8));
}

.mob-card-style img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.mob-slay-task-icon {
    position: absolute;
    top: 4px;
    right: 4px;
    z-index: 2;
    display: none;
    filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.8));
}

.mob-slay-task-icon img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.mob-quest-task-icon {
    position: absolute;
    top: 4px;
    right: 4px;
    z-index: 1;
    display: none;
    filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.8));
}
/* When a row is BOTH a slay target AND a quest target, push the
   quest icon down 32px + 4px gap so the two stack vertically
   instead of slay covering it. Class toggled by MobSelectionModal
   in step with slayTaskIcon's display change. */
.mob-row-icon.has-slay-task .mob-quest-task-icon {
    top: 36px;
}

.mob-quest-task-icon img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.slay-weights-link {
    display: none;
    cursor: pointer;
    color: var(--text-gold);
    margin-left: 48px;
    font-size: 20px;
}

.slay-weights-link:hover {
    color: var(--text-bright);
}

.mob-card-chance {
    position: absolute;
    bottom: 0px;
    left: 4px;
    font-size: 22px;
    color: var(--text-bright);
    background: var(--bg-cell);
    text-shadow: 1px 1px 0 #000;
    z-index: 2;
}

/* ── Encounter requirement badges ──
   Chaos mobs gate on more than a slay level (level 90 in the skills whose
   tools they drop; total level for the capstone). Icon + number badges sit
   in the sprite's bottom-right, the only corner not already claimed by the
   style icon (top-left), the slay task icon (top-right) or the weight %
   (bottom-left). Markup comes from RequirementBadges so the Slay Masters
   cards and the Skill Customization rows stay identical. */
.req-corner {
    position: absolute;
    right: 3px;
    bottom: 3px;
    z-index: 2;
    display: flex;
    flex-direction: column;
    gap: 3px;
    align-items: flex-end;
    pointer-events: none;
}

.req-badge {
    display: flex;
    align-items: center;
    gap: 2px;
    height: 22px;
    padding: 0 4px 0 2px;
    background: rgba(0, 0, 0, 0.7);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
}

.req-badge img {
    width: 18px;
    height: 18px;
    image-rendering: pixelated;
}

.req-badge b {
    font-size: 12px;
    font-weight: normal;
    color: #ffd34d;
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}

/* Red wash over the sprite while the card is locked, so a gated mob reads
   as blocked at a glance and the badges say what is blocking it. */
.req-dim {
    display: none;
    position: absolute;
    inset: 0;
    z-index: 1;
    background: rgba(150, 0, 0, 0.30);
    pointer-events: none;
}
.mob-card.locked .req-dim { display: block; }
.mob-row.locked .req-dim { display: block; }
/* .mob-row-icon sizes every descendant img to 128px, which would swallow
   a badge icon on ordering alone. Pin it explicitly. */
.mob-row-icon .req-badge img { width: 18px; height: 18px; filter: none; }

/* ── Tier color accents ── */
.tier-feeble .master-name-line  { color: #4caf50; }
.tier-feeble .master-panel { border-left: 3px solid #4caf50; }
.tier-dire .master-name-line    { color: #4fc3f7; }
.tier-dire .master-panel   { border-left: 3px solid #4fc3f7; }
.tier-savage .master-name-line  { color: #ff9800; }
.tier-savage .master-panel { border-left: 3px solid #ff9800; }
.tier-fell .master-name-line    { color: #f44336; }
.tier-fell .master-panel   { border-left: 3px solid #f44336; }
.tier-ancient .master-name-line { color: #9c27b0; }
.tier-ancient .master-panel { border-left: 3px solid #9c27b0; }
.tier-chaos .master-panel { border-left: 3px solid; border-image: linear-gradient(180deg, #ff4444, #ff8800, #ffdd00, #44ff44, #4488ff, #8844ff) 1; }
.tier-chaos .master-name-line { text-shadow: none; filter: drop-shadow(1px 1px 0 #000); }
/* Chaos is the one tier whose row stacks: the blurb explains the pool it
   borrows from every other master, and its own twelve mobs card up
   underneath. Every other tier puts its cards directly in the row. */
.chaos-stack {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.chaos-stack .mob-cards-scroll {
    flex: 1;
    min-height: 0;
}
.chaos-blurb {
    display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
    padding: 16px 24px; flex: 1; min-width: 0;
}
/* Inside the stack the blurb sizes to its text instead of splitting the
   row's height with the cards, which would crop them. */
.chaos-stack .chaos-blurb {
    flex: 0 0 auto;
    padding: 12px 24px 4px;
}
.chaos-blurb-title {
    font-size: 20px; font-weight: bold; margin-bottom: 8px;
    filter: drop-shadow(1px 1px 0 #000);
}
.chaos-blurb-text {
    font-size: 14px; color: var(--text-dim); line-height: 1.5;
}

/* ══════════════════════════════════════════════════════════════
   QUEST MODAL
   ══════════════════════════════════════════════════════════════ */

.quest-layout {
    flex: 1;
    display: flex;
    gap: 0;
    overflow: hidden;
}

/* ── Quest List (Left Side) ── */
.quest-list-side {
    width: 420px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-right: 2px solid var(--border-primary);
}

.quest-list-toolbar {
    display: flex;
    align-items: center;
    padding: 6px 10px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border-primary);
    gap: 6px;
    flex-shrink: 0;
    flex-wrap: wrap;
}

.quest-search {
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 4px 8px;
    font-family: var(--game-font);
    font-size: 20px;
    color: var(--text-bright);
    width: 160px;
    outline: none;
}
.quest-search::placeholder { color: var(--border-primary); }
.quest-search:focus { border-color: var(--text-accent); }

.quest-filter-btn {
    padding: 4px 8px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 17px;
    text-shadow: 1px 1px 0 #000;
}
.quest-filter-btn:hover { background: var(--bg-cell); color: var(--text-bright); border-color: var(--text-accent); }
.quest-filter-btn.active { color: var(--text-bright); border-color: var(--text-accent); background: var(--bg-cell); }

.quest-sort-row {
    display: flex;
    align-items: center;
    padding: 3px 10px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border-primary);
    gap: 6px;
    flex-shrink: 0;
}

.quest-sort-label {
    font-size: 17px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
}

.quest-sort-btn {
    padding: 2px 8px;
    background: var(--bg-panel);
    border: 1px solid var(--bg-cell);
    border-radius: 3px;
    color: var(--text-muted);
    cursor: pointer;
    font-family: var(--game-font);
    font-size: 16px;
    text-shadow: 1px 1px 0 #000;
}
.quest-sort-btn:hover { color: var(--text-light); border-color: var(--border-primary); }
.quest-sort-btn.active { color: var(--text-accent); border-color: var(--text-accent); }

/* ── Quest List Scroll ── */
.quest-list-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 2px;
}

/* ── Quest Row ── */
.quest-row {
    display: flex;
    align-items: center;
    padding: 8px 10px;
    border-bottom: 1px solid var(--bg-panel);
    min-height: 80px;
    cursor: pointer;
    transition: background 0.1s;
    gap: 10px;
}
.quest-row:hover { background: var(--bg-cell); }
.quest-row.selected { background: #2a3a20; outline: 2px solid #4caf50; outline-offset: -2px; }

.quest-status-dot {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    flex-shrink: 0;
    border: 1px solid rgba(0,0,0,0.4);
}
.quest-status-dot.locked { background: #f44336; }
.quest-status-dot.available { background: #f44336; }
.quest-status-dot.in-progress { background: var(--text-bright); }
.quest-status-dot.completed {
    background: transparent;
    border: none;
    color: #4caf50;
    font-size: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    text-shadow: 1px 1px 0 #000;
    font-weight: bold;
}

.quest-row-info {
    flex: 1;
    min-width: 0;
}

.quest-row-name {
    font-size: 22px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.1;
}

/* Status-based row name coloring */
.quest-row.status-locked .quest-row-name { color: #f44336; }
.quest-row.status-available .quest-row-name { color: #f44336; }
.quest-row.status-active .quest-row-name { color: #ffff00; }
.quest-row.status-claimable .quest-row-name { color: #ffff00; }
.quest-row.status-completed .quest-row-name { color: #4caf50; }

.quest-row-reqs {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 2px;
    max-width: 300px;
    overflow-x: clip;
}

.quest-req-badge {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 1px 5px;
    background: var(--bg-dark);
    border: 1px solid var(--bg-cell);
    border-radius: 2px;
    font-size: 22px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
}
.quest-req-badge .req-icon {
    width: 32px;
    height: 32px;
    border-radius: 2px;
    display: inline-block;
}

.quest-row-meta {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    flex-shrink: 0;
    gap: 2px;
}

.quest-step-badge {
    font-size: 22px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}

/* Status-based step badge coloring */
.quest-row.status-locked .quest-step-badge { color: #f44336; }
.quest-row.status-available .quest-step-badge { color: #f44336; }
.quest-row.status-active .quest-step-badge { color: #ffff00; }
.quest-row.status-claimable .quest-step-badge { color: #ffff00; }
.quest-row.status-completed .quest-step-badge { color: #4caf50; }

.quest-progress-badge {
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    white-space: nowrap;
}

/* Status-based progress badge coloring */
.quest-row.status-active .quest-progress-badge { color: #ffff00; }
.quest-row.status-claimable .quest-progress-badge { color: #ffff00; }

/* ══════════════════════════════════════════════
   QUEST DETAIL (Right Side)
   ══════════════════════════════════════════════ */

.quest-detail-side {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.quest-detail-header {
    padding: 14px 18px 10px;
    background: var(--bg-dark);
    border-bottom: 1px solid var(--border-primary);
    flex-shrink: 0;
}

.quest-detail-title {
    font-size: 32px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
    margin-bottom: 4px;
}

.quest-detail-desc {
    font-size: 22px;
    color: var(--text-dim);
    text-shadow: 1px 1px 0 #000;
    line-height: 1.2;
}

/* Status-based detail title coloring */
.quest-detail-side.status-locked .quest-detail-title { color: #f44336; }
.quest-detail-side.status-available .quest-detail-title { color: #f44336; }
.quest-detail-side.status-active .quest-detail-title { color: #ffff00; }
.quest-detail-side.status-claimable .quest-detail-title { color: #ffff00; }
.quest-detail-side.status-completed .quest-detail-title { color: #4caf50; }

/* Status-based detail desc coloring (muted shades) */
.quest-detail-side.status-locked .quest-detail-desc { color: #b33a3a; }
.quest-detail-side.status-available .quest-detail-desc { color: #b33a3a; }
.quest-detail-side.status-active .quest-detail-desc { color: #cccc66; }
.quest-detail-side.status-claimable .quest-detail-desc { color: #cccc66; }
.quest-detail-side.status-completed .quest-detail-desc { color: #3a8a3a; }

/* ── Requirements Section ── */
.quest-reqs-section {
    padding: 10px 18px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border-primary);
    flex-shrink: 0;
    display: flex;
    gap: 24px;
    flex-wrap: wrap;
}

.quest-reqs-group {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.quest-reqs-label {
    font-size: 24px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
}

.quest-req-item {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
}

.quest-req-item .req-skill-icon {
    width: 32px;
    height: 32px;
    border-radius: 3px;
    display: inline-block;
}

.req-met { color: #4caf50; }
.req-unmet { color: #f44336; }
.req-check { font-size: 18px; }

/* ── Main Detail Content (Steps + Dialogue) ── */
.quest-detail-content {
    flex: 1;
    display: flex;
    overflow: hidden;
}

/* ── Steps Column ── */
.quest-steps-col {
    width: 480px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--bg-cell);
    overflow: hidden;
}

.quest-steps-header {
    padding: 8px 14px;
    font-size: 22px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    border-bottom: 1px solid var(--bg-cell);
    flex-shrink: 0;
    background: var(--bg-panel);
}

.quest-steps-list {
    flex: 1;
    overflow-y: auto;
    padding: 6px 0;
}

.quest-step {
    display: flex;
    align-items: flex-start;
    padding: 8px 14px;
    gap: 10px;
    min-height: 60px;
    transition: background 0.1s;
}
.quest-step.current { background: rgba(255,255,0,0.06); }

.quest-step-num {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    text-shadow: 1px 1px 0 #000;
    flex-shrink: 0;
    border: 2px solid;
}
.quest-step-num.done {
    background: #2a4a20;
    border-color: #4caf50;
    color: #4caf50;
}
.quest-step-num.active {
    background: #4a4a10;
    border-color: var(--text-bright);
    color: var(--text-bright);
    box-shadow: 0 0 8px rgba(255,255,0,0.3);
}
.quest-step-num.future {
    background: var(--bg-panel);
    border-color: var(--text-muted);
    color: var(--text-muted);
}

.quest-step-body {
    flex: 1;
    min-width: 0;
}

.quest-step-text {
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
    line-height: 1.2;
}
.quest-step-text.done { color: #4caf50; }
.quest-step-text.active { color: #ffff00; }
.quest-step-text.future { color: var(--text-muted); }

/* ── Dialogue / Quest Log Column ── */
.quest-dialogue-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.quest-dialogue-header {
    padding: 8px 14px;
    font-size: 22px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    border-bottom: 1px solid var(--bg-cell);
    flex-shrink: 0;
    background: var(--bg-panel);
}

.quest-dialogue-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 10px 14px;
}

.quest-dialogue-entry {
    margin-bottom: 14px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--bg-panel);
}
.quest-dialogue-entry:last-child { border-bottom: none; }

.quest-dialogue-step-label {
    font-size: 22px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
}

.quest-dialogue-text {
    font-size: 20px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    line-height: 1.35;
    font-style: italic;
}

.quest-dialogue-active {
    border-left: 3px solid var(--text-accent);
    padding-left: 10px;
}

.quest-dialogue-active .quest-dialogue-step-label {
    color: var(--text-bright);
}

.quest-dialogue-pending {
    color: var(--text-muted);
    font-style: italic;
}

.quest-dialogue-locked {
    font-size: 22px;
    color: var(--text-muted);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
    margin-top: 6px;
}

/* ── Rewards + Actions Bar (bottom) ── */
.quest-bottom-bar {
    border-top: 2px solid var(--border-primary);
    background: var(--bg-dark);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    padding: 10px 18px;
    gap: 20px;
}

.quest-rewards-section {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 14px;
}

.quest-rewards-label {
    font-size: 20px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    flex-shrink: 0;
}

.quest-reward-xp-list {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.quest-reward-xp {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 19px;
    text-shadow: 1px 1px 0 #000;
}
.quest-reward-xp .xp-icon {
    width: 32px;
    height: 32px;
    border-radius: 3px;
    display: inline-block;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.quest-reward-xp .xp-amount { color: #4caf50; }
.quest-reward-xp .xp-skill { color: var(--text-light); }

.quest-reward-items {
    display: flex;
    gap: 4px;
}

/* ── Action Buttons ── */
.quest-actions {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
}

.quest-btn {
    padding: 10px 24px;
    font-family: var(--game-font);
    font-size: 26px;
    text-shadow: 2px 2px 0 #000;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.15s;
    text-align: center;
    white-space: nowrap;
    position: relative;
}
.quest-btn:hover .icon-tooltip { display: block; }

.quest-btn-begin {
    color: var(--text-bright);
    background: linear-gradient(180deg, #4a6a2a 0%, #3a5a1a 100%);
    border: 2px solid #6a8a3a;
}
.quest-btn-begin:hover { background: linear-gradient(180deg, #5a7a3a 0%, #4a6a2a 100%); border-color: #8aaa5a; }

.quest-btn-complete {
    color: var(--text-bright);
    background: linear-gradient(180deg, #6a5a1a 0%, #5a4a0a 100%);
    border: 2px solid var(--text-accent);
    box-shadow: 0 0 10px rgba(200,168,62,0.3);
}
.quest-btn-complete:hover { background: linear-gradient(180deg, #7a6a2a 0%, #6a5a1a 100%); box-shadow: 0 0 15px rgba(200,168,62,0.5); }

.quest-btn-disabled {
    color: var(--border-primary);
    background: var(--bg-panel);
    border: 2px solid var(--bg-cell);
    cursor: not-allowed;
}

.quest-btn-done-label {
    font-size: 24px;
    color: #4caf50;
    text-shadow: 1px 1px 0 #000;
    display: flex;
    align-items: center;
    gap: 6px;
}

/* ── No Selection Placeholder ── */
.quest-detail-side .no-selection {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 12px;
}
.quest-detail-side .no-selection-icon { transform: scale(2); image-rendering: pixelated; filter: drop-shadow(1px 1px 0 #000); opacity: 0.3; margin-bottom: 12px; }
.quest-detail-side .no-selection-text {
    font-size: 28px;
    color: var(--border-primary);
    text-shadow: 1px 1px 0 #000;
}

/* ── Scrollbars ── */
.quest-list-scroll::-webkit-scrollbar,
.quest-steps-list::-webkit-scrollbar,
.quest-dialogue-scroll::-webkit-scrollbar { width: 8px; }
.quest-list-scroll::-webkit-scrollbar-track,
.quest-steps-list::-webkit-scrollbar-track,
.quest-dialogue-scroll::-webkit-scrollbar-track { background: var(--bg-dark); }
.quest-list-scroll::-webkit-scrollbar-thumb,
.quest-steps-list::-webkit-scrollbar-thumb,
.quest-dialogue-scroll::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }

/* ═══════════════════════════════════════════════════════════════
   Reconnect Overlay
   ═══════════════════════════════════════════════════════════════ */

.reconnect-overlay {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    background: rgba(0, 0, 0, 0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
}

.reconnect-box {
    background: var(--bg-panel);
    border: 2px solid var(--border-secondary);
    border-radius: 8px;
    padding: 32px 40px;
    width: 480px;
    max-height: 80%;
    display: flex;
    flex-direction: column;
    gap: 16px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}

.reconnect-title {
    font-size: 36px;
    color: var(--text-gold);
    text-align: center;
    text-shadow: 2px 2px 0 #000;
}

.reconnect-countdown {
    font-size: 28px;
    color: var(--text-bright);
    text-align: center;
    text-shadow: 1px 1px 0 #000;
    min-height: 36px;
}

.reconnect-buttons {
    display: flex;
    gap: 12px;
    justify-content: center;
}

.reconnect-btn {
    font-family: var(--game-font);
    font-size: 22px;
    padding: 8px 24px;
    border: 2px solid var(--border-secondary);
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.15s;
    background: var(--bg-cell);
    color: var(--text-light);
}

.reconnect-btn:hover {
    background: var(--bg-hover);
    border-color: var(--text-gold);
    color: var(--text-gold);
}

.reconnect-btn-now {
    background: var(--bg-cell);
    border-color: var(--text-gold);
    color: var(--text-gold);
}

.reconnect-btn-now:hover {
    background: var(--bg-hover);
}

.reconnect-btn-cancel {
    color: var(--text-muted);
    border-color: var(--border-primary);
}

.reconnect-btn-cancel:hover {
    color: #ff6666;
    border-color: #ff6666;
}

.reconnect-phase {
    font-size: 18px;
    color: var(--text-muted);
    text-align: center;
}

.reconnect-log-header {
    font-size: 18px;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    border-bottom: 1px solid var(--border-primary);
    padding-bottom: 6px;
}

.reconnect-log {
    max-height: 280px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.reconnect-log::-webkit-scrollbar { width: 8px; }
.reconnect-log::-webkit-scrollbar-track { background: var(--bg-dark); }
.reconnect-log::-webkit-scrollbar-thumb { background: var(--border-primary); border-radius: 4px; }

.reconnect-log-entry {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 8px;
    font-size: 18px;
    border-radius: 3px;
    background: var(--bg-cell);
}

.reconnect-log-entry.failed .reconnect-log-status { color: #ff6666; }
.reconnect-log-entry.success .reconnect-log-status { color: #66ff66; }
.reconnect-log-entry.connecting .reconnect-log-status { color: var(--text-gold); }
.reconnect-log-entry.success { background: rgba(102, 255, 102, 0.1); border: 1px solid rgba(102, 255, 102, 0.3); }

.reconnect-log-num {
    color: var(--text-dim);
    min-width: 40px;
}

.reconnect-log-status {
    flex: 1;
    color: var(--text-light);
}

.reconnect-log-time {
    color: var(--text-dark);
    font-size: 16px;
}

/* ── Screen Effects (beam drops) ───────────────────────────── */
#screen-effects {
    position: absolute;
    top: 0; left: 0;
    width: 1920px;
    height: 1080px;
    z-index: 1;
    pointer-events: none;
    overflow: hidden;
}
.screen-effect {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    pointer-events: none;
    opacity: 0;
}
.screen-effect.active {
    animation: seFade 2.2s ease-out forwards;
}
.se-beam {
    position: absolute;
    top: -20%;
    left: var(--playable-center-x, 50%);
    transform: translateX(-50%);
    width: 6px;
    height: 0;
    border-radius: 3px;
    filter: blur(1px);
    z-index: 1;
}
.screen-effect.active .se-beam {
    animation: seBeamDrop 0.5s ease-in forwards;
}
.se-beam-glow {
    position: absolute;
    top: -20%;
    left: var(--playable-center-x, 50%);
    transform: translateX(-50%);
    width: 40px;
    height: 0;
    border-radius: 20px;
    filter: blur(8px);
    z-index: 0;
}
.screen-effect.active .se-beam-glow {
    animation: seBeamDrop 0.5s ease-in forwards;
}
.se-impact {
    position: absolute;
    top: 50%;
    left: var(--playable-center-x, 50%);
    transform: translate(-50%, -50%);
    width: 0;
    height: 0;
    border-radius: 50%;
    opacity: 0;
    z-index: 2;
}
.screen-effect.active .se-impact {
    animation: seImpact 0.6s ease-out 0.45s forwards;
}
.se-ring {
    position: absolute;
    top: 50%;
    left: var(--playable-center-x, 50%);
    transform: translate(-50%, -50%);
    width: 0;
    height: 0;
    border: 2px solid;
    border-radius: 50%;
    opacity: 0;
    z-index: 2;
}
.screen-effect.active .se-ring {
    animation: seRing 0.8s ease-out 0.45s forwards;
}
.se-shard {
    position: absolute;
    top: 50%;
    left: var(--playable-center-x, 50%);
    width: 4px;
    height: 4px;
    border-radius: 1px;
    opacity: 0;
    z-index: 3;
}
.screen-effect.active .se-shard {
    animation: seShard 0.8s ease-out 0.5s forwards;
}
.se-shard-0  { --sx: -60px; --sy: -80px; --rot: 15deg; }
.se-shard-1  { --sx: 20px;  --sy: -90px; --rot: -30deg; }
.se-shard-2  { --sx: 70px;  --sy: -50px; --rot: 45deg; }
.se-shard-3  { --sx: 85px;  --sy: 10px;  --rot: -15deg; }
.se-shard-4  { --sx: 60px;  --sy: 60px;  --rot: 60deg; }
.se-shard-5  { --sx: 10px;  --sy: 80px;  --rot: -45deg; }
.se-shard-6  { --sx: -40px; --sy: 70px;  --rot: 30deg; }
.se-shard-7  { --sx: -80px; --sy: 30px;  --rot: -60deg; }
.se-shard-8  { --sx: -70px; --sy: -20px; --rot: 20deg; }
.se-shard-9  { --sx: 50px;  --sy: -70px; --rot: -40deg; }
.se-shard-10 { --sx: -30px; --sy: 85px;  --rot: 50deg; }
.se-shard-11 { --sx: 80px;  --sy: -30px; --rot: -25deg; }
.se-mist {
    position: absolute;
    top: 50%;
    left: var(--playable-center-x, 50%);
    width: 8px;
    height: 8px;
    border-radius: 50%;
    opacity: 0;
    z-index: 1;
    filter: blur(3px);
}
.screen-effect.active .se-mist {
    animation: seMist 1.2s ease-out 0.5s forwards;
}
.se-mist-0 { --mx: -40px; --my: -30px; --mdy: 50px; width: 12px; height: 12px; }
.se-mist-1 { --mx: 30px;  --my: -40px; --mdy: 60px; width: 10px; height: 10px; }
.se-mist-2 { --mx: 50px;  --my: -10px; --mdy: 40px; width: 14px; height: 14px; }
.se-mist-3 { --mx: -50px; --my: -15px; --mdy: 45px; width: 11px; height: 11px; }
.se-mist-4 { --mx: -20px; --my: -50px; --mdy: 70px; width: 16px; height: 16px; }
.se-mist-5 { --mx: 45px;  --my: -35px; --mdy: 55px; width: 9px;  height: 9px; }
.se-mist-6 { --mx: -35px; --my: -45px; --mdy: 65px; width: 13px; height: 13px; }
.se-mist-7 { --mx: 15px;  --my: -20px; --mdy: 35px; width: 10px; height: 10px; }

@keyframes seFade {
    0%   { opacity: 1; }
    80%  { opacity: 1; }
    100% { opacity: 0; }
}
@keyframes seBeamDrop {
    0%   { height: 0; top: -20%; }
    100% { height: 70%; top: -20%; }
}
@keyframes seImpact {
    0%   { width: 0; height: 0; opacity: 1; }
    40%  { width: 160px; height: 160px; opacity: 0.8; }
    100% { width: 220px; height: 220px; opacity: 0; }
}
@keyframes seShard {
    0%   { transform: translate(0, 0) rotate(0deg); opacity: 1; }
    30%  { opacity: 1; }
    100% { transform: translate(var(--sx), var(--sy)) rotate(var(--rot)); opacity: 0; }
}
@keyframes seMist {
    0%   { transform: translate(0, -60px) scale(0.5); opacity: 0.8; }
    30%  { transform: translate(var(--mx), var(--my)) scale(1.2); opacity: 0.6; }
    100% { transform: translate(var(--mx), var(--mdy)) scale(0.3); opacity: 0; }
}
@keyframes seRing {
    0%   { width: 0; height: 0; opacity: 0.8; border-width: 3px; }
    100% { width: 180px; height: 180px; opacity: 0; border-width: 1px; }
}

/* Rare drop floating item icon */
.se-rare-item {
    position: absolute;
    top: 50%;
    left: var(--playable-center-x, 50%);
    transform: translate(-50%, -50%) scale(1.5);
    z-index: 4;
    pointer-events: none;
    opacity: 0;
}
.se-rare-item.active {
    animation: seRareItem 3.2s ease-out forwards;
}
.se-rare-item img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(2px 2px 0 #000) drop-shadow(0 0 8px rgba(255, 68, 68, 0.6));
}
@keyframes seRareItem {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
    15%  { opacity: 1; transform: translate(-50%, -50%) scale(1.5); }
    75%  { opacity: 1; transform: translate(-50%, -50%) scale(1.5); }
    100% { opacity: 0; transform: translate(-50%, -60%) scale(1.5); }
}

/* ── Lamp Overlay ──────────────────────────────────────────── */
.lamp-overlay {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0, 0, 0, 0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2200;
}
.lamp-panel {
    background: linear-gradient(168deg,
        color-mix(in srgb, var(--bg-panel) 97%, transparent) 0%,
        color-mix(in srgb, var(--bg-darkest) 98%, transparent) 100%);
    border: 2px solid color-mix(in srgb, var(--text-gold) 45%, transparent);
    border-radius: 6px;
    padding: 24px 32px;
    text-align: center;
    font-family: var(--game-font);
}
.lamp-title {
    font-size: 28px;
    color: #ffd700;
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
}
.lamp-subtitle {
    font-size: 18px;
    color: #ccc;
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 16px;
}
.lamp-grid {
    display: grid;
    grid-template-columns: repeat(4, 80px);
    gap: 4px;
    margin-bottom: 16px;
}
.lamp-skill-cell {
    width: 80px;
    height: 72px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}
.lamp-skill-cell:hover:not(.disabled) {
    border-color: var(--text-accent);
    background: #3a2e1a;
}
.lamp-skill-cell.disabled {
    opacity: 0.3;
    cursor: not-allowed;
}
.lamp-skill-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.lamp-skill-name {
    font-size: 14px;
    color: #ccc;
    text-shadow: 1px 1px 0 #000;
    margin-top: 2px;
}
.lamp-skill-level {
    font-size: 12px;
    color: #888;
    text-shadow: 1px 1px 0 #000;
}
.lamp-cancel-btn {
    font-family: var(--game-font);
    font-size: 20px;
    color: #ccc;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    padding: 6px 24px;
    cursor: pointer;
    transition: border-color 0.15s;
}
.lamp-cancel-btn:hover {
    border-color: var(--text-accent);
    color: var(--text-gold);
}

/* ── Unlocks Modal ─────────────────────────────────────────── */

/* Reuse SkillCustomModal grid patterns — these are scoped to the unlocks tab */
#tab-unlocks .unlocks-grid-section {
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
}
#tab-unlocks .unlocks-grid-header {
    display: flex; align-items: center;
    padding: 4px 8px;
    background: var(--bg-cell);
}
#tab-unlocks .unlocks-grid-title {
    font-size: 30px; color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}
/* Specials Armory: sits under the main unlocks grid; the summary shows
   owned count + the crit the Armory currently grants. */
#tab-unlocks .unlocks-armory-section { margin-top: 8px; }
#tab-unlocks .unlocks-armory-summary {
    margin-left: auto;
    font-size: 20px; color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
}
#tab-unlocks .unlocks-grid {
    display: grid;
    gap: 2px; padding: 6px;
}
#tab-unlocks .grid-skill-header {
    width: 56px; height: 56px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-panel);
    border-radius: 3px;
}
#tab-unlocks .grid-skill-header img {
    transform: scale(1.5);
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
#tab-unlocks .unlock-item {
    position: relative;
    width: 56px; height: 56px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
}
#tab-unlocks .unlock-item img {
    transform: scale(1.5);
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
/* Pack icons (Offline Progress row) ship at 112px (2x) rather than
   the 32px native item icons, so they get explicit sizing instead of
   the natural-size + scale(1.5) treatment above. 48px matches the
   visual size of the scaled item icons inside the 56px cell. */
#tab-unlocks .unlock-item img.unlock-pack-icon {
    width: 48px;
    height: 48px;
    transform: none;
    image-rendering: auto;
}
#tab-unlocks .unlock-item.locked { opacity: 0.3; }
#tab-unlocks .unlock-item.unlocked { border-color: var(--text-accent); }
#tab-unlocks .unlock-item.selected { border-color: var(--text-bright); cursor: pointer; }
#tab-unlocks .unlock-item.unlocked.pet-selectable { cursor: pointer; }
#tab-unlocks .unlock-item.obtained { border-color: #888; opacity: 0.7; }
#tab-unlocks .unlock-item.empty { border-color: transparent; background: transparent; }

/* Unlocks/Collections sub-view toggle in the modal-header (unlocks tab only) */
/* Unlocks/Collections/Diary view switch — same centered icon-rail layout
   as .processing-nav (its buttons use .processing-nav-btn). Kept as its
   own selector so it can be restyled independently later. */
.modal-header .unlocks-header-slot {
    display: flex;
    align-items: center;
    gap: 8px;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

/* Collections indicator pill (shown in modal-header on mobs/slay/unlocks tabs) */
.modal-header .collections-indicator {
    margin-left: auto;
    margin-right: 12px;
    padding: 6px 14px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    color: var(--text-accent);
    font-size: 20px;
    text-shadow: 1px 1px 0 #000;
    cursor: pointer;
    user-select: none;
    transition: border-color 0.15s, color 0.15s;
    white-space: nowrap;
}
.modal-header .collections-indicator:hover {
    border-color: var(--text-accent);
    color: var(--text-bright);
}

/* Collections collapsible sections */
#tab-unlocks .collections-section {
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
}
#tab-unlocks .collections-section-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: var(--bg-cell);
    cursor: pointer;
    user-select: none;
}
#tab-unlocks .collections-section-header:hover {
    background: var(--bg-hover);
}
#tab-unlocks .collections-chevron {
    color: var(--text-accent);
    font-size: 18px;
    width: 18px;
    text-align: center;
    flex: 0 0 auto;
}
#tab-unlocks .collections-section-title {
    font-size: 30px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    flex: 1;
}
/* Per-section icon (gem / glyph / chest / ...) before the section title,
   and the small icon before the Unlocks / Collections / Armory titles. */
#tab-unlocks .collections-section-icon,
#tab-unlocks .unlocks-title-icon {
    width: 32px; height: 32px;
    flex: 0 0 auto;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
    margin-right: 6px;
}
#tab-unlocks .collections-section-content {
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Collections view */
#tab-unlocks .collections-row {
    display: flex;
    gap: 12px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 8px;
    align-items: center;
}
#tab-unlocks .collections-mob-icon {
    width: 96px; height: 96px;
    flex: 0 0 96px;
    background-color: var(--bg-cell);
    background-size: cover;
    background-position: center;
    border-radius: 3px;
    position: relative;
    overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
}
#tab-unlocks .collections-mob-icon canvas {
    width: 96px; height: 96px;
    image-rendering: pixelated;
}
#tab-unlocks .collections-row-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}
#tab-unlocks .collections-row-name {
    font-size: 24px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}
#tab-unlocks .collections-slots {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}
#tab-unlocks .collections-slots-items {
    gap: 32px;
}
/* Gathering and Processing / Creating: one labelled slot strip per row
   (Raw / Processed / Soups, T0 ... T10 / Chaos / God, potion bands). */
#tab-unlocks .collections-skilling-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-top: 4px;
}
#tab-unlocks .collections-skilling-row-label {
    flex: 0 0 90px;
    padding-top: 26px;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    text-align: right;
}
/* Blank slot used to right-align a short row (the T10 gem weapons, the
   three-tier potion band) under the wider rows above it. */
#tab-unlocks .collections-slot-pad {
    width: 56px;
    height: 56px;
    visibility: hidden;
}
/* The God raws' 1/N badge overlays the slot's bottom-right corner so it
   adds no height to its row (the tier label owns the bottom-left). */
#tab-unlocks .collections-skilling-row .collections-slot { position: relative; }
#tab-unlocks .collections-skilling-row .collections-rate-badge {
    position: absolute;
    right: 2px;
    bottom: 0;
    font-size: 14px;
    line-height: 1;
}
#tab-unlocks .collections-slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    width: 56px;
}
/* Lock/unlock styling mirrors .unlock-item, but applied to the inner .inv-slot
   so the rate badge underneath stays at full opacity. */
#tab-unlocks .collections-slot.locked .inv-slot {
    opacity: 0.3;
}
#tab-unlocks .collections-slot.unlocked .inv-slot {
    border-color: var(--text-accent);
}
#tab-unlocks .collections-rate-badge {
    color: var(--text-accent);
    font-size: 18px;
    white-space: nowrap;
    pointer-events: none;
    text-shadow: 1px 1px 0 #000;
}

#tab-unlocks .unlock-tooltip {
    display: none;
    position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);
    background: rgba(0,0,0,0.9); color: var(--text-light);
    padding: 3px 8px; border-radius: 3px; font-size: 14px;
    white-space: nowrap; pointer-events: none; z-index: 10;
    text-shadow: 1px 1px 0 #000;
}
/* unlock-tooltip display handled by TooltipManager (no CSS :hover needed) */

/* Perk icon cells (alms perks section) */
#tab-unlocks .perk-icon-cell {
    width: 56px; height: 56px;
}
#tab-unlocks .perk-icon-cell .inv-qty {
    font-size: 20px;
    top: auto;
    bottom: 1px;
    left: 50%;
    transform: translateX(-50%);
}

/* Alms perk rows */
#tab-unlocks .unlocks-perk-row {
    margin-bottom: 10px;
}
#tab-unlocks .unlocks-perk-row-label {
    font-size: 20px;
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 4px;
}
#tab-unlocks .unlocks-perk-row-desc {
    font-size: 20px;
    color: var(--text-dim);
}
#tab-unlocks .unlocks-perk-row-cells {
    display: flex;
    gap: 3px;
    flex-wrap: wrap;
}

/* ═══════════════════════════════════════════════════════════════
   Clan Modal — Tab content for clan management + browse
   ═══════════════════════════════════════════════════════════════ */

.clan-accept-btn {
    background: #2a4a2a;
    border: 1px solid #4caf50;
    color: #4caf50;
}

.clan-accept-btn:hover {
    background: #3a5a3a;
}

.clan-decline-btn {
    background: #5c2a2a;
    border: 1px solid #f44336;
    color: #f44336;
}

.clan-decline-btn:hover {
    background: #7a3a3a;
}

.clan-view-toggle {
    display: flex;
    gap: 6px;
    padding: 10px 14px 6px;
}

.clan-view-toggle .qp-toggle-btn {
    font-size: 24px;
    height: 36px;
    padding: 4px 12px;
}

.clan-content {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 10px 14px;
}

/* Create section */
.clan-create-section {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
    gap: 14px;
}

.clan-create-title {
    font-size: 28px;
    font-weight: 700;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

.clan-create-desc {
    font-size: 16px;
    color: var(--text-light);
    text-align: center;
    max-width: 500px;
}

.clan-create-row {
    display: flex;
    gap: 8px;
    align-items: center;
}

.clan-create-input,
.clan-invite-input {
    background: var(--bg-darkest);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 16px;
    padding: 6px 10px;
    width: 240px;
    outline: none;
}

.clan-create-input:focus,
.clan-invite-input:focus {
    border-color: var(--text-accent);
}

.clan-error {
    color: #f44336;
    font-size: 14px;
    min-height: 18px;
}

/* My Clan view */
.clan-info-header {
    margin-bottom: 14px;
}

.clan-name-display {
    font-size: 32px;
    font-weight: 700;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 6px;
}

.clan-stats-row {
    display: flex;
    gap: 20px;
    font-size: 16px;
    color: var(--text-light);
    font-family: var(--game-font);
}

.clan-stats-row strong {
    color: var(--text-accent);
}

.clan-section-title {
    font-size: 24px;
    font-weight: 600;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--border-primary);
    padding-bottom: 4px;
}

.clan-members-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 14px;
}

.clan-member-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    background: var(--bg-cell);
    border-radius: 4px;
    font-size: 16px;
    color: var(--text-light);
}

.clan-member-row:hover {
    background: var(--bg-hover);
}

.clan-member-name {
    flex: 1;
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.clan-leader-badge {
    color: var(--text-accent);
    font-weight: 400;
    font-size: 20px;
}

.clan-member-level {
    color: var(--text-dim);
    font-size: 14px;
}

.clan-kick-btn {
    padding: 2px 8px;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: #f44336;
    font-family: var(--game-font);
    font-size: 13px;
    cursor: pointer;
    transition: background 0.15s;
}

.clan-kick-btn:hover {
    background: var(--bg-hover);
    border-color: #f44336;
}

/* Clan tag row (above actions). Leader sees an input + button; members
   just see the current tag. */
.clan-tag-row {
    display: flex;
    gap: 8px;
    align-items: center;
    margin: 10px 0 4px 0;
}

.clan-tag-label {
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 15px;
    text-shadow: 1px 1px 0 #000;
}

.clan-tag-current {
    color: var(--text-accent);
    font-family: var(--game-font);
    font-size: 15px;
    text-shadow: 1px 1px 0 #000;
    min-width: 60px;
}

.clan-tag-input {
    width: 80px;
    padding: 6px 8px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    color: var(--text-bright);
    font-family: var(--game-font);
    font-size: 15px;
    text-shadow: 1px 1px 0 #000;
    text-transform: none;
}

.clan-tag-input:focus {
    outline: none;
    border-color: var(--text-accent);
}

/* Actions row (invite + leave on same line) */
.clan-actions-row {
    display: flex;
    gap: 8px;
    align-items: center;
    margin: 10px 0;
}

.clan-action-btn {
    padding: 6px 14px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 15px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
    transition: background 0.15s, border-color 0.15s;
    text-align: center;
}

.clan-action-btn:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
    color: var(--text-bright);
}

.clan-leave-btn {
    color: #f44336;
    border-color: #f44336;
    max-width: 320px;
}

.clan-leave-btn:hover {
    background: rgba(244, 67, 54, 0.15);
}

/* Loading */
.clan-loading {
    text-align: center;
    color: var(--text-dim);
    font-size: 16px;
    padding: 40px;
}

/* Browse clans */
.clan-browse-list {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.clan-browse-row {
    border-radius: 4px;
    overflow: hidden;
}

/* Grid layout (was flex) so 5/5, Lv X, XP all land in identical column
   positions row-to-row. Every column is left-aligned; track widths do the
   alignment work instead of per-cell text-align overrides. */
.clan-browse-main {
    display: grid;
    grid-template-columns: 56px 56px 1fr 60px 110px 1fr 24px;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    background: var(--bg-cell);
    cursor: pointer;
    font-size: 22px;
    transition: background 0.1s;
}

.clan-browse-main:hover {
    background: var(--bg-hover);
}

.clan-browse-rank {
    color: var(--text-dim);
    font-weight: 600;
    text-align: left;
}

.clan-browse-tag {
    color: var(--text-accent);
    font-weight: 600;
    text-align: left;
    text-shadow: 1px 1px 0 #000;
}

.clan-browse-name {
    color: #5dade2;
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.clan-browse-members {
    color: var(--text-dim);
    font-size: 18px;
    text-align: left;
}

.clan-browse-level {
    color: var(--text-bright);
    text-align: left;
}

.clan-browse-xp {
    color: var(--text-light);
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.clan-browse-expand {
    color: var(--text-dim);
    font-size: 16px;
    text-align: left;
}

/* Inline detail (expanded) */
.clan-detail-inline {
    background: var(--bg-dark);
    border-top: 1px solid var(--border-primary);
    padding: 8px 14px;
}

.clan-detail-member {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 8px;
    font-size: 15px;
    cursor: pointer;
    border-radius: 3px;
    transition: background 0.1s;
}

.clan-detail-member:hover {
    background: var(--bg-cell);
}

.clan-detail-member-name {
    flex: 1;
    color: var(--text-light);
    font-weight: 600;
}

.clan-detail-member-level {
    color: var(--text-bright);
    min-width: 80px;
}

.clan-detail-member-xp {
    color: var(--text-light);
    min-width: 100px;
    text-align: right;
}

/* ── Clan detail summary stats ── */
.clan-detail-summary {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 6px 0 8px;
    font-size: 24px;
    color: var(--text-light);
    font-family: var(--game-font);
}

.clan-detail-stat-line strong {
    color: var(--text-accent);
}

/* ── Clan detail member table ── */
.clan-detail-mtable {
    margin-bottom: 10px;
}

/* Grid columns: name | level | xp | kick | expand. Same template on the
   header (clan-detail-mhead) and body rows so column lines stay aligned
   regardless of which rows show a Kick button. The kick column is always
   allocated; rows without a kick render an empty placeholder span. */
.clan-detail-mrow {
    display: grid;
    grid-template-columns: 1fr 80px 160px 60px 24px;
    align-items: center;
    gap: 8px;
    padding: 5px 8px;
    font-size: 24px;
    color: var(--text-light);
    cursor: pointer;
    border-radius: 3px;
    transition: background 0.1s;
}

.clan-detail-mrow:hover {
    background: var(--bg-cell);
}

.clan-detail-mhead {
    cursor: default;
    color: var(--text-dim);
    font-size: 20px;
    border-bottom: 1px solid var(--border-primary);
    padding-bottom: 3px;
    margin-bottom: 2px;
}

.clan-detail-mhead:hover {
    background: transparent;
}

.clan-detail-mcol-name {
    overflow: hidden;
    min-width: 0;
}

/* [TAG] prefix span inside a member name. Matches the chat clan-tag and
   browse-row tag color so the affiliation reads consistently across UIs. */
.clan-detail-mtag {
    color: var(--text-accent);
    font-weight: 600;
}

.clan-detail-mname-text {
    font-weight: 600;
    text-shadow: 1px 1px 0 #000;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.clan-detail-mactivity {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 20px;
    color: var(--text-dim);
    margin-top: 2px;
}

.clan-detail-mactivity img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.clan-detail-mcol-lvl {
    color: var(--text-bright);
    text-align: left;
}

.clan-detail-mcol-xp {
    color: var(--text-light);
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Side-by-side skill grids row */
.clan-grids-row {
    display: flex;
    gap: 20px;
    overflow-x: auto;
    overflow-y: visible;
    padding: 16px 0 8px;
}

.clan-skill-grid-wrapper {
    flex-shrink: 0;
    width: 320px;
}

.clan-skill-grid-label {
    font-size: 24px;
    font-weight: 600;
    color: var(--text-accent);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
    margin-bottom: 6px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 320px;
}

/* 4-column grid matching skills panel layout */
.clan-skill-grid-4col {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 4px;
    width: 100%;
}

.clan-sg-cell {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0;
    padding: 3px 5px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    font-size: 20px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    height: 50px;
    min-width: 0;
    overflow: hidden;
    cursor: default;
}

.clan-sg-cell:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
}

.clan-sg-cell img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.clan-sg-cell span {
    margin-left: auto;
    line-height: 1;
}

/* Grid footer (Total Level + Total XP) — matches grid width */
.clan-sg-footer {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 4px;
    margin-top: 4px;
    width: 100%;
}

.clan-sg-footer-cell {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 3px 5px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    font-size: 18px;
    min-width: 0;
    overflow: hidden;
    height: 50px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

.clan-sg-footer-cell img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.clan-sg-footer-cell span {
    margin-left: auto;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
}

/* Expanded member hiscores table */
.clan-member-hs-table {
    padding: 6px 12px 10px;
    background: var(--bg-dark);
    border-radius: 4px;
    margin: 2px 0 6px;
}

.clan-member-hs-table .hs-table {
    font-size: 15px;
}

/* Hiscores mode toggle */
.hs-mode-toggle {
    display: flex;
    gap: 6px;
    padding: 10px 14px 0;
}

/* ═══════════════════════════════════════════════════════════════
   Chat Category Filter Context Menu
   ═══════════════════════════════════════════════════════════════ */

.chat-category-menu {
    position: absolute;
    z-index: 2300;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    padding: 8px 0;
    min-width: 200px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
    font-family: var(--game-font);
}

.chat-category-title {
    padding: 4px 12px 8px;
    font-size: 15px;
    font-weight: 600;
    color: var(--text-accent);
    border-bottom: 1px solid var(--border-primary);
    margin-bottom: 4px;
}

.chat-category-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 12px;
    cursor: pointer;
    font-size: 14px;
    color: var(--text-light);
    transition: background 0.1s;
}

.chat-category-row:hover {
    background: var(--bg-hover);
}

.chat-category-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}

.chat-category-check {
    width: 16px;
    height: 16px;
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    background: var(--bg-darkest);
    margin-left: auto;
    flex-shrink: 0;
    position: relative;
}

.chat-category-check.checked {
    background: var(--text-accent);
    border-color: var(--text-accent);
}

.chat-category-check.checked::after {
    content: '\2713';
    position: absolute;
    top: -1px;
    left: 2px;
    font-size: 12px;
    color: var(--bg-dark);
    font-weight: bold;
}

/* ═══════════════════════════════════════════════════════════════
   Floating Tab Strip — always-visible icons over game world
   Matches .modal-tabs positioning exactly so icons align when
   modal opens. Hidden when GroupOfModals is open.
   ═══════════════════════════════════════════════════════════════ */

.floating-tab-strip {
    position: absolute;
    left: 2px;
    top: 2px;
    width: 60px;
    display: flex;
    flex-direction: column;
    padding: 4px 0;
    gap: 1px;
    /* Sits above the in-game HUD (z-index 80) so the rightward
       tooltip flyout isn't clipped by the HUD panel that lives
       just to its right. The strip itself doesn't overlap the
       HUD (left: 2px vs left: 72px) - only the tooltip extends
       into HUD territory. */
    z-index: 100;
    pointer-events: none;
}

/* Ungrouped sidebar expands every member into its own icon (~20). Rather
   than scroll (which would clip the rightward hover tooltips), tighten the
   spacing and shrink the buttons so they all fit the viewport height with
   overflow left visible — tooltips keep flying out to the right. */
.floating-tab-strip.ungrouped {
    padding: 0;
    gap: 1px;
}
.floating-tab-strip.ungrouped .floating-tab-btn {
    height: 44px;
}
.floating-tab-strip.ungrouped .floating-tab-icon {
    width: 28px;
    height: 28px;
}

/* Collapse/expand arrow for the side tab strip. Always visible at
   the top-left. When body.side-tabs-collapsed is set, the tab
   buttons below it are hidden; the toggle itself stays put so the
   user can click ▶ to re-expand. */
.floating-tab-toggle {
    width: 56px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    pointer-events: auto;
    color: var(--text-light);
    font-size: 14px;
    line-height: 1;
    background: rgba(0, 0, 0, 0.35);
    border-radius: 0 6px 6px 0;
    border-left: 3px solid transparent;
    transition: background 0.15s, border-left-color 0.15s, color 0.15s;
    margin-bottom: 2px;
    user-select: none;
}
.floating-tab-toggle:hover {
    background: rgba(0, 0, 0, 0.55);
    border-left-color: var(--text-accent);
    color: var(--text-bright);
}
.floating-tab-toggle-arrow {
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
}

body.side-tabs-collapsed .floating-tab-strip .floating-tab-btn {
    display: none;
}

.floating-tab-btn {
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    position: relative;
    pointer-events: auto;
    border-left: 3px solid transparent;
    transition: background 0.15s;
    border-radius: 0 6px 6px 0;
}

.floating-tab-btn:hover {
    background: rgba(0, 0, 0, 0.5);
    border-left-color: var(--text-accent);
}

.floating-tab-btn.active {
    background: rgba(0, 0, 0, 0.6);
    border-left-color: var(--text-accent);
}

.floating-tab-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8));
    transition: filter 0.15s;
}

.floating-tab-btn:hover .floating-tab-icon {
    filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8)) brightness(1.3);
}

.floating-tab-emoji {
    font-size: 28px;
    filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8));
}

.floating-tab-btn:hover .floating-tab-emoji {
    filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8)) brightness(1.3);
}

.floating-tab-tooltip {
    display: none;
    position: absolute;
    left: calc(100% + 8px);
    top: 50%;
    transform: translateY(-50%);
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 4px 10px;
    white-space: nowrap;
    pointer-events: none;
    font-size: 20px;
    font-family: var(--game-font);
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
    z-index: 100;
}

.floating-tab-btn:hover .floating-tab-tooltip {
    display: block;
}

/* ── Floating-strip group popout (Combat / Processing / Unlocks) ──
   The group front reveals its members to the right on hover, mirroring
   the skilling-queue option popout. The popout is a DOM child of the
   front and sits flush (left:100%) so the cursor can cross into it
   without dropping the front's :hover. */
.floating-popout-front { position: relative; overflow: visible; }
.floating-popout-front:hover { z-index: 120; }   /* lift above sibling tabs */

/* One wrapper holds every member. Absolute so it can overflow the 56px
   slot to the right when expanded. */
.floating-popout-members {
    position: absolute;
    left: 0;
    top: 0;
    display: flex;
    flex-direction: row;
}
.floating-popout-member {
    position: relative;
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border-radius: 6px;
    border-left: 3px solid transparent;
    order: 2;             /* non-selected follow the anchor, in member order */
}
.floating-popout-member.active {
    order: 1;             /* selected is the anchor (first, in the strip slot) */
    border-left-color: var(--text-accent);
}
/* Collapsed: only the selected member is shown (the anchor). */
.floating-popout-front:not(:hover) .floating-popout-member:not(.active) {
    display: none;
}
/* Hover: reveal every member to the right, in an expanded panel. */
.floating-popout-front:hover .floating-popout-members {
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 6px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.8);
    padding: 2px;
    gap: 2px;
    z-index: 110;
}
.floating-popout-member:hover { background: var(--bg-cell); }
.floating-popout-member .floating-tab-icon {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
}
/* Member name tooltips sit ABOVE each member (the row expands right, so a
   rightward flyout would overlap neighbors). The front-hover rule hides
   them all; the later equal-specificity member-hover rule reveals only the
   hovered one. */
.floating-popout-member .floating-tab-tooltip {
    /* Anchor to the member's LEFT edge and extend right (not centered) so
       the leftmost/anchor member's tooltip never runs off-screen left.
       Font size inherits the base .floating-tab-tooltip (matches the solo
       vertical-strip tab tooltips). */
    left: 0;
    right: auto;
    top: auto;
    bottom: calc(100% + 6px);
    transform: none;
}
.floating-popout-front:hover .floating-tab-tooltip { display: none !important; }
.floating-popout-member:hover .floating-tab-tooltip { display: block !important; }

/* While a modal is open, keep the floating strip visible OVER the modal
   (above the overlay's z-index 2000) so its group popouts can switch
   members in-place, and hide the redundant in-modal sidebar (its 60px
   width is preserved so the modal body doesn't reflow). The two rails
   are aligned and show the same tabs; the floating strip — which carries
   the popouts and the selected-member icons — becomes the single rail. */
body.modal-open .floating-tab-strip { z-index: 2100; }
/* Only when the strip is expanded — a collapsed strip leaves the in-modal
   sidebar as the nav. */
body.modal-open:not(.side-tabs-collapsed) .modal-tabs { visibility: hidden; }

.floating-tab-hotkey {
    position: absolute;
    bottom: 2px;
    left: 4px;
    font-size: 16px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
    pointer-events: none;
    font-family: var(--game-font);
}

.panel-tab-hotkey {
    position: absolute;
    bottom: 2px;
    left: 4px;
    font-size: 14px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
    pointer-events: none;
    font-family: var(--game-font);
    z-index: 2;
}

.modal-tab-hotkey {
    position: absolute;
    bottom: 2px;
    left: 4px;
    font-size: 16px;
    color: #ffffff;
    text-shadow: 1px 1px 0 #000, 2px 2px 0 rgba(0,0,0,.6);
    line-height: 1;
    pointer-events: none;
    font-family: var(--game-font);
}

.hide-floating-tab-hotkeys .floating-tab-hotkey,
.hide-floating-tab-hotkeys .modal-tab-hotkey { display: none; }
.hide-panel-tab-hotkeys .panel-tab-hotkey { display: none; }

/* Grouped left-panel rows (combat / processing / unlocks) in Settings */
.settings-hotkey-group {
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    margin: 2px 0;
    background: rgba(0, 0, 0, 0.14);
}
.settings-hotkey-group-header {
    font-weight: bold;
    color: var(--text-gold);
    background: rgba(255, 215, 0, 0.05);
    border-bottom: 1px solid var(--border-primary);
}
.settings-group-members {
    padding-left: 18px;   /* indent members under their group */
}
.settings-hotkey-member .settings-hotkey-icon img {
    filter: none;
}

/* Tab reorder via custom drag on the grip in Settings > Hotkeys */
.settings-hotkey-row.tab-dragging {
    opacity: 0.4;
}
.settings-hotkey-row.tab-drag-over {
    box-shadow: inset 0 3px 0 var(--text-gold);
    background: color-mix(in srgb, var(--text-gold) 8%, transparent);
}
.settings-hotkey-grip {
    color: #888;
    font-size: 22px;
    line-height: 1;
    padding: 0 10px 0 0;
    cursor: grab;
    user-select: none;
    letter-spacing: -3px;
    flex-shrink: 0;
}
.settings-hotkey-grip:active {
    cursor: grabbing;
}
.settings-hotkey-row:hover .settings-hotkey-grip {
    color: var(--text-gold);
}
.settings-hotkey-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    margin-right: 12px;
    flex-shrink: 0;
    font-size: 22px;
}
.settings-hotkey-icon img {
    width: 28px;
    height: 28px;
    image-rendering: pixelated;
}

/* Hotkey rebind button states (Settings > Hotkeys) */
.settings-hotkey-bind-btn:hover {
    background: #6b5a00;
    border-color: var(--text-gold);
}
.settings-hotkey-bind-btn.capturing {
    background: #1a3a6a;
    border-color: #4488ff;
    color: #aaccff;
    animation: hotkey-capture-pulse 0.9s ease-in-out infinite;
}
.settings-hotkey-bind-btn.error {
    background: #5a1a1a;
    border-color: #ff6666;
    color: #ff9999;
}
@keyframes hotkey-capture-pulse {
    0%, 100% { opacity: 0.7; }
    50% { opacity: 1; }
}

/* ═══════════════════════════════════════════════════════════════
   Bank Consume Context Menu (bulk potions/crystals)
   ═══════════════════════════════════════════════════════════════ */

.bank-consume-menu {
    position: absolute;
    z-index: 2300;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    padding: 10px 12px;
    min-width: 200px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
    font-family: var(--game-font);
}

.consume-menu-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    font-size: 18px;
    font-weight: 600;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

.consume-menu-header img {
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}

.consume-menu-slider-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.consume-menu-slider {
    flex: 1;
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    background: var(--bg-darkest);
    border-radius: 3px;
    outline: none;
}

.consume-menu-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--text-accent);
    cursor: pointer;
    border: 2px solid var(--border-secondary);
}

.consume-menu-slider::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--text-accent);
    cursor: pointer;
    border: 2px solid var(--border-secondary);
}

.consume-menu-count {
    font-size: 20px;
    font-weight: 700;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    min-width: 36px;
    text-align: center;
}

.consume-menu-btn {
    width: 100%;
    padding: 6px 14px;
    background: var(--text-accent);
    color: var(--bg-dark);
    font-family: var(--game-font);
    font-size: 16px;
    font-weight: bold;
    text-align: center;
    border-radius: 4px;
    cursor: pointer;
    transition: background 0.15s;
}

.consume-menu-btn:hover {
    background: #dabb4e;
}

/* ═══════════════════════════════════════════════════════════════
   Test Panel (dev only - mounted when server reports
   debugCommandsEnabled=true on auth_success).
   Lives inside #ui-container so it scales with the 1920x1080 grid.
   ═══════════════════════════════════════════════════════════════ */

.test-tab {
    position: absolute;
    top: 240px;
    right: 0;
    width: 44px;
    padding: 28px 0;
    background: #4a0a0a;
    border: 3px solid #c84a4a;
    border-right: none;
    border-radius: 8px 0 0 8px;
    color: #ffd1d1;
    font-family: var(--game-font);
    font-size: 28px;
    font-weight: 900;
    letter-spacing: 4px;
    writing-mode: vertical-rl;
    text-align: center;
    cursor: pointer;
    user-select: none;
    z-index: 2147483646;
    text-shadow: 2px 2px 0 #000;
    box-shadow: -2px 2px 12px rgba(0, 0, 0, 0.6);
}
.test-tab:hover {
    background: #6a1010;
    border-color: #ff6a6a;
}

.test-panel {
    position: absolute;
    top: 80px;
    right: 80px;
    width: 480px;
    max-height: 920px;
    background: var(--bg-panel);
    border: 2px solid #c84a4a;
    border-radius: 6px;
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.6);
    font-family: var(--game-font);
    color: var(--text-light);
    z-index: 2147483647;
    display: flex;
    flex-direction: column;
}
.test-panel.hidden { display: none; }

.test-panel-header {
    display: flex;
    align-items: center;
    padding: 8px 12px;
    background: #4a0a0a;
    border-bottom: 2px solid #c84a4a;
    border-radius: 4px 4px 0 0;
    flex: 0 0 auto;
}
.test-panel-title {
    flex: 1;
    color: #ffd1d1;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    text-shadow: 1px 1px 0 #000;
}
.test-panel-close {
    cursor: pointer;
    color: #ffd1d1;
    font-size: 16px;
    padding: 0 6px;
    user-select: none;
}
.test-panel-close:hover { color: #ff6a6a; }

.test-panel-body {
    flex: 1;
    overflow-y: auto;
    padding: 8px 10px 12px;
}

.test-section {
    margin-bottom: 10px;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
}
.test-section-title {
    padding: 6px 10px;
    background: var(--bg-cell);
    color: var(--text-accent);
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    cursor: pointer;
    user-select: none;
    border-radius: 3px 3px 0 0;
}
.test-section-title:hover { background: var(--bg-hover); }
.test-section.collapsed > *:not(.test-section-title) { display: none; }

.test-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
}
.test-row-wrap { flex-wrap: wrap; }
.test-row-label {
    flex: 0 0 100px;
    color: var(--text-light);
    font-size: 12px;
}
.test-num {
    flex: 1;
    min-width: 60px;
    padding: 4px 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 13px;
    outline: none;
}
.test-num:focus { border-color: var(--text-accent); }

.test-btn {
    padding: 4px 10px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 12px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
}
.test-btn:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
    color: var(--text-bright);
}
.test-btn.active {
    background: #4a0a0a;
    border-color: #c84a4a;
    color: #ffd1d1;
}
.test-btn-wide { flex: 1; }
.test-btn-quick { font-size: 11px; padding: 4px 6px; }

.test-quick-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px;
    padding: 6px 10px;
}

.test-target-toggle {
    display: flex;
    gap: 0;
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    overflow: hidden;
}
.test-toggle-btn {
    padding: 4px 12px;
    background: var(--bg-cell);
    border: none;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 12px;
    cursor: pointer;
}
.test-toggle-btn.active {
    background: var(--text-accent);
    color: #000;
    font-weight: 700;
}
.test-toggle-btn:not(.active):hover { background: var(--bg-hover); }

.test-search {
    width: calc(100% - 20px);
    margin: 0 10px 6px;
    padding: 5px 8px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 13px;
    outline: none;
}
.test-search:focus { border-color: var(--text-accent); }

.test-list {
    max-height: 280px;
    overflow-y: auto;
    margin: 0 10px 8px;
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    background: var(--bg-darkest);
}
.test-list-short { max-height: 200px; }

.test-list-row {
    display: grid;
    grid-template-columns: 32px 1fr 36px auto;
    gap: 6px;
    align-items: center;
    padding: 3px 6px;
    border-bottom: 1px solid var(--bg-cell);
    font-size: 12px;
}
.test-list-row:last-child { border-bottom: none; }
.test-list-row:hover { background: var(--bg-hover); }
.test-list-row-click { cursor: pointer; grid-template-columns: 32px 1fr 60px auto; }
.test-list-row-noico { grid-template-columns: 1fr 36px auto; }
.test-mini-btn-all {
    color: #ffd1d1;
    background: #4a0a0a;
    border-color: #c84a4a;
}
.test-mini-btn-all:hover {
    background: #6a1010;
    border-color: #ff6a6a;
    color: #fff;
}

.test-ring-toggle {
    width: 16px;
    height: 16px;
    margin: 0 4px 0 0;
    accent-color: var(--text-accent);
    cursor: pointer;
}
.test-ring-label {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    font-size: 12px;
}
.test-ring-swatch {
    display: inline-block;
    width: 12px;
    height: 12px;
    border: 1px solid var(--border-primary);
    border-radius: 2px;
    flex-shrink: 0;
}
.test-ring-amt {
    color: var(--text-muted);
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    min-width: 50px;
    text-align: right;
}

.test-tabs {
    display: flex;
    gap: 0;
    margin: 6px 10px 8px;
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    overflow: hidden;
}
.test-tab-btn {
    flex: 1;
    padding: 6px 10px;
    background: var(--bg-cell);
    border: none;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 12px;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 1px;
}
.test-tab-btn:not(.active):hover { background: var(--bg-hover); }
.test-tab-btn.active {
    background: var(--text-accent);
    color: #000;
    font-weight: 700;
}
.test-subview { display: block; }

.test-pause-bar {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: 6px 10px;
    margin: -8px -10px 8px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border-primary);
}
.test-pause-btn {
    width: 100%;
    padding: 8px 10px;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
}

.test-list-ico {
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
}
.test-list-ico img {
    max-width: 24px;
    max-height: 24px;
    image-rendering: pixelated;
    filter: drop-shadow(1px 1px 0 #000);
}
.test-list-name {
    color: var(--text-light);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.test-list-chip {
    color: var(--text-gold);
    font-size: 11px;
    text-align: right;
}
.test-list-chip-dim {
    color: var(--text-muted);
    font-size: 10px;
    text-transform: uppercase;
}
.test-list-actions {
    display: flex;
    gap: 2px;
}

.test-mini-btn {
    padding: 2px 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 2px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 10px;
    cursor: pointer;
}
.test-mini-btn:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
    color: var(--text-bright);
}

.test-skill-select {
    flex: 1 1 140px;
    min-width: 130px;
    padding: 4px 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 12px;
    outline: none;
    cursor: pointer;
}
.test-skill-select:hover { border-color: var(--text-accent); }
.test-skill-select:focus { border-color: var(--text-accent); }

/* ═══════════════════════════════════════════════════════════════
   Raid Modal (Phase 2 = lobby UI)
   ═══════════════════════════════════════════════════════════════ */

.raid-subtab-bar .qp-toggle-btn {
    font-size: 24px;
}

.raid-subtab-bar {
    display: flex;
    gap: 6px;
    padding: 8px 12px 0 12px;
}

.raid-subtab-bar .qp-toggle-btn {
    padding: 6px 16px;
    font-size: 16px;
}

.raid-content {
    padding: 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    color: var(--text-light);
    font-family: var(--game-font);
    /* Fill the tab body and own the scroll internally — the invite,
       drop-table, and party panels each scroll within themselves so
       they stop at the bottom of the screen. */
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

.raid-section-label {
    font-size: 18px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 6px;
}

/* Create lobby — centered stack of title + two large card buttons. */
/* ── Open-lobby Join browser ─────────────────────────────────── */
.raid-browse-section {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    padding: 16px;
    color: var(--text-light);
}
.raid-browse-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}
.raid-browse-title {
    flex: 1;
    text-align: center;
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}
/* Map-node preselect notice under the title. */
.raid-browse-hint {
    font-size: 14px;
    color: var(--text-accent);
    text-align: center;
    margin-bottom: 10px;
}
/* Create Lobby + Refresh sit in each column's sort row: match the sort
   buttons and sit together at the right edge of the row. */
.raid-browse-create {
    padding: 4px 12px;
    font-size: 14px;
    margin-left: auto;
}
.raid-browse-refresh {
    padding: 4px 12px;
    font-size: 14px;
}

/* Two-column body: dungeon raids (left) + skilling raids (right). */
.raid-browse-columns {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
    flex: 1;
    min-height: 0;
}
.raid-browse-col {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--bg-dark);
    border: 1px solid var(--border-primary);
    border-radius: 6px;
    padding: 12px;
}
.raid-browse-col-header {
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    text-align: center;
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Column-header flanks: readout (left) / loadout selector or spacer
   (right) share the leftover space so the title stays centered. */
.raid-colhdr-side {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    min-width: 0;
}

.raid-colhdr-title {
    flex: 0 0 auto;
    white-space: nowrap;
}

.raid-colhdr-loadout {
    justify-content: flex-end;
}

.raid-colhdr-readout {
    /* Label ("Avg Lv 99" / "Best Role Lv 99") stacked ABOVE the two
       skill cells, both left-aligned. */
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
}

.raid-colhdr-avg {
    font-size: 14px;
    color: var(--text-gold);
    white-space: nowrap;
}

.raid-colhdr-skill-grid {
    display: grid;
    grid-template-columns: repeat(2, auto);
    gap: 2px 8px;
}
.raid-col-header-icon {
    width: 22px;
    height: 22px;
    vertical-align: -4px;
    margin-right: 4px;
    image-rendering: pixelated;
}
.raid-browse-skilling {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-dim);
    font-style: italic;
    font-size: 16px;
    border: 1px dashed var(--border-primary);
    border-radius: 6px;
}

.raid-browse-sortrow {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}
.raid-sort-carrot {
    margin-left: 5px;
    font-size: 10px;
    vertical-align: 1px;
}

.raid-browse-sortlabel { color: var(--text-dim); font-size: 14px; }
.raid-browse-sortbtn {
    padding: 4px 12px;
    font-size: 14px;
    color: var(--text-light);
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
}
.raid-browse-sortbtn:hover { background: var(--bg-hover); }
.raid-browse-sortbtn.active {
    background: color-mix(in srgb, var(--bar-fill-damage) 55%, black 45%);
    color: var(--text-bright);
    font-weight: bold;
}
/* Direction button groups with the sort buttons (Create Lobby takes the
   right edge via its own margin-left:auto, with Refresh beside it). */
.raid-browse-dir { margin-left: 0; }

.raid-browse-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    align-items: center;   /* center the width-capped rows in the column */
    gap: 6px;
}
.raid-browse-empty {
    color: var(--text-dim);
    font-style: italic;
    text-align: center;
    padding: 24px 0;
}
.raid-browse-row {
    width: 100%;
    max-width: 560px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 12px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 5px;
}
.raid-browse-host {
    flex: 1 1 0;
    min-width: 0;
    font-size: 15px;
    color: var(--text-bright);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Named lobby: lobby name on top, "hosted by X" beneath. */
.raid-browse-host.has-name {
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.raid-browse-lobbyname {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.raid-browse-hostsub {
    min-width: 0;
    font-size: 12px;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Fixed column widths keep every browse row's columns horizontally
   aligned regardless of content (tier label length, member count,
   one-button vs two-button action area). */
.raid-browse-diff {
    flex: 0 0 118px;
    font-size: 14px;
    font-weight: bold;
}
.raid-browse-diff.tier-feeble  { color: var(--tier-feeble); }
.raid-browse-diff.tier-dire    { color: var(--tier-dire); }
.raid-browse-diff.tier-savage  { color: var(--tier-savage); }
.raid-browse-diff.tier-fell    { color: var(--tier-fell); }
.raid-browse-diff.tier-ancient { color: var(--tier-ancient); }
.raid-browse-diff.tier-chaos   { color: #ff6ec7; }
.raid-browse-count {
    flex: 0 0 32px;
    text-align: center;
    font-variant-numeric: tabular-nums;
    color: var(--text-light);
    font-size: 14px;
}
.raid-browse-status {
    flex: 0 0 62px;
    text-align: center;
    font-size: 12px;
    padding: 2px 8px;
    border-radius: 10px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.raid-browse-status.in-lobby {
    color: var(--text-dim);
    background: rgba(255, 255, 255, 0.06);
}
.raid-browse-status.in-raid {
    color: var(--text-bright);
    background: color-mix(in srgb, var(--bar-fill-damage) 40%, transparent);
}
.raid-browse-join {
    position: relative;
    flex: 0 0 auto;
    padding: 5px 16px;
    font-size: 14px;
    color: var(--text-bright);
    background: color-mix(in srgb, var(--tier-feeble) 30%, var(--bg-cell));
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    cursor: pointer;
}
.raid-browse-join:hover {
    background: color-mix(in srgb, var(--tier-feeble) 45%, var(--bg-cell));
}
.raid-browse-join.disabled {
    opacity: 0.5;
    cursor: not-allowed;
    background: var(--bg-cell);
}

/* Browse-while-in-lobby: the row for the lobby you're already in. */
.raid-browse-row.mine {
    border: 1px solid var(--text-gold);
    background: color-mix(in srgb, var(--text-gold) 12%, var(--bg-cell));
}
.raid-browse-continue {
    background: color-mix(in srgb, var(--text-gold) 30%, var(--bg-cell));
}
.raid-browse-continue:hover {
    background: color-mix(in srgb, var(--text-gold) 45%, var(--bg-cell));
}
/* Right-anchored actions column: same width whether it holds
   Continue + Leave (my lobby) or Peek + Join (other lobbies), so the
   columns to its left line up across all rows. */
.raid-browse-actions {
    flex: 0 0 160px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
}
.raid-browse-actions .raid-browse-join {
    padding: 5px 10px;
}
/* Leave button on my own lobby's row: danger tint, mirrors the
   lobby action row's leave/end button. */
.raid-browse-leave {
    background: color-mix(in srgb, var(--bar-fill-damage) 30%, var(--bg-cell));
}
.raid-browse-leave:hover {
    background: color-mix(in srgb, var(--bar-fill-damage) 45%, var(--bg-cell));
}
/* Peek button sits left of Join with a neutral tint. */
.raid-browse-peek {
    background: color-mix(in srgb, var(--tier-dire) 25%, var(--bg-cell));
}
.raid-browse-peek:hover {
    background: color-mix(in srgb, var(--tier-dire) 40%, var(--bg-cell));
}
/* Fortress host-set minimum role level badge in the browser row. */
.raid-browse-minlvl {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 6px;
    font-size: 12px;
    color: var(--text-gold);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
}
/* Peek view: read-only party list + back control. */
.raid-peek-section .raid-browse-header { gap: 12px; align-items: center; }
.raid-peek-party { margin-top: 10px; }
.raid-peek-join-btn {
    background: color-mix(in srgb, var(--tier-feeble) 35%, var(--bg-cell));
}
/* Host min-role-level stepper in the action row. */
.raid-minlvl-ctl { display: flex; align-items: center; gap: 6px; cursor: default; }
.raid-minlvl-btn { cursor: pointer; padding: 0 6px; color: var(--text-bright); }
.raid-minlvl-btn:hover { color: var(--text-gold); }
.raid-minlvl-val { font-size: 13px; }

/* Open/Close lobby toggle in the action row. */
.raid-open-toggle.is-open {
    background: color-mix(in srgb, var(--tier-feeble) 35%, var(--bg-cell));
    color: var(--text-bright);
}

/* Two-column lobby grid: left col holds difficulty/invite/actions,
   right col holds the vertical party list. */
.raid-lobby-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
    /* stretch so both columns get the modal's full inner height;
       each column's panels then scroll within themselves. */
    align-items: stretch;
    flex: 1;
    min-height: 0;
}

.raid-lobby-col {
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-width: 0;
    min-height: 0;
}

/* Difficulty selector */
.raid-diff-section {
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
}

/* Difficulties laid out across the left column. flex:1 per button so
   all five share the row evenly. Internal layout stacks the master
   portrait above the name + Lv line so each button stays narrow. */
.raid-diff-row {
    display: flex;
    flex-direction: row;
    gap: 8px;
}

.raid-diff-btn {
    flex: 1;
    min-width: 0;
    padding: 6px 4px;
    background: var(--bg-cell);
    border: 2px solid var(--border-primary);
    border-radius: 4px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
}

.raid-diff-master {
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    border-radius: 4px;
    image-rendering: pixelated;
    object-fit: cover;
}

.raid-diff-text {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    min-width: 0;
}

.raid-diff-slayicon {
    width: 14px;
    height: 14px;
    image-rendering: pixelated;
    vertical-align: middle;
}

.raid-diff-req {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 13px;
    color: var(--text-light);
}

.raid-diff-btn:hover {
    background: var(--bg-hover);
}

/* Tier accents: outline + name color pulled from existing slay tier
   vars so the difficulty selector visually matches the rest of the
   slay/mob UI. Selected state uses a tier-tinted glow + bg. */
.raid-diff-btn.tier-feeble  { border-color: var(--tier-feeble); }
.raid-diff-btn.tier-dire    { border-color: var(--tier-dire); }
.raid-diff-btn.tier-savage  { border-color: var(--tier-savage); }
.raid-diff-btn.tier-fell    { border-color: var(--tier-fell); }
.raid-diff-btn.tier-ancient { border-color: var(--tier-ancient); }
.raid-diff-btn.tier-chaos   { border-image: linear-gradient(180deg, #ff4444, #ff8800, #ffdd00, #44ff44, #4488ff, #8844ff) 1; }

/* Drop-table tiered-rare selector (T1-T5 + C), difficulty-color-coded. */
.raid-rare-tier-row {
    display: flex; gap: 5px; flex-wrap: wrap;
    padding: 5px 2px;
}
.raid-rare-tier-btn {
    min-width: 34px; padding: 3px 9px;
    background: var(--bg-dark); border: 1px solid var(--border-primary);
    border-radius: 4px; cursor: pointer;
    font-weight: bold; font-size: 14px; line-height: 1;
    color: var(--text-light);
}
.raid-rare-tier-btn:hover { background: var(--bg-cell); }
.raid-rare-tier-btn.tier-feeble  { color: var(--tier-feeble);  border-color: var(--tier-feeble); }
.raid-rare-tier-btn.tier-dire    { color: var(--tier-dire);    border-color: var(--tier-dire); }
.raid-rare-tier-btn.tier-savage  { color: var(--tier-savage);  border-color: var(--tier-savage); }
.raid-rare-tier-btn.tier-fell    { color: var(--tier-fell);    border-color: var(--tier-fell); }
.raid-rare-tier-btn.tier-ancient { color: var(--tier-ancient); border-color: var(--tier-ancient); }
.raid-rare-tier-btn.tier-chaos {
    background: linear-gradient(90deg, #ff4444, #ff8800, #ffdd00, #44ff44, #4488ff, #8844ff);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    border-image: linear-gradient(180deg, #ff4444, #ff8800, #ffdd00, #44ff44, #4488ff, #8844ff) 1;
}
/* Selected: brighten + a light ring that reads on every tier (incl. the
   transparent-text chaos button). */
.raid-rare-tier-btn.selected {
    background: var(--bg-panel);
    box-shadow: 0 0 0 2px var(--text-bright, #fff);
    filter: brightness(1.15);
}
.raid-rare-tier-btn.tier-chaos.selected {
    background: linear-gradient(90deg, #ff4444, #ff8800, #ffdd00, #44ff44, #4488ff, #8844ff);
    -webkit-background-clip: text; background-clip: text;
}

.raid-diff-btn.tier-feeble  .raid-diff-name { color: var(--tier-feeble); }
.raid-diff-btn.tier-dire    .raid-diff-name { color: var(--tier-dire); }
.raid-diff-btn.tier-savage  .raid-diff-name { color: var(--tier-savage); }
.raid-diff-btn.tier-fell    .raid-diff-name { color: var(--tier-fell); }
.raid-diff-btn.tier-ancient .raid-diff-name { color: var(--tier-ancient); }
.raid-diff-btn.tier-chaos   .raid-diff-name { color: #ff6ec7; text-shadow: 0 0 6px rgba(255, 110, 199, 0.6); }

.raid-diff-btn.tier-feeble.selected  { background: rgba(76, 175, 80, 0.18);  box-shadow: 0 0 10px rgba(76, 175, 80, 0.55); }
.raid-diff-btn.tier-dire.selected    { background: rgba(79, 195, 247, 0.18); box-shadow: 0 0 10px rgba(79, 195, 247, 0.55); }
.raid-diff-btn.tier-savage.selected  { background: rgba(255, 152, 0, 0.18);  box-shadow: 0 0 10px rgba(255, 152, 0, 0.55); }
.raid-diff-btn.tier-fell.selected    { background: rgba(244, 67, 54, 0.18);  box-shadow: 0 0 10px rgba(244, 67, 54, 0.55); }
.raid-diff-btn.tier-ancient.selected { background: rgba(156, 39, 176, 0.18); box-shadow: 0 0 10px rgba(156, 39, 176, 0.55); }
.raid-diff-btn.tier-chaos.selected   { background: rgba(255, 110, 199, 0.16); box-shadow: 0 0 12px rgba(255, 110, 199, 0.5); }

.raid-diff-btn.disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.raid-diff-btn.disabled:hover {
    background: var(--bg-cell);
    border-color: var(--border-primary);
}

.raid-diff-btn.readonly {
    cursor: default;
}

.raid-diff-name {
    font-size: 18px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
}

/* Party slots */
.raid-party-section {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.raid-party-row {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;
}

.raid-party-slot {
    position: relative;
    padding: 12px 8px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    text-align: center;
    min-height: 110px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 4px;
}

.raid-party-slot.host {
    border-color: #ffc107;
    box-shadow: 0 0 6px rgba(255, 193, 7, 0.3);
}

.raid-party-slot.offline {
    opacity: 0.55;
}

.raid-party-slot.empty {
    border-style: dashed;
    color: var(--text-dim);
    justify-content: center;
}

.raid-party-avatar {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--bg-hover);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    margin-bottom: 2px;
}

.raid-party-name {
    font-size: 14px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
    white-space: nowrap;
}

.raid-party-host-badge {
    color: #ffc107;
    font-weight: 600;
}

/* Clone slot badge: a host-added stat-copy of themselves. */
.raid-party-clone-badge {
    color: #4fc3f7;
    font-weight: 600;
}

/* "Clone Self" button + cost hint on an empty dungeon slot. */
.raid-clone-add-btn {
    margin-top: 8px;
    padding: 5px 12px;
    background: rgba(79, 195, 247, 0.15);
    border: 1px solid #4fc3f7;
    border-radius: 4px;
    color: #4fc3f7;
    font-size: 13px;
    cursor: pointer;
    transition: background 0.12s;
}

.raid-clone-add-btn:hover {
    background: rgba(79, 195, 247, 0.3);
}

.raid-clone-add-hint {
    margin-top: 5px;
    font-size: 11px;
    color: var(--text-dim);
    text-align: center;
}

/* Gauntlet empty-slot role picker: one button per role to clone into. */
.raid-clone-role-row {
    display: flex;
    gap: 6px;
    margin-top: 6px;
    justify-content: center;
    flex-wrap: wrap;
}

.raid-clone-role-btn {
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(79, 195, 247, 0.12);
    border: 1px solid #4fc3f7;
    border-radius: 4px;
    cursor: pointer;
    transition: background 0.12s;
}

.raid-clone-role-btn:hover {
    background: rgba(79, 195, 247, 0.3);
}

.raid-clone-role-btn img {
    width: 22px;
    height: 22px;
    image-rendering: pixelated;
}

.raid-party-slay {
    font-size: 12px;
    color: var(--text-dim);
}

.raid-party-kick {
    position: absolute;
    top: 4px;
    right: 4px;
    padding: 2px 6px;
    font-size: 11px;
    background: rgba(244, 67, 54, 0.15);
    border: 1px solid #f44336;
    border-radius: 3px;
    color: #f44336;
    cursor: pointer;
}

.raid-party-kick:hover {
    background: rgba(244, 67, 54, 0.3);
}

.raid-party-empty-icon {
    font-size: 28px;
    color: var(--text-dim);
    opacity: 0.5;
}

.raid-party-empty-label {
    font-size: 13px;
    color: var(--text-dim);
}

/* Invite row */
.raid-invite-row {
    display: flex;
    gap: 8px;
    align-items: center;
}

.raid-invite-input {
    flex: 1;
}

/* Two-column control grid under the difficulty selector:
   left = invite-by-name + clan/friends lists, right = action row +
   drop table. */
/* Fills the left lobby column under the difficulty selector so the
   invite + drop-table panels extend to the bottom. The drop-table
   (right) column is wider than the invite (left) column. */
.raid-ctrl-grid {
    display: grid;
    grid-template-columns: 2fr 3fr;
    gap: 16px;
    margin-top: 4px;
    align-items: baseline;
    flex: 1;
    min-height: 0;
}

/* height:100% gives each column the grid's full height even though
   the grid aligns items to baseline (not stretch). */
.raid-ctrl-col {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    min-height: 0;
    height: 100%;
}

/* Invite lists: clan section stacked directly above friends section.
   Sections size to their content (no 50/50 split, so no gap between
   them); the whole list scrolls as one when it overflows. */
.raid-invite-lists {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

.raid-invite-section {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    flex: 0 0 auto;
}

.raid-invite-listscroll {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.raid-invite-listrow {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    padding: 4px 8px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    cursor: pointer;
    transition: background 0.1s, border-color 0.1s;
}

.raid-invite-listrow:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
}

.raid-invite-listrow.offline { opacity: 0.55; }

.raid-invite-listname {
    color: var(--text-light);
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.raid-invite-listbtn {
    color: var(--text-accent);
    font-size: 13px;
    flex: 0 0 auto;
}

/* Brief confirmation flash after sending an invite (Invite → Sent). */
.raid-invite-sent {
    color: var(--text-success, #6fcf6f) !important;
    font-weight: bold;
}

.raid-invite-empty {
    color: var(--text-dim);
    font-size: 13px;
    padding: 4px 8px;
}

/* Drop table for the selected difficulty — reuses the .loot-section /
   .loot-table styling from the mob selection UI so the theme matches.
   Fills the rest of the right control column and scrolls with a
   hidden scrollbar. */
.raid-droptable {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: none;       /* Firefox */
    -ms-overflow-style: none;    /* legacy Edge */
}
.raid-droptable::-webkit-scrollbar {
    display: none;               /* Chrome / Safari / Electron */
}

/* Common-drop qty cell carries a contribution-scaling tooltip. */
.raid-drop-qty-cell {
    position: relative;
    cursor: help;
}

/* Lobby name row above the action row: host input / member read-only. */
.raid-name-row {
    margin-bottom: 6px;
}
.raid-name-edit {
    display: flex;
}
.raid-name-input {
    flex: 1;
    width: auto;
    font-size: 14px;
}
.raid-name-view {
    font-size: 15px;
    color: var(--text-bright);
    padding: 4px 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Action row (start / end / leave) */
.raid-action-row {
    display: flex;
    /* The gauntlet row carries an extra control (the min-role stepper),
       which can overflow the column width. Wrap whole buttons onto a
       second line instead of letting their labels wrap and stretch
       every button in the row to double height. */
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 4px;
}

.raid-action-row .clan-action-btn {
    white-space: nowrap;
}

.raid-start-btn {
    flex: 1;
    background: rgba(76, 175, 80, 0.15);
    border-color: #4caf50;
    color: #4caf50;
}

.raid-start-btn:hover {
    background: rgba(76, 175, 80, 0.3);
}

.raid-start-btn.disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.raid-start-btn.disabled:hover {
    background: rgba(76, 175, 80, 0.15);
}

/* Pre-start countdown pill: shown in the lobby action row while the
   server counts down to auto-start after the 5th player joins. */
.raid-start-countdown {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    padding: 0 14px;
    border: 1px solid #ffb74d;
    border-radius: 4px;
    background: rgba(255, 183, 77, 0.12);
    color: #ffb74d;
    font-weight: bold;
    white-space: nowrap;
}

.raid-end-btn,
.raid-leave-btn {
    color: #f44336;
    border-color: #f44336;
    flex: 0 0 auto;
    min-width: 140px;
}

.raid-end-btn:hover,
.raid-leave-btn:hover {
    background: rgba(244, 67, 54, 0.15);
}

.raid-footer-hint {
    font-size: 13px;
    color: var(--text-dim);
    text-align: center;
    margin-top: 4px;
}

/* ─────────────────────────────────────────────────────────────────
   Vertical party list with combat sprite + stats + paperdoll +
   equip stats + style picker. Each row is a horizontal flex layout:
     sprite | combat stats | paperdoll | equip stats | style picker
   ───────────────────────────────────────────────────────────────── */

.raid-party-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    /* Scrolls within itself so the party panel stops at the bottom
       of the screen instead of pushing the modal taller. */
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

.raid-party-row-item {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    /* 12px -> 4px: freed ~32px across the row so the combat-stats
       column could widen to fit the effective-level badges. */
    gap: 4px;
    padding: 8px 12px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    height: 176px;
    position: relative;
}

/* Left group: name + stat header stacked above the sprite + stats
   columns. Sits to the left of style/paperdoll/equip, which span the
   full row height as siblings. */
.raid-row-leftgroup {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 0 0 auto;
    /* Pin to the body width (sprite 152 + gap 12 + stats 180) so a long
       name truncates with an ellipsis instead of widening the whole row
       and pushing the name off where it has no room to render. */
    width: 344px;
    min-width: 0;
}

/* Sprite + stats columns, under the name/header. */
.raid-row-body {
    display: flex;
    align-items: stretch;
    gap: 4px;
}

.raid-party-row-item.host {
    border-color: #ffc107;
    box-shadow: 0 0 4px rgba(255, 193, 7, 0.25);
}

.raid-party-row-item.self {
    background: rgba(76, 175, 80, 0.06);
    height: 176px;
    overflow: hidden;
}

/* Column 1: vertical info stack (name / combat+slay / respawn / KC /
   loadout). Fixed width so the middle columns keep their space and a
   long name truncates instead of widening the row. */
.raid-row-info {
    flex: 0 0 auto;
    width: 168px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
    align-self: flex-start;
}

.raid-row-info-line {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 16px;
    color: var(--text-light);
    white-space: nowrap;
    overflow: hidden;
    flex: 0 0 auto;
}

.raid-party-row-item.offline {
    opacity: 0.55;
}

.raid-party-row-item.empty {
    border-style: dashed;
    align-items: center;
    justify-content: center;
    color: var(--text-dim);
    min-height: 60px;
}

/* Sprite column — just the sprite portrait box now (name + stat
   header sit full-width above the row body). */
.raid-row-spritecol {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
}

.raid-row-sprite {
    width: 152px;
    height: 156px;
    flex: 0 0 auto;
    background: rgba(0, 0, 0, 0.25);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 4px;
    /* overflow:hidden crops the 2x-scaled sprite's outer transparent
       padding so the character fills the visible box. */
    overflow: hidden;
    align-self: center;
    position: relative;
}

.raid-row-sprite canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* Selected attack-style badge — top-left over the sprite, mirroring
   the mob attack-style badge in the mob selection UI. */
.raid-row-style-badge {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 32px;
    height: 32px;
    image-rendering: pixelated;
    z-index: 1;
    filter: drop-shadow(1px 1px 0 #000);
}

.raid-row-sprite canvas {
    image-rendering: pixelated;
}

/* Combat stats column (2x6 skill grid). Wide enough for the raw level
   plus the full effective-level badge ("47 +18"); the row gap shrank
   from 12px to 4px to make the room. */
.raid-row-stats {
    flex: 0 0 auto;
    width: 172px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-self: center;
}

/* Player name — top of the info column; truncates within its width. */
.raid-row-name {
    font-size: 16px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
    /* Never let the column flex shrink the name line away. */
    flex: 0 0 auto;
    min-width: 0;
}

/* Stat header line: combat icon + level, slay icon + level, respawn,
   all inline on one row under the name. */
.raid-row-header-line {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 18px;
    color: var(--text-light);
    flex: 0 0 auto;
}

.raid-row-header-icon {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
}

/* Per-player wave-respawn reduction. The party's reductions sum
   against the 10s base (min 1s) for the actual between-wave wait. */
.raid-row-respawn-line {
    color: var(--text-light);
}

.raid-row-skill-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2px;
    width: 172px;
}

.raid-row-skill-cell {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 0px 3px;
    background: rgba(0, 0, 0, 0.25);
    border-radius: 2px;
    font-size: 20px;
    color: var(--text-light);
    font-variant-numeric: tabular-nums;
}

.raid-row-skill-cell img {
    width: 22px;
    height: 22px;
    image-rendering: pixelated;
}

/* Unlock bonus descriptions list one effect per line — the strings
   from ItemBonusDescriptions are '\n'-joined and rendered with
   textContent, so pre-line turns each effect into its own line in
   the bank / drop-table / unlocks-grid tooltips. */
.tt-tool-line,
.unlock-tooltip div {
    white-space: pre-line;
}

/* Raw level in the dungeon skill grid. Levels run 1-99, so a bare span
   is one or two digits wide and drags the +N badge left on single-digit
   levels, leaving the green bonuses ragged down the column. A fixed
   two-digit box (the cell already sets tabular-nums, so every digit is
   the same width) right-aligns the number, which puts the "+" at the
   same x in every cell no matter the level. */
.raid-row-skill-lvl {
    min-width: 2ch;
    text-align: right;
}

/* Effective-level bonus (pets + capes + combat tools + talents) next
   to the raw grid level ("47 +9") — the raid engine fights with the
   fully boosted level. Tooltip on the badge itemizes the sources. */
.raid-skill-talent-bonus {
    font-size: 14px;
    color: #4caf50;
    margin-left: 1px;
}

/* Paperdoll: reuse .paperdoll grid positions from BankModal at
   ItemSlotRenderer scale 1.0 (.inv-s10), 40x40 cells. */
.raid-row-paperdoll.paperdoll {
    flex: 0 0 auto;
    display: grid;
    grid-template-columns: repeat(3, 32px);
    grid-template-rows: repeat(5, 32px);
    gap: 2px;
    align-self: center;
}

.raid-row-paperdoll.paperdoll .inv-slot.inv-s10 {
    width: 32px;
    height: 32px;
    background: rgba(0, 0, 0, 0.4);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 2px;
}

.raid-row-paperdoll.paperdoll .inv-slot.inv-s10 img {
    width: 28px;
    height: 28px;
    transform: none;
}

.raid-row-paperdoll.paperdoll .inv-slot.empty {
    background: rgba(0, 0, 0, 0.2);
    border-style: dashed;
}

/* Empty-slot placeholder icons (belt, cape, etc.), dimmed like the
   equipment panel / mob-config paperdolls. */
.raid-row-paperdoll.paperdoll .inv-slot .equip-silhouette { opacity: 0.4; }
.raid-row-paperdoll.paperdoll .inv-slot:not(.empty) .equip-silhouette { display: none; }

/* Tier badge on equipped items reads oversized in the small 32px lobby
   slots; trim it to 14px here only. */
.raid-row-paperdoll.paperdoll .inv-tier-label { font-size: 14px; }

/* Equipment stats panel (right of paperdoll). flex: 0 0 auto so the
   table sizes to its content instead of stretching across leftover
   row width. */
.raid-row-equip-stats {
    flex: 0 0 auto;
    min-width: 200px;
    display: flex;
    flex-direction: column;
    color: var(--text-light);
    font-size: 16px;
}

.raid-row-equip-empty {
    color: var(--text-dim);
    font-style: italic;
    text-align: center;
    padding: 20px;
}

.raid-row-equip-style {
    color: var(--text-bright);
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
}

.raid-row-equip-table {
    border-collapse: collapse;
    width: 100%;
    font-variant-numeric: tabular-nums;
}

.raid-row-equip-table th {
    text-align: right;
    color: var(--text-bright);
    font-size: 10px;
    font-weight: normal;
    padding: 2px 6px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.raid-row-equip-table th:first-child {
    text-align: left;
}

.raid-row-equip-table td {
    padding: 2px 6px;
    text-align: right;
    color: var(--text-light);
}

.raid-row-equip-table td:first-child {
    text-align: left;
    color: var(--text-bright);
}

.raid-row-equip-table td img {
    width: 14px;
    height: 14px;
    vertical-align: middle;
    margin-right: 4px;
    image-rendering: pixelated;
}

/* CRIT column (chance / damage) — gold so it reads apart from the
   ATK/DEF/STR bonuses. */
.raid-row-equip-table td.raid-row-equip-crit-cell {
    color: var(--text-gold);
}

/* Style picker column (vertical list on the far right) */
/* Loadout selector / readonly chip — last item in the info column. */
.raid-row-style-col {
    flex: 0 0 auto;
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 2px;
}
.raid-row-style-col .raid-style-btn {
    font-size: 13px;
    padding: 3px 6px;
    flex: 0 0 auto;
}
.raid-row-style-col .raid-style-btn img { width: 16px; height: 16px; }

/* ── Gauntlet lobby: the 10-skill grid doubles as the role selector.
   Each pair row (fish/cook, mine/smith, ...) is one role: your own
   rows are clickable, the picked pair highlights, the rest dim. ── */
.raid-gauntlet-skill-grid {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 150px;
}
.raid-role-skill-row {
    position: relative;
    display: grid;
    grid-template-columns: 22px 1fr 1fr;
    gap: 2px;
    border-radius: 3px;
    border: 1px solid transparent;
    transition: background 0.1s, border-color 0.1s;
}

/* Best-pair arrow gutter, just left of the gather icon. Both slots
   always render (hidden when off) so green sits left and gold right
   in the same spot on every row. */
.raid-role-arrows {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 1px;
}
.raid-role-arrow {
    font-size: 10px;
    line-height: 1;
    text-shadow: 1px 1px 0 #000;
}
.raid-role-arrow.green { color: #5cbf60; }
.raid-role-arrow.gold { color: #FFD700; }
.raid-role-arrow.off { visibility: hidden; }
.raid-role-skill-row.clickable { cursor: pointer; }
.raid-role-skill-row.clickable:hover {
    border-color: var(--text-accent);
}
.raid-role-skill-row.role-active {
    background: rgba(199, 125, 255, 0.22);
    border-color: #C77DFF;
}
.raid-role-skill-row.role-active .raid-row-skill-cell {
    color: var(--text-bright);
}
.raid-role-skill-row.role-dim .raid-row-skill-cell { opacity: 0.45; }
.raid-role-skill-row.role-dim.clickable:hover .raid-row-skill-cell { opacity: 1; }

/* Gauntlet yield preview: raw → processed item + stat points each. */
.raid-row-gauntlet-preview {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    min-width: 200px;
    padding: 4px 8px;
    background: rgba(0, 0, 0, 0.25);
    border-radius: 3px;
}
.raid-gauntlet-pv-items {
    display: flex;
    align-items: center;
    gap: 6px;
}
.raid-gauntlet-pv-arrow {
    color: var(--text-muted);
    font-size: 16px;
}
.raid-gauntlet-pv-line {
    font-size: 12px;
    color: var(--text-muted);
    text-align: center;
}
.raid-gauntlet-pv-value {
    font-size: 14px;
    color: var(--text-bright);
    font-variant-numeric: tabular-nums;
}

/* Movement row (Vigor + active move potion): never dims with role pick,
   and gets a subtle top divider so it reads as separate from the 5
   selectable role rows above it. */
.raid-role-skill-row.raid-gauntlet-move-row {
    opacity: 1;
}
.raid-gauntlet-move-potion { justify-content: flex-start; }
.raid-gauntlet-move-none { color: var(--text-muted); font-size: 16px; }

/* Role strengths: gather + process bonuses for the picked role, right of
   the yield preview. */
.raid-row-gauntlet-strengths {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0px;
    min-width: 132px;
    padding: 4px 8px;
}
.raid-gauntlet-str-block {
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.raid-gauntlet-str-head {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 15px;
    color: var(--text-bright);
}
.raid-gauntlet-str-head img {
    width: 20px; height: 20px;
    image-rendering: pixelated;
}
.raid-gauntlet-str-line {
    font-size: 13px;
    color: var(--text-light);
    padding-left: 25px;
    font-variant-numeric: tabular-nums;
}
/* Active movement-potion line in the Misc block — temporary buff. */
.raid-gauntlet-str-line.raid-gauntlet-str-potion {
    color: var(--text-success);
}

.raid-style-btn {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 3px 8px;
    background: var(--bg-hover);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-size: 18px;
    cursor: pointer;
    user-select: none;
    transition: background 0.1s, border-color 0.1s;
}

.raid-style-btn img {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
}

.raid-style-btn:hover {
    background: rgba(255, 255, 255, 0.08);
    border-color: var(--text-accent);
}

.raid-style-btn.selected {
    background: rgba(199, 125, 255, 0.2);
    border-color: #C77DFF;
    color: var(--text-bright);
}

.raid-style-btn.readonly {
    cursor: default;
    opacity: 0.7;
}

.raid-style-btn.readonly:hover {
    background: var(--bg-hover);
    border-color: var(--border-primary);
}

.raid-row-unpicked {
    position: absolute;
    bottom: 4px;
    right: 12px;
    font-size: 11px;
    color: #ffc107;
    font-style: italic;
}

.raid-party-row-item {
    position: relative;
}

.raid-party-row-item .raid-party-kick {
    position: absolute;
    top: 6px;
    right: 6px;
    padding: 2px 8px;
    background: rgba(244, 67, 54, 0.15);
    border: 1px solid #f44336;
    border-radius: 3px;
    color: #f44336;
    font-size: 11px;
    cursor: pointer;
}


/* ═══════════════════════════════════════════════════════════════
   Windowed Panels - opt-in mode (SettingsModal.panelsWindowed).
   Adds a draggable titlebar to each bottom-right tab panel and
   lets multiple panels be open at once.
   ═══════════════════════════════════════════════════════════════ */

/* Titlebar - hidden by default, shown when body.panels-windowed is on.
   Lives as the first child of each panel; positioned absolutely so it
   doesn't disturb the existing flex layout of the panel body. */
.panel-titlebar {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 24px;
    align-items: center;
    justify-content: space-between;
    padding: 0 6px;
    background: var(--bg-cell);
    border-bottom: 1px solid var(--border-primary);
    border-radius: 4px 4px 0 0;
    cursor: move;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    /* No z-index. WindowedPanels appends the titlebar as the last
       DOM child so it paints above panel body siblings via DOM
       order. Avoids creating a stacking context that would trap
       inner content tooltips beneath it. */
}

.panel-titlebar-label {
    font-size: 13px;
    color: var(--text-bright);
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
    letter-spacing: 0.5px;
}

.panel-titlebar-btns {
    display: flex;
    gap: 4px;
}

.panel-titlebar-btn {
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    color: var(--text-light);
    cursor: pointer;
    padding: 0;
    line-height: 0;
}

.panel-titlebar-btn:hover {
    background: var(--bg-hover);
    border-color: var(--text-accent);
    color: var(--text-bright);
}

.panel-titlebar-close:hover {
    background: rgba(180, 40, 40, 0.55);
    border-color: rgba(220, 80, 80, 0.85);
    color: #ffd0d0;
}

/* Minimize button carries two glyphs — a horizontal line (collapse)
   and an empty box (restore). Show one based on whether the panel
   is minimized, so a single button reads as "minimize" or "restore"
   without any JS icon swapping. */
.panel-titlebar-min .icon-min { display: inline; }
.panel-titlebar-min .icon-restore { display: none; }
.panel-minimized .panel-titlebar-min .icon-min { display: none; }
.panel-minimized .panel-titlebar-min .icon-restore { display: inline; }

/* Minimize only makes sense once a dock panel is floating. The dock
   holds one panel at a time, so a minimized panel sitting there would
   occupy the slot while showing nothing; hide the button until it has
   been dragged out. The standalone HUDs (chat, task, info, and the two
   raid HUDs) own their own corner of the screen instead of the dock
   slot, so .panel-min-attached keeps the button available in place. */
body.panels-windowed .panel-titlebar-min {
    display: none;
}
body.panels-windowed .panel-floating .panel-titlebar-min,
body.panels-windowed .panel-min-attached .panel-titlebar-min {
    display: flex;
}

/* ── Activated state ────────────────────────────────────────── */
body.panels-windowed .panel-titlebar {
    display: flex;
}

/* Push panel content down to make room for the titlebar. Original
   panels use padding: 6px; titlebar is 24px tall so the new
   padding-top is 30px. Height grows from 440px to 464px so the
   visible content area inside is unchanged. */
body.panels-windowed .tasks-panel,
body.panels-windowed .slay-tasks-panel,
body.panels-windowed .skills-panel,
body.panels-windowed .quests-panel,
body.panels-windowed .inventory-panel,
body.panels-windowed .diary-panel,
body.panels-windowed .equipment-panel,
body.panels-windowed .friends-panel,
body.panels-windowed .barter-panel {
    padding-top: 30px;
    height: 464px;
}

/* Chat panel makes room for the titlebar. Chat is a flex column with
   its own height (default 220px, user-resizable + persisted), so we
   only add padding-top - the flex children compress slightly to make
   room. Users can drag the top edge to grow it back. */
body.panels-windowed .chat-panel {
    padding-top: 24px;
}

/* Top-left Info HUD (online count, name, location, state). The base
   panel has `pointer-events: none` so clicks pass through to the map
   except on the online row. In windowed mode we re-enable pointer
   events so the titlebar is grabbable, and add padding-top to clear
   the titlebar. Existing 8px top padding stacks under the 24px
   titlebar -> 32px total. */
body.panels-windowed .ingame-hud {
    pointer-events: auto;
    padding-top: 32px;
}

/* Task HUD: the outer .floating-current-task is a transparent
   positioning shell; the visible card is .float-task-inner. Pushing
   24px of padding on the outer makes room for the titlebar above
   the inner card. */
body.panels-windowed .floating-current-task {
    padding-top: 24px;
}

/* The Task HUD is centered on the playable area via
   `transform: translateX(-50%)`. While floating (user has dragged it),
   that transform would offset the inline left/top we write, so clear
   it. The outer is 340px wide; inline left then represents the actual
   left edge in pixels. Reverts automatically on Reattach (class drops).
   `transition: none` overrides the base `transition: left 0.3s ease`
   (used for the auto-recenter slide) — without this, every pointer-move
   during drag triggers a 300ms ease and the HUD lags the cursor. */
body.panels-windowed .floating-current-task.panel-floating {
    transform: none;
    transition: none;
}

/* Raid DPS panel (no dock tab, like the Task/Info HUDs). Re-enable
   pointer events so the titlebar is grabbable, add padding-top to clear
   the 24px titlebar (base padding-top is 6px), push the left tab rail
   and the right collapse toggle below the titlebar, and clear the
   centering transform while floating. */
body.panels-windowed .raid-contrib-hud {
    pointer-events: auto;
    padding-top: 30px;
}
body.panels-windowed .raid-contrib-hud .raid-contrib-tabs,
body.panels-windowed .raid-contrib-hud > .hud-collapse-btn,
body.panels-windowed .gauntlet-hud > .hud-collapse-btn {
    top: 24px;
}
body.panels-windowed .raid-contrib-hud.panel-floating {
    transform: none;
}

/* Fortress HUD (the skilling raid's meter). Structural twin of the Raid
   DPS panel above: same top-center anchor, same centering transform,
   same pointer-events:none base, and no dock tab either. */
body.panels-windowed .gauntlet-hud {
    pointer-events: auto;
    padding-top: 30px;
}
body.panels-windowed .gauntlet-hud.panel-floating {
    transform: none;
}

/* Cursor hint - the titlebar itself owns the drag, but the rest of
   the panel border area still feels grabbable to users. We leave
   it as the default cursor to avoid hijacking clicks on panel
   content. */

/* Minimized state - hide every direct child except the titlebar
   and shrink the panel to just the titlebar's height. Each panel
   keeps its border + background so the minimized strip is still
   visually distinct. */
.panel-minimized > *:not(.panel-titlebar) {
    display: none !important;
}

body.panels-windowed .tasks-panel.panel-minimized,
body.panels-windowed .slay-tasks-panel.panel-minimized,
body.panels-windowed .skills-panel.panel-minimized,
body.panels-windowed .quests-panel.panel-minimized,
body.panels-windowed .inventory-panel.panel-minimized,
body.panels-windowed .diary-panel.panel-minimized,
body.panels-windowed .equipment-panel.panel-minimized,
body.panels-windowed .friends-panel.panel-minimized,
body.panels-windowed .barter-panel.panel-minimized,
body.panels-windowed .chat-panel.panel-minimized,
body.panels-windowed .floating-current-task.panel-minimized,
body.panels-windowed .ingame-hud.panel-minimized,
body.panels-windowed .raid-contrib-hud.panel-minimized,
body.panels-windowed .gauntlet-hud.panel-minimized {
    /* !important needed because chat persists its resized width/height
       as inline style (scapewatch_chatHeight in localStorage). Inline
       style normally beats class selectors, so without !important the
       minimized height never takes effect. */
    height: 26px !important;
    min-height: 26px !important;
    padding: 0 !important;
    padding-top: 24px !important;
    min-width: 80px;
}

/* Task HUD shell has no background of its own (the visible card is
   .float-task-inner). When minimized that card is hidden, leaving the
   titlebar floating alone. The titlebar already paints its own
   background + border, so nothing else needed. */


/* ═══════════════════════════════════════════════════════════════
   Dashboard panel (DashboardPanel.js)

   An always-floating analytics window. Independent of the global
   "Windowed Panels" mode, so it carries its own titlebar/drag chrome
   styled to match. z-index 9000 keeps it above the game modals
   (GoM 2000, combat/chest 2200) as an always-on overlay, but below
   the global tooltip layer (99999) so its own tooltips still show.
   ═══════════════════════════════════════════════════════════════ */
.dashboard-panel {
    position: absolute;
    width: 340px;
    height: 460px;
    z-index: 1500;
    display: flex;
    flex-direction: column;
    background: var(--bg-panel);
    border: 1px solid var(--border-primary);
    border-radius: 6px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
    font-family: var(--game-font);
    font-size: 12px;
    color: var(--text-light);
    overflow: hidden;
    user-select: none;
    -webkit-user-select: none;
}

.dashboard-titlebar {
    flex-shrink: 0;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 6px;
    background: var(--bg-cell);
    border-bottom: 1px solid var(--border-primary);
    border-radius: 5px 5px 0 0;
    cursor: move;
    touch-action: none;
}
.dashboard-titlebar-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.5px;
    color: var(--text-accent);
}
.dashboard-titlebar-btns {
    display: flex;
    align-items: center;
    gap: 2px;
}
.dashboard-titlebar-btn {
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    color: var(--text-muted);
    cursor: pointer;
}
.dashboard-titlebar-btn:hover {
    background: var(--bg-hover);
    color: var(--text-light);
}
.dashboard-titlebar-close:hover {
    background: rgba(180, 40, 40, 0.55);
    border-color: rgba(220, 80, 80, 0.85);
    color: #ffd0d0;
}
/* Minimize button shows the line glyph when expanded, the box when
   minimized — driven by the .dashboard-minimized class on the panel. */
.dashboard-titlebar-min .dash-icon-restore { display: none; }
.dashboard-minimized .dashboard-titlebar-min .dash-icon-min { display: none; }
.dashboard-minimized .dashboard-titlebar-min .dash-icon-restore { display: inline; }

/* Minimized: collapse to just the titlebar. */
.dashboard-panel.dashboard-minimized {
    height: auto;
}
.dashboard-panel.dashboard-minimized .dashboard-tabbar,
.dashboard-panel.dashboard-minimized .dashboard-content {
    display: none;
}

.dashboard-tabbar {
    flex-shrink: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 4px;
    background: var(--bg-dark);
    border-bottom: 1px solid var(--border-primary);
}
.dashboard-tab {
    padding: 3px 7px;
    background: var(--bg-panel);
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    color: var(--text-muted);
    font-family: var(--game-font);
    font-size: 11px;
    cursor: pointer;
    transition: background 0.1s, color 0.1s;
}
.dashboard-tab:hover {
    background: var(--bg-hover);
    color: var(--text-light);
}
.dashboard-tab.active {
    background: var(--bg-cell);
    border-color: var(--text-accent);
    color: var(--text-bright);
}

.dashboard-content {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 8px;
}
/* Hide the scrollbar but keep scrolling, matching the game's panels. */
.dashboard-content::-webkit-scrollbar { display: none; }
.dashboard-content { scrollbar-width: none; -ms-overflow-style: none; }

.dashboard-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    height: 100%;
    text-align: center;
}
.dashboard-placeholder-title {
    font-size: 16px;
    font-weight: 700;
    color: var(--text-accent);
}
.dashboard-placeholder-sub {
    font-size: 11px;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 1px;
}

/* ── Shared dashboard content primitives ── */
.dash-row {
    display: flex;
    gap: 4px;
    margin-bottom: 8px;
}
.dash-cell {
    flex: 1;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 6px 4px;
    text-align: center;
}
.dash-cell-val {
    font-size: 18px;
    font-weight: 700;
    color: var(--text-gold);
}
.dash-cell-label {
    font-size: 9px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-top: 2px;
}
.dash-subtle {
    font-size: 10px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 8px;
}
.dash-near {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    background: rgba(255, 165, 0, 0.08);
    border: 1px solid #FFA500;
    border-radius: 4px;
    padding: 5px 7px;
    margin-bottom: 8px;
    font-size: 11px;
    font-weight: 700;
    color: #FFA500;
}
.dash-near-skill { color: var(--text-light); font-weight: 600; }
.dash-near-pct { color: #FFA500; }
.dash-dot { color: var(--text-dark); }

/* ── XP tab: per-skill rows ── */
.dash-skill-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.dash-skill-row {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 4px 6px;
}
.dash-skill-row.active { border-color: var(--text-success); }
.dash-skill-row.near { border-color: #FFA500; }
.dash-skill-icon {
    width: 22px;
    height: 22px;
    image-rendering: pixelated;
    flex-shrink: 0;
}
.dash-skill-main {
    flex: 1;
    min-width: 0;
}
.dash-skill-top {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 6px;
}
.dash-skill-name {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-light);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dash-skill-row.active .dash-skill-name { color: var(--text-success); }
.dash-skill-lv {
    font-size: 10px;
    color: var(--text-muted);
    flex-shrink: 0;
}
.dash-bar {
    margin-top: 3px;
    height: 4px;
    background: var(--bg-darkest);
    border-radius: 2px;
    overflow: hidden;
}
.dash-bar-fill {
    height: 100%;
    background: var(--bar-fill-progress);
    border-radius: 2px;
}
.dash-skill-row.near .dash-bar-fill { background: #FFA500; }
.dash-skill-stats {
    flex-shrink: 0;
    text-align: right;
    min-width: 56px;
}
.dash-skill-gained {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-accent);
}
.dash-skill-rate {
    font-size: 10px;
    color: var(--text-success);
}
/* Live session timer riding in the "XP this session" section header —
   normal case + dim, so only the label keeps the uppercase treatment. */
.dash-subtle-timer {
    color: var(--text-dim);
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
}
/* XP tab: "Total" summary row — no icon/bar, brighter border, bright total. */
.dash-skill-row.total { border-color: var(--border-primary); }
.dash-skill-row.total .dash-skill-name { color: var(--text-muted); }
.dash-skill-row.total .dash-skill-gained { color: var(--text-bright); }

/* ── Pets tab ── */
.dash-pet-row {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 4px 6px;
}
.dash-pet-row.complete { opacity: 0.5; }
.dash-pet-icon {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
    flex-shrink: 0;
}
.dash-pet-name {
    flex: 1;
    min-width: 0;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-light);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dash-pet-pips { flex-shrink: 0; letter-spacing: 1px; }
.dash-pip { color: var(--text-disabled); font-size: 11px; }
.dash-pip.on { color: var(--text-light); }
.dash-pip.shiny.on { color: var(--tier-dire); }
.dash-pet-eta {
    flex-shrink: 0;
    font-size: 10px;
    color: var(--text-success);
    min-width: 86px;
    text-align: right;
}
.dash-pet-row.complete .dash-pet-eta { color: var(--text-muted); }

/* ── Goals tab ── */
.dash-goal-form {
    display: flex;
    gap: 4px;
    margin-bottom: 8px;
}
.dash-goal-skill,
.dash-goal-target {
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 11px;
    padding: 3px 4px;
}
.dash-goal-skill { flex: 1; min-width: 0; }
.dash-goal-target { width: 48px; }
.dash-goal-add {
    background: var(--bg-hover);
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    color: var(--text-bright);
    font-family: var(--game-font);
    font-size: 11px;
    padding: 3px 10px;
    cursor: pointer;
}
.dash-goal-add:hover { background: var(--border-primary); }
.dash-goal-row {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 4px 6px;
}
.dash-goal-row.complete { opacity: 0.6; }
.dash-goal-del {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    color: var(--text-muted);
    font-size: 11px;
    cursor: pointer;
    padding: 0;
}
.dash-goal-del:hover {
    background: rgba(180, 40, 40, 0.55);
    border-color: rgba(220, 80, 80, 0.85);
    color: #ffd0d0;
}

/* ── Queue + Drops rows ── */
.dash-q-row {
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 4px 6px;
}
.dash-q-row.active { border-color: var(--text-success); }
.dash-q-top {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 6px;
}
.dash-q-name {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-light);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dash-q-row.active .dash-q-name { color: var(--text-success); }
.dash-q-xp {
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-accent);
}
.dash-q-sub {
    display: flex;
    justify-content: space-between;
    gap: 6px;
    margin-top: 2px;
    font-size: 10px;
    color: var(--text-muted);
}
.dash-q-sub span {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Name + tags wrapper: name ellipsizes, tags keep their size. */
.dash-q-left {
    display: flex;
    align-items: baseline;
    gap: 4px;
    min-width: 0;
}
/* Task tags (Low Mat / Out / Lucky). Material colors match the in-game
   task panel's own shortage colors; Lucky uses the theme success token. */
.dash-tag {
    flex-shrink: 0;
    font-size: 8px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 1px 4px;
    border-radius: 2px;
}
.dash-tag-low { color: #ff8c00; background: rgba(255, 140, 0, 0.12); }
.dash-tag-out { color: #ff3232; background: rgba(255, 50, 50, 0.14); }
.dash-tag-lucky { color: var(--text-success); background: rgba(136, 255, 136, 0.12); }
/* Per-slot alternatives (the other reroll options). */
.dash-q-alts-btn {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-dim);
    font-size: 10px;
    font-weight: 600;
    padding: 4px 0 0;
}
.dash-q-alts-btn:hover { color: var(--text-light); }
.dash-q-alts {
    margin-top: 3px;
    padding-top: 3px;
    border-top: 1px solid var(--border-secondary);
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.dash-q-alt {
    display: flex;
    justify-content: space-between;
    gap: 6px;
    font-size: 10px;
    color: var(--text-dim);
}
.dash-q-alt-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dash-q-alt-xp {
    flex-shrink: 0;
    font-family: monospace;
    color: var(--text-success);
}
/* Estimated (↗) vs realized (▲/▼) XP/hr line under a queue row. */
.dash-q-rate {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 2px;
    font-size: 10px;
    color: var(--text-dim);
}
.dash-cal-up { color: var(--text-success); }
.dash-cal-dn { color: #ff8c00; }
/* Material-shortage banner (matches the in-game 'out' red). */
.dash-warn {
    display: flex;
    align-items: center;
    gap: 6px;
    background: rgba(255, 50, 50, 0.10);
    border: 1px solid #ff3232;
    border-radius: 4px;
    padding: 6px 9px;
    margin-bottom: 8px;
    font-size: 11px;
    color: var(--text-light);
}
.dash-warn strong { color: #ff3232; }
/* ── Slay tab ── */
.dash-slay-stats {
    margin-top: 4px;
    font-size: 10px;
    color: var(--text-success);
}
.dash-slay-next {
    margin-top: 8px;
    padding: 6px 8px;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-left: 3px solid var(--text-gold);
    border-radius: 4px;
    font-size: 11px;
    color: var(--text-muted);
}
.dash-slay-next strong { color: var(--text-bright); }
.dash-slay-next .dash-slay-eta { color: var(--text-success); }
.dash-slay-master {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 4px 6px;
    font-size: 11px;
}
.dash-slay-master.current {
    border-color: var(--text-gold);
    background: rgba(200, 168, 62, 0.08);
}
.dash-slay-master.locked { opacity: 0.45; }
.dash-slay-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}
.dash-slay-name {
    color: var(--text-light);
    font-weight: 600;
    white-space: nowrap;
}
.dash-slay-who { color: var(--text-dim); font-weight: 400; font-size: 10px; }
.dash-slay-range {
    margin-left: auto;
    color: var(--text-muted);
    font-size: 10px;
    flex-shrink: 0;
}
.dash-slay-master.current .dash-slay-range { color: var(--text-bright); font-weight: 700; }
.dash-drop-search {
    width: 100%;
    box-sizing: border-box;
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 11px;
    padding: 4px 6px;
    margin-bottom: 8px;
}
/* Drop-hunt result cards (best source + odds + distribution curve). */
.dash-drop-card {
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-left: 3px solid var(--bar-fill-damage, #F44336);
    border-radius: 4px;
    padding: 5px 8px;
    margin-bottom: 6px;
}
.dash-drop-src {
    font-size: 11px;
    color: var(--text-muted);
    margin: 2px 0;
}
.dash-drop-src strong { color: var(--text-bright); }
.dash-drop-rate { color: var(--text-success); font-family: monospace; }
.dash-drop-more {
    font-size: 10px;
    color: var(--text-dim);
    margin-top: 2px;
}
.dash-drop-chart {
    display: block;
    width: 100%;
    max-width: 260px;
    margin-top: 6px;
}
.dash-drop-top-right { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.dash-pin-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 11px;
    line-height: 1;
    padding: 0;
    opacity: 0.35;
    filter: grayscale(1);
}
.dash-pin-btn:hover { opacity: 0.7; }
.dash-pin-btn.on { opacity: 1; filter: none; }
.dash-drop-pinned { margin-bottom: 8px; }
/* ── Food tab ── */
.dash-dmg { color: #ff3232; }
.dash-food-row {
    display: flex;
    align-items: baseline;
    gap: 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 4px 6px;
    font-size: 11px;
}
.dash-food-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-light);
    font-weight: 600;
}
.dash-food-ct { color: var(--text-bright); font-weight: 700; flex-shrink: 0; }
.dash-food-hp { color: var(--text-success); flex-shrink: 0; font-family: monospace; }
.dash-food-avg { color: var(--text-dim); flex-shrink: 0; font-size: 10px; }
/* Pet ETA urgency colors (soon → far). */
.dash-eta-soon { color: var(--text-success); }
.dash-eta-mid { color: var(--text-gold); }
.dash-eta-far { color: #FFA500; }
/* Raid tab: locked (Slay-gated) raid rows. */
.dash-raid-locked { opacity: 0.5; }

/* ── Live raid / Fortress view ── */
.dash-raid-live-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-danger, #ff6b6b);
    margin-bottom: 6px;
}
.dash-warn-line { color: var(--text-danger, #ff6b6b); }
/* Per-player damage / deposit rows — bar fill sits behind the label. */
.dash-raid-dps {
    position: relative;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 7px;
    margin-bottom: 3px;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    font-size: 11px;
    overflow: hidden;
}
.dash-raid-dps-fill {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    background: var(--bar-fill-progress);
    opacity: 0.28;
    z-index: 0;
}
.dash-raid-dps > span { position: relative; z-index: 1; }
.dash-raid-dps-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-light);
}
.dash-raid-dps-share { color: var(--text-muted); flex-shrink: 0; }
.dash-raid-dps-dmg { color: var(--text-bright); font-weight: 700; flex-shrink: 0; }
.dash-raid-dps.me .dash-raid-dps-name { color: var(--text-success); font-weight: 700; }
.dash-raid-dps.me { border-color: var(--text-success); }
.dash-raid-dps.dead .dash-raid-dps-name { text-decoration: line-through; color: var(--text-muted); }
/* Fortress Force rows: name · army value · vs enemy. */
.dash-fort-stat {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 7px;
    margin-bottom: 2px;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    font-size: 11px;
}
.dash-fort-stat-name { flex: 0 0 82px; font-weight: 600; }
.dash-fort-stat-mine { color: var(--text-bright); font-weight: 700; min-width: 34px; }
.dash-fort-stat-vs { color: var(--text-muted); flex: 1; text-align: right; }
.dash-fort-role {
    color: var(--text-muted);
    font-size: 10px;
    flex-shrink: 0;
    white-space: nowrap;
}

/* ── Raid loadout ranking (lifetime cards) ── */
.dash-raid-rank-top { font-size: 10px; margin-top: 3px; line-height: 1.4; }
.dash-raid-rank-label { color: var(--text-muted); }
.dash-raid-rank-name { font-weight: 600; }
.dash-raid-rank-dps { color: var(--text-dim); margin-left: 3px; }
.dash-raid-rank-runners { color: var(--text-dim); }
.dash-raid-rank-toggle {
    cursor: pointer;
    color: var(--text-muted);
    text-decoration: underline;
    white-space: nowrap;
}
.dash-raid-rank-toggle:hover { color: var(--text-bright); }
.dash-raid-rank-list {
    margin-top: 3px;
    border-top: 1px solid var(--border-secondary);
    padding-top: 3px;
}
.dash-raid-rank-item {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 10px;
    padding: 1px 0;
}
.dash-raid-rank-i { color: var(--text-dim); width: 14px; flex-shrink: 0; }
.dash-raid-rank-n { font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-raid-rank-d { color: var(--text-muted); width: 48px; text-align: right; flex-shrink: 0; }

/* ── Loot / Barter / Log rows ── */
.dash-loot-head {
    display: flex;
    align-items: center;
    gap: 6px;
    justify-content: space-between;
    margin-bottom: 6px;
}
.dash-loot-search { flex: 1; margin-bottom: 0; }
/* Loot grouped by source: one card per source, item icon grid inside. */
.dash-loot-groups { display: flex; flex-direction: column; gap: 6px; }
.dash-loot-group {
    background: var(--bg-cell);
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    padding: 6px 8px;
}
.dash-loot-group-head {
    font-size: 12px;
    font-weight: 700;
    color: var(--text-light);
    margin-bottom: 6px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dash-loot-grid { display: flex; flex-wrap: wrap; gap: 6px; }
.dash-loot-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    width: 40px;
}
.dash-loot-icon {
    width: 28px;
    height: 28px;
    image-rendering: pixelated;
    background: var(--bg-darkest);
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
}
.dash-loot-qty { font-size: 10px; font-weight: 700; color: var(--text-bright); }
.dash-clear-btn {
    background: var(--bg-hover);
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 10px;
    padding: 2px 8px;
    cursor: pointer;
}
.dash-clear-btn:hover { background: var(--border-primary); }
.dash-buy { color: var(--tier-feeble); font-weight: 700; }
.dash-sell { color: var(--text-gold); font-weight: 700; }
/* Barter deal-quality tags + filter row. */
.dash-tag-good { color: var(--text-success); background: rgba(136, 255, 136, 0.12); }
.dash-tag-poor { color: #ff3232; background: rgba(255, 50, 50, 0.14); }
.dash-tag-milestone { color: var(--text-gold); background: rgba(200, 168, 62, 0.14); }
.dash-barter-filter {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 8px;
}
.dash-barter-seg { flex-shrink: 0; margin-bottom: 0; }
.dash-barter-search { flex: 1; margin-bottom: 0; }
/* Quest current-step line (visit/kill + description). */
.dash-q-step {
    display: flex;
    align-items: baseline;
    gap: 4px;
    margin-top: 4px;
    font-size: 10px;
}
.dash-q-step-text {
    color: var(--text-muted);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dash-step-kill { color: #ff3232; background: rgba(255, 50, 50, 0.14); }
.dash-step-visit { color: #4FC3F7; background: rgba(79, 195, 247, 0.14); }
/* Scroll remaining-waypoint chips. */
.dash-scroll-wps {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 6px;
}
.dash-scroll-wp {
    font-size: 10px;
    color: var(--text-light);
    background: var(--bg-darkest);
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    padding: 2px 6px;
    white-space: nowrap;
}
.dash-scroll-done { font-size: 10px; font-weight: 600; color: var(--text-success); margin-top: 6px; display: inline-block; }
.dash-log-row {
    display: flex;
    align-items: baseline;
    gap: 6px;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 4px 6px;
}
.dash-log-dot { flex-shrink: 0; font-size: 9px; }
.dash-log-text {
    flex: 1;
    min-width: 0;
    font-size: 11px;
    color: var(--text-light);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dash-log-ago {
    flex-shrink: 0;
    font-size: 10px;
    color: var(--text-muted);
}

/* ── Settings tab ── */
.dash-set-label {
    font-size: 10px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin: 10px 0 4px;
}
.dash-set-label:first-child { margin-top: 0; }
.dash-set-seg { display: flex; gap: 4px; }
.dash-seg-btn {
    flex: 1;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    color: var(--text-muted);
    font-family: var(--game-font);
    font-size: 11px;
    padding: 4px;
    cursor: pointer;
}
.dash-seg-btn.active {
    background: var(--bg-hover);
    border-color: var(--text-accent);
    color: var(--text-bright);
}
.dash-set-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 5px 8px;
    margin-bottom: 3px;
    font-size: 11px;
    color: var(--text-light);
    cursor: pointer;
}
.dash-switch {
    width: 28px;
    height: 14px;
    border-radius: 7px;
    background: var(--bg-darkest);
    border: 1px solid var(--border-secondary);
    position: relative;
    flex-shrink: 0;
}
.dash-switch::after {
    content: '';
    position: absolute;
    top: 1px;
    left: 1px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--text-muted);
    transition: left 0.1s, background 0.1s;
}
.dash-switch.on { background: var(--bar-fill-progress); border-color: var(--text-success); }
.dash-switch.on::after { left: 15px; background: #fff; }
.dash-tabcfg-row {
    display: flex;
    align-items: center;
    gap: 4px;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 3px 6px;
    margin-bottom: 3px;
}
.dash-tabcfg-name { flex: 1; min-width: 0; font-size: 11px; color: var(--text-light); }
.dash-tabcfg-btn {
    flex-shrink: 0;
    background: var(--bg-panel);
    border: 1px solid var(--border-secondary);
    border-radius: 3px;
    color: var(--text-muted);
    font-family: var(--game-font);
    font-size: 10px;
    padding: 2px 6px;
    cursor: pointer;
}
.dash-tabcfg-btn:disabled { opacity: 0.35; cursor: default; }
.dash-tabcfg-btn.on { color: var(--text-success); border-color: var(--text-success); }

/* ── Settings sliders ── */
.dash-set-slider {
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    padding: 5px 8px 7px;
    margin-bottom: 3px;
}
.dash-set-slider-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 11px;
    color: var(--text-light);
    margin-bottom: 4px;
}
.dash-set-slider-val { color: var(--text-bright); font-size: 11px; }
.dash-set-slider input[type=range] {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 5px;
    border-radius: 3px;
    background: var(--bg-darkest);
    border: 1px solid var(--border-secondary);
    outline: none;
    cursor: pointer;
}
.dash-set-slider input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: var(--bar-fill-progress);
    border: 1px solid var(--text-success);
    cursor: pointer;
}
.dash-set-slider input[type=range]::-moz-range-thumb {
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: var(--bar-fill-progress);
    border: 1px solid var(--text-success);
    cursor: pointer;
}

/* ── Settings data (export / import / reset) ── */
.dash-set-data { display: flex; gap: 4px; }
.dash-data-btn {
    flex: 1;
    background: var(--bg-cell);
    border: 1px solid var(--border-secondary);
    border-radius: 4px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 11px;
    padding: 5px 6px;
    cursor: pointer;
}
.dash-data-btn:hover { border-color: var(--text-bright); color: var(--text-bright); }
.dash-data-btn.danger {
    color: var(--text-danger, #ff3232);
    border-color: var(--text-danger, #ff3232);
}

/* ── Toast notification ── */
.dash-toast {
    position: absolute;
    bottom: 80px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 9500;
    background: var(--bg-panel);
    border: 1px solid var(--text-accent);
    border-radius: 6px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.6);
    color: var(--text-bright);
    font-family: var(--game-font);
    font-size: 13px;
    padding: 8px 16px;
    pointer-events: none;
    opacity: 1;
    transition: opacity 0.5s;
}
.dash-toast.out { opacity: 0; }

/* Dashboard launcher — a tab-strip entry that toggles the floating
   DashboardPanel instead of opening a modal tab. It lives in BOTH the
   always-visible floating tab strip (.floating-tab-btn) and the
   in-modal sidebar (.tab-btn), mirroring every other tab. Hidden until
   the feature is enabled in Settings.

   Placement uses flex `order`, NOT DOM position: TAB_ORDER.apply()
   (main.js) keeps the saved tab order by re-appending every [data-tab]
   button to the end of each strip. This launcher has no data-tab, so a
   reorder would otherwise strand it at the FRONT. A high `order` keeps
   it visually last (right after the final tab icon) regardless of DOM
   order. No margin-top:auto — an auto top margin on a first-position
   child bottom-aligns the whole strip (the earlier bug). */
.tab-btn.dashboard-launcher,
.floating-tab-btn.dashboard-launcher {
    order: 999;
}
.tab-btn.dashboard-launcher.hidden,
.floating-tab-btn.dashboard-launcher.hidden {
    display: none;
}


/* ═══════════════════════════════════════════════════════════════
   World Map overlay (MapOverlay.js)

   Mounted inside #ui-container with z-index 1000 so it renders
   above every default HUD element (chat z:5, ingame-hud z:80,
   floating-tab-strip z:100, panel-tab-bar z:100, floating-current
   -task z:500, raid-contrib-hud z:505). The body.map-active class
   hides the HUD chrome that should be obscured and lifts the
   pieces that stay visible (Tasks queue, windowed-mode Slay queue)
   above the map. window-controls at z:99999 sit above the map
   naturally; GroupOfModals overlay at z:2000 covers the map when
   opened so modal dialogs still display correctly.
   ═══════════════════════════════════════════════════════════════ */
.map-overlay {
    position: absolute;
    left: 0;
    top: 0;
    width: 1920px;
    height: 1080px;
    z-index: 1000;
    pointer-events: auto;
}

/* When the map is up, hide the chat box, the top-left info HUD,
   the side modal strip, the top-center task widget, potions, raid
   damage meter, and the auto-recenter pill. The bottom-right tab
   group (panel-tab-bar + all panels + HP bar) stays interactive
   and gets lifted above the map so the player can freely swap
   between tasks/slay/skills/etc while the map is up. */
body.map-active .chat-panel,
body.map-active .ingame-hud,
body.map-active .floating-tab-strip,
body.map-active .floating-current-task,
body.map-active .active-potions-panel,
body.map-active .raid-contrib-hud,
body.map-active .recenter-camera-btn {
    display: none !important;
}

/* Lift the entire bottom-right group above the map z-index so the
   tab bar, HP bar, and whichever panels PanelManager has open all
   stay clickable. We don't force any specific panel's visibility;
   that stays the user's choice via the tab bar. */
body.map-active .hp-bar,
body.map-active .tasks-panel,
body.map-active .slay-tasks-panel,
body.map-active .skills-panel,
body.map-active .inventory-panel,
body.map-active .diary-panel,
body.map-active .equipment-panel,
body.map-active .quests-panel,
body.map-active .friends-panel,
body.map-active .barter-panel {
    z-index: 1100;
}

/* Tab bar sits one layer above the panels so its hover tooltips
   (.panel-tab-tooltip floats above the bar via bottom:100%+8px)
   render over the active panel instead of disappearing behind it. */
body.map-active .panel-tab-bar {
    z-index: 1200;
}

/* Dimmed backdrop fills the letterboxed gutters so the map view
   reads as a discrete surface instead of bleeding into the game
   world underneath. */
.map-overlay-bg {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background: #08080f;
}

.map-overlay-img {
    position: absolute;
    image-rendering: auto;
    -webkit-user-drag: none;
    user-select: none;
    pointer-events: none;
}

/* Dynamic layer for friend dots, routes, weather. Sized to the
   full 1920x1080 UI plane so drawing math matches everything else. */
.map-overlay-canvas {
    position: absolute;
    left: 0;
    top: 0;
    width: 1920px;
    height: 1080px;
    pointer-events: none;
}

/* Floating filter panel. Top-left of the overlay, out of the way
   of the top-right HUD chrome (window controls + active potions). */
.map-filter-panel {
    position: absolute;
    left: 80px;
    top: 12px;
    min-width: 200px;
    padding: 10px 14px 12px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    font-family: var(--game-font);
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    z-index: 1;
}

.map-filter-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 18px;
    color: var(--text-gold);
    font-weight: 600;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--border-primary);
    padding-bottom: 4px;
    cursor: pointer;
    user-select: none;
}

/* Collapse caret on the right of the title. Points down when the
   body is open, rotates to point right when collapsed. */
.map-filter-caret {
    font-size: 12px;
    color: var(--text-light);
    transition: transform 0.12s;
}
.map-filter-caret::before {
    content: '\25BC'; /* down triangle */
}
.map-filter-panel.collapsed .map-filter-caret {
    transform: rotate(-90deg);
}

/* Collapsed: hide the body, and drop the title's bottom border so the
   bar reads as a single compact pill. */
.map-filter-panel.collapsed .map-filter-body {
    display: none;
}
.map-filter-panel.collapsed .map-filter-title {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

/* Node search box. */
.map-filter-search {
    width: 100%;
    box-sizing: border-box;
    margin-bottom: 8px;
    padding: 5px 8px;
    background: var(--bg-input, rgba(0, 0, 0, 0.35));
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    color: var(--text-light);
    font-family: var(--game-font);
    font-size: 14px;
    outline: none;
}
.map-filter-search::placeholder {
    color: var(--text-dim);
}
.map-filter-search:focus {
    border-color: var(--text-accent);
}

/* Route legend column: sits just to the right of the filter panel and
   collapses the same way (caret in its title bar). */
.map-legend-panel {
    position: absolute;
    left: 318px;
    top: 12px;
    min-width: 180px;
    max-width: 260px;
    padding: 10px 14px 12px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-radius: 6px;
    font-family: var(--game-font);
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    z-index: 1;
}

.map-legend-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 18px;
    color: var(--text-gold);
    font-weight: 600;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--border-primary);
    padding-bottom: 4px;
    cursor: pointer;
    user-select: none;
}

.map-legend-panel.collapsed .map-filter-caret {
    transform: rotate(-90deg);
}
.map-legend-panel.collapsed .map-legend-body {
    display: none;
}
.map-legend-panel.collapsed .map-legend-title {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

/* Cap the body so a long route scrolls instead of running off-screen. */
.map-legend-body {
    max-height: 60vh;
    overflow-y: auto;
}

.map-legend-section + .map-legend-section {
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid var(--border-primary);
}

.map-legend-route {
    font-size: 13px;
    color: var(--text-dim);
    margin-bottom: 3px;
}

/* Animate toggle: plays the route one leg at a time. Sits above the
   first entry. */
.map-legend-animate {
    display: inline-block;
    margin-bottom: 6px;
    padding: 3px 10px;
    background: var(--bg-input, rgba(0, 0, 0, 0.35));
    border: 1px solid var(--border-primary);
    border-radius: 4px;
    color: var(--text-light);
    font-size: 13px;
    cursor: pointer;
    user-select: none;
}
.map-legend-animate:hover {
    border-color: var(--text-accent);
}
.map-legend-animate.active {
    background: var(--text-accent);
    color: #1a1205;
    border-color: var(--text-accent);
}

.map-legend-entry {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 0;
    font-size: 14px;
    cursor: pointer;
    border-radius: 3px;
}
/* Hovering a row, or the row of the currently animated leg, highlights
   it to match the leg isolated on the map. */
.map-legend-entry:hover,
.map-legend-entry.active {
    background: rgba(255, 255, 255, 0.12);
}

.map-legend-dot {
    flex: 0 0 auto;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 1px solid rgba(0, 0, 0, 0.85);
}

.map-legend-label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.map-legend-empty {
    font-size: 14px;
    color: var(--text-dim);
}

/* Total route distance read-out. Sits above the filter checkboxes,
   refreshed live from MapOverlay._draw(). */
.map-filter-distance {
    font-size: 14px;
    color: var(--text-bright);
    margin-bottom: 6px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--border-primary);
}

.map-filter-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    cursor: pointer;
    font-size: 15px;
}

.map-filter-row:hover .map-filter-label {
    color: var(--text-bright);
}

.map-filter-checkbox {
    width: 16px;
    height: 16px;
    cursor: pointer;
    accent-color: var(--text-accent);
}

.map-filter-label {
    transition: color 0.12s;
}

/* Settings hotkey row "Other" section: extras rows omit the drag
   grip; reserve the same horizontal slot so icon + label still
   line up with the reorderable rows above. */
.settings-hotkey-grip-empty {
    visibility: hidden;
}


/* Raid-lobby blurb: a small lip hanging off the bottom of the floating
   task HUD (same panel theme as .float-task-inner — panel background,
   2px side/bottom border, rounded bottom corners, no top border so it
   reads as part of the box above). */
.float-raid-lobby {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: fit-content;
    margin: 0 auto;
    padding: 3px 14px;
    background: var(--bg-panel);
    border: 2px solid var(--border-primary);
    border-top: none;
    border-radius: 0 0 6px 6px;
    font-size: 13px;
    font-family: var(--game-font);
    color: var(--text-light);
    text-shadow: 1px 1px 0 #000;
    cursor: pointer;
}

.float-raid-lobby:hover {
    background: var(--bg-hover);
    color: var(--text-bright);
}

.float-raid-lobby-icon {
    width: 16px;
    height: 16px;
    image-rendering: pixelated;
}

.float-raid-lobby-count {
    color: var(--text-gold);
}


/* ── PvP Modal ─────────────────────────────────────────────── */
.pvp-layout { display: flex; flex-direction: column; gap: 10px; height: 100%; padding: 12px; overflow: hidden; }
.pvp-toggle { display: flex; gap: 6px; flex-shrink: 0; }
.pvp-cols { display: flex; gap: 16px; flex: 1; min-height: 0; }
.pvp-left { flex: 1; min-width: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.pvp-right { flex: 1; min-width: 0; overflow-y: auto; }
.pvp-section-title { font-family: 'Cinzel', serif; font-weight: 700; font-size: 15px; color: var(--text-gold); margin-top: 4px; }
.pvp-hint { font-size: 12px; color: var(--text-muted); line-height: 1.4; }
.pvp-balance-row { display: flex; align-items: center; gap: 6px; font-size: 15px; font-weight: 700; color: var(--tier-fell); }
.pvp-balance-row img { width: 20px; height: 20px; }
.pvp-pair-row { font-size: 12px; padding: 3px 8px; border-radius: 4px; background: var(--bg-cell); }
.pvp-ok { color: var(--text-success); }
.pvp-bad { color: var(--tier-fell); }
.pvp-status { display: flex; flex-direction: column; gap: 4px; }
.pvp-donate-row { display: flex; gap: 6px; align-items: center; }
.pvp-donate-input { width: 110px; padding: 5px 8px; background: var(--bg-dark); border: 1px solid var(--border-primary); border-radius: 4px; color: var(--text-light); font-family: var(--game-font); }
.pvp-btn { padding: 5px 12px; background: var(--bg-cell); border: 1px solid var(--tier-fell); border-radius: 4px; color: var(--text-light); cursor: pointer; font-size: 12px; font-family: var(--game-font); }
.pvp-btn:hover { background: var(--bg-hover); }
.pvp-btn:disabled { opacity: 0.45; cursor: default; }
.pvp-attack-btn { padding: 2px 10px; }
.pvp-mini-btn { padding: 0 6px; background: var(--bg-cell); border: 1px solid var(--border-primary); border-radius: 3px; color: var(--text-dim); cursor: pointer; font-size: 10px; font-family: var(--game-font); }
.pvp-mini-btn:disabled { opacity: 0.3; cursor: default; }
.pvp-member-list { display: flex; flex-direction: column; gap: 3px; }
.pvp-member-row { display: flex; align-items: center; gap: 8px; padding: 4px 8px; background: var(--bg-cell); border-radius: 4px; font-size: 12px; }
.pvp-member-name { flex: 1; color: var(--text-light); }
.pvp-member-status { font-size: 11px; }
.pvp-confirm-dialog { max-width: 560px; }
.pvp-confirm-side { margin: 8px 0; font-size: 12px; color: var(--text-light); line-height: 1.5; text-align: left; }
.pvp-confirm-weapons { color: var(--text-muted); font-size: 11px; }
.ctx-menu-attack { color: var(--tier-fell); font-weight: 700; }

/* ═══════════════════════════════════════════════════════════════
   Ledger — welcome-back progress diff (Unlocks tab sub-view).
   Lives inside the scrolling Unlocks content box; everything is sized
   in the 1920x1080 space and colored only through theme tokens.
   Layout: top bar (title + period tabs), then a 400px left column
   (portrait, milestones) and a right column (skills grid, loot).
   ═══════════════════════════════════════════════════════════════ */
#tab-ledger { padding: 12px 16px; }
/* The page fills the tab; the loot column scrolls on its own (below) while
   Milestones and Skills stay put. If those two outgrow the tab, the tab
   itself still scrolls. */
.ledger { display: flex; flex-direction: column; gap: 12px; height: 100%; min-height: 0; font-family: var(--game-font); color: var(--text-light); }
.ledger-tn { font-variant-numeric: tabular-nums; }
.ledger-up { color: var(--bar-fill-progress, #88FF88); }
.ledger-dn { color: var(--bar-fill-damage, #b8442d); }
.ledger-zero { color: var(--text-dark); }
.ledger-lbl { font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--text-accent); }
.ledger-cnt { font-size: 13px; color: var(--text-muted); }

.ledger-top { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 4px 4px 0; }
/* In the modal header (GroupOfModals._ledgerHeaderSlot): fills the space between the tab name and the close button. */
.modal-header .ledger-header-slot { display: flex; align-items: center; flex: 1; min-width: 0; margin: 0 16px; }
.modal-header .ledger-header-slot .ledger-top { flex: 1; min-width: 0; padding: 0; }
.modal-header .ledger-header-slot .ledger-title { font-size: 20px; }
.ledger-top-left { display: flex; align-items: baseline; gap: 16px; min-width: 0; }
.ledger-title { font-family: "Cinzel", serif; font-size: 24px; font-weight: 700; color: var(--text-gold); white-space: nowrap; }
.ledger-sub { font-size: 14px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ledger-tabs { display: flex; gap: 4px; flex: none; align-items: center; }
.ledger-opens { display: flex; gap: 14px; margin-right: 14px; }
.ledger-tab { padding: 8px 14px; border: 1px solid var(--border-primary); border-radius: 4px; background: var(--bg-cell); color: var(--text-dim); font-size: 14px; cursor: pointer; }
.ledger-tab:hover { background: var(--bg-hover); color: var(--text-light); }
.ledger-tab.active { color: var(--text-bright); border-color: var(--border-secondary); background: var(--bg-hover); }

.ledger-body { display: grid; grid-template-columns: 380px 640px 1fr; grid-template-rows: minmax(0, 1fr); gap: 14px; align-items: start; flex: 1; min-height: 0; }
.ledger-col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.ledger-col-right, .ledger-col-mid { max-height: 100%; min-height: 0; }
.ledger-loot, .ledger-skills { display: flex; flex-direction: column; min-height: 0; }
/* Skills caps to the column like Loot does; its header and Total row pin to the scroll edges. */
.ledger-skills > .ledger-sec-h { flex: none; }
.ledger-skills > .ledger-sec-body { overflow-y: auto; min-height: 0; }
.ledger-skills .ledger-table th { position: sticky; top: 0; z-index: 1; }
.ledger-skills .ledger-total-row td { position: sticky; bottom: 0; z-index: 1; }
.ledger-loot > .ledger-sec-h, .ledger-loot > .ledger-loot-bar { flex: none; }
.ledger-loot > .ledger-sec-body { overflow-y: auto; min-height: 0; padding-bottom: 4px; }
.ledger-sec { background: var(--bg-dark); border: 1px solid var(--border-primary); border-radius: 6px; padding: 12px 14px; }
.ledger-sec-h { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.ledger-sec-right { display: flex; align-items: center; gap: 12px; }
.ledger-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-muted); cursor: pointer; }
.ledger-toggle:hover { color: var(--text-light); }

/* Left column: portrait + milestones */
.ledger-hero .ledger-sec-body { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 4px 0 2px; }
.ledger-portrait { width: 192px; height: 192px; display: flex; align-items: flex-end; justify-content: center; }
.ledger-portrait-canvas { width: 192px; height: 192px; image-rendering: pixelated; }
.ledger-name { font-family: "Cinzel", serif; font-size: 24px; font-weight: 700; color: var(--text-gold); }
.ledger-badges { display: flex; gap: 10px; margin-top: 4px; }
.ledger-badge { display: flex; align-items: center; gap: 6px; font-size: 14px; padding: 5px 10px; background: var(--bg-cell); border: 1px solid var(--border-primary); border-radius: 4px; }
.ledger-badge img { width: 20px; height: 20px; image-rendering: pixelated; }
.ledger-badge .ledger-up { font-size: 12px; font-weight: 700; }

.ledger-miles .ledger-sec-body { display: flex; flex-direction: column; gap: 2px; }
.ledger-row { display: grid; grid-template-columns: 26px 1fr auto; align-items: center; gap: 10px; padding: 4px 8px; border-radius: 4px; font-size: 14px; min-height: 30px; }
.ledger-row:nth-child(odd) { background: var(--bg-cell); }
.ledger-row img { width: 22px; height: 22px; image-rendering: pixelated; }
.ledger-row-k { color: var(--text-light); display: flex; flex-direction: column; line-height: 1.15; }
.ledger-row-note { font-size: 11px; color: var(--text-dim); }
/* Row tooltips (label / change / where you stand now): numbers right-aligned;
   a label + value line (Dungeon tiers) spreads to both edges. */
.tooltip .tt-line.ledger-tt-num, .tooltip .ledger-tt-num { text-align: right; font-variant-numeric: tabular-nums; }
.tooltip .tt-line.ledger-tt-kv { display: flex; justify-content: space-between; gap: 28px; }
.ledger-row-v { font-weight: 700; color: var(--text-light); text-align: right; }
.ledger-row.quiet { opacity: .55; }

/* Middle column: skills table (same bones as the hiscores table) */
.ledger-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 15px; }
.ledger-table th { background: var(--bg-cell); padding: 6px 8px; text-align: left; color: var(--text-bright); text-shadow: 1px 1px 0 #000; border-bottom: 2px solid var(--border-primary); font-weight: 700; }
.ledger-table th.ledger-th-num { text-align: right; }
.ledger-table td { padding: 2px 8px; border-bottom: 1px solid var(--bg-panel); color: var(--text-light); white-space: nowrap; }
.ledger-table tbody tr:hover { background: var(--bg-cell); }
.ledger-td-icon { width: 30px; padding-right: 0 !important; }
.ledger-td-icon img { width: 24px; height: 24px; image-rendering: pixelated; vertical-align: middle; }
.ledger-td-name { color: var(--text-light); }
.ledger-td-num { text-align: right; font-variant-numeric: tabular-nums; }
.ledger-td-level { color: var(--text-bright); font-weight: 700; }
.ledger-skill-row.quiet td { color: var(--text-dark); }
.ledger-skill-row.quiet .ledger-td-level { color: var(--text-dim); font-weight: 400; }
.ledger-skill-row.quiet img { opacity: .5; }
.ledger-total-row td { background: var(--bg-cell); border-top: 2px solid var(--border-secondary); border-bottom: 0; font-weight: 700; color: var(--text-bright); padding: 4px 8px; }
.ledger-total-row .ledger-td-name { color: var(--text-bright); }

/* Right column: loot — the bank grid and the plain shared inv-slot
   (no extra chrome); only the quantity badge changes: signed, bright
   text for gained, light text for used. */
.ledger-loot-bar { background: transparent; border-bottom: 0; padding: 0 0 10px; gap: 6px; flex-wrap: wrap; }
.ledger-loot-bar .bank-search { font-size: 15px; width: 150px; padding: 4px 8px; }
.ledger-loot-bar .bank-filter-btn, .ledger-loot-bar .bank-filter-menu-btn { font-size: 14px; padding: 4px 9px; }
.ledger-lootgrid.bank-grid { grid-template-columns: repeat(auto-fill, 57px); gap: 8px; }
.ledger-slot > .inv-qty { color: var(--text-bright); }
.ledger-slot-used > .inv-qty { color: var(--text-light); }
.ledger-empty { color: var(--text-muted); font-size: 14px; padding: 6px 2px; }

/* ── Ledger return screens (LedgerReturn.js) ─────────────────────
   Card over the world on login / return from idle, and the night
   receipt after Wake Up. Both reuse the .ledger-* section styles. */
.ledger-return-overlay { position: absolute; top: 0; left: 0; width: 1920px; height: 1080px; background: rgba(0, 0, 0, .72); display: flex; align-items: center; justify-content: center; z-index: 6800; font-family: var(--game-font); }
.ledger-card { width: 1240px; max-height: 1000px; overflow-y: auto; background: var(--bg-panel); border: 2px solid var(--border-secondary); border-radius: 10px; box-shadow: 0 0 0 2px rgba(0,0,0,.5), 0 18px 60px rgba(0,0,0,.6); padding: 22px 26px 18px; display: flex; flex-direction: column; gap: 14px; color: var(--text-light); }
.ledger-card-head { display: flex; flex-direction: column; gap: 10px; padding: 2px 4px 8px; }
.ledger-card-id { display: flex; align-items: center; gap: 14px; }
.ledger-card-portrait { width: 96px; height: 96px; flex: 0 0 96px; display: flex; align-items: flex-end; justify-content: center; }
.ledger-card-portrait .ledger-portrait-canvas { width: 96px; height: 96px; }
.ledger-card-titles { min-width: 0; }
.ledger-card-title { font-family: "Cinzel", serif; font-size: 20px; font-weight: 700; color: var(--text-gold); line-height: 1.1; }
.ledger-card-name { font-family: "Cinzel", serif; font-size: 26px; font-weight: 700; color: var(--text-gold); line-height: 1.1; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ledger-card-sub { font-size: 14px; color: var(--text-muted); margin-top: 6px; }
.ledger-card-badges { display: flex; flex-wrap: wrap; gap: 8px; }
.ledger-card-foot { display: flex; justify-content: flex-end; gap: 10px; border-top: 1px solid var(--border-primary); padding-top: 12px; }
.ledger-btn { font-family: var(--game-font); font-size: 15px; padding: 8px 18px; border-radius: 6px; border: 1px solid var(--border-secondary); background: var(--bg-cell); color: var(--text-light); cursor: pointer; }
.ledger-btn:hover { background: var(--bg-hover); color: var(--text-bright); }
.ledger-btn-primary { background: var(--bg-hover); color: var(--text-bright); font-weight: 700; }

.ledger-compact { display: grid; grid-template-columns: 360px 1fr; gap: 14px; align-items: start; }
/* Loot bodies: a little bottom room so the 1.5x item art (which spills a
   fraction of a pixel past its slot) never trips a scrollbar;
   LedgerView.fitScroll then picks auto/hidden from the real overflow. */
.ledger-sec-loot > .ledger-sec-body { padding-bottom: 4px; }
/* Return card: Skills shows ten rows and Loot four before scrolling in place, so the card stays on screen.
   The table header and Total row pin to the scroll edges (opaque, so rows pass underneath unseen). */
.ledger-card .ledger-sec-skills > .ledger-sec-body { max-height: 380px; overflow-y: auto; }
.ledger-card .ledger-sec-loot > .ledger-sec-body { max-height: 260px; overflow-y: auto; }
.ledger-card .ledger-table th { position: sticky; top: 0; z-index: 1; }
.ledger-card .ledger-total-row td { position: sticky; bottom: 0; z-index: 1; }
.ledger-compact-right { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.ledger-compact .ledger-sec { padding: 10px 12px; }
.ledger-compact .ledger-row { padding: 3px 8px; min-height: 28px; font-size: 14px; }

.ledger-night { position: absolute; top: 0; left: 0; width: 1920px; height: 1080px; box-sizing: border-box; padding: 26px 40px 30px; background: #000; display: flex; flex-direction: column; gap: 14px; z-index: 100000; font-family: var(--game-font); color: var(--text-light); user-select: none; }
.ledger-night-top { flex: none; display: flex; align-items: center; min-height: 40px; }
.ledger-night-title { font-family: "Cinzel", serif; font-size: 26px; color: var(--text-accent); letter-spacing: .06em; }
/* Same shape as the full Ledger: overview + milestones | skills | loot.
   Absolute so its bottom edge can stop above the Wake Up / Open Ledger
   slot (set inline by showNight from the sleep screen's button position). */
.ledger-night-body { position: absolute; left: 40px; right: 40px; top: 84px; bottom: 360px; display: grid; grid-template-columns: 420px 640px 1fr; grid-template-rows: minmax(0, 1fr); gap: 14px; }
.ledger-night-col { display: flex; flex-direction: column; gap: 12px; min-width: 0; min-height: 0; }
/* The sleep screen's stack (same classes, same gap, centred the same way, so frame one matches the screen just left).
   Once settled in the top-left the scene shrinks and the note collapses, leaving room for Milestones beneath. */
.ledger-night-stack { flex: none; display: flex; flex-direction: column; align-items: center; gap: 18px; transition: transform .7s cubic-bezier(.22, .61, .36, 1); }
.ledger-night-pre .ledger-night-stack { transition: none; }
.ledger-night-stack .sleep-scene { transform-origin: top center; transition: transform .7s cubic-bezier(.22, .61, .36, 1), height .7s cubic-bezier(.22, .61, .36, 1); }
.ledger-night:not(.ledger-night-pre) .ledger-night-stack .sleep-scene { height: 200px; transform: scale(.77); }
.ledger-night-stack .sleep-note, .ledger-night-stack .sleep-status { overflow: hidden; max-height: 80px; transition: opacity .3s ease, max-height .5s ease, margin .5s ease; }
.ledger-night:not(.ledger-night-pre) .ledger-night-stack .sleep-note, .ledger-night:not(.ledger-night-pre) .ledger-night-stack .sleep-status { opacity: 0; max-height: 0; margin-top: -18px; }
.ledger-night-stack .ledger-portrait-canvas { width: 192px; height: 192px; image-rendering: pixelated; }
/* Wake Up / Open Ledger: fixed where the sleep screen's Wake Up was (top set inline). */
.ledger-night-actions { position: absolute; left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 10px; }
.ledger-night-actions .sleep-wake-btn { margin-top: 0; }
.ledger-night-open { white-space: nowrap; font-family: "Cinzel", serif; font-size: 16px; color: var(--text-dark); background: transparent; border: 1px solid transparent; border-radius: 5px; padding: 6px 14px; cursor: pointer; }
.ledger-night-open:hover { color: var(--text-bright); border-color: var(--border-primary); }
/* The receipt fades in once the stack has started moving. */
.ledger-night-fade { opacity: 1; transition: opacity .45s ease .3s; }
.ledger-night-pre .ledger-night-fade { opacity: 0; transition: none; }
/* Leaving (Wake Up on the receipt): same choreography as the sleep screen's exit. */
.ledger-night.ledger-night-leaving { opacity: 0; pointer-events: none; transition: opacity .6s ease .8s; }
.ledger-night.ledger-night-leaving .ledger-night-fade { opacity: 0; transition: opacity .3s ease; }
.ledger-night.ledger-night-leaving .sleep-timer, .ledger-night.ledger-night-leaving .ledger-night-actions { opacity: 0; transform: translateY(14px); transition: opacity .45s ease, transform .45s ease; }
.ledger-night.ledger-night-leaving .ledger-night-actions { transform: translateX(-50%) translateY(14px); }
.ledger-night.ledger-night-leaving .ledger-night-stack .sleep-scene { transform: translateY(-90px) scale(.85); opacity: 0; transition: transform .8s ease-in .45s, opacity .7s ease .5s; }
/* Returning (Sleep on the receipt): the receipt fades while the stack glides home and the scene grows back; the sleep screen then takes over frame-for-frame. */
.ledger-night.ledger-night-returning { pointer-events: none; }
.ledger-night.ledger-night-returning .ledger-night-fade { opacity: 0; transition: opacity .3s ease; }
.ledger-night.ledger-night-returning .ledger-night-stack .sleep-scene { height: 260px; transform: none; }
.ledger-night.ledger-night-returning .ledger-night-stack .sleep-note, .ledger-night.ledger-night-returning .ledger-night-stack .sleep-status { opacity: 1; max-height: 80px; margin-top: 0; }
/* Sections cap to their column and scroll inside; header, loot bar and the table's header/total stay put. */
.ledger-night .ledger-sec { background: transparent; flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; }
.ledger-night .ledger-sec > .ledger-sec-h { flex: none; }
.ledger-night .ledger-sec > .ledger-sec-body { min-height: 0; overflow-y: auto; }
.ledger-night .ledger-row:nth-child(odd) { background: rgba(255, 255, 255, .03); }
.ledger-night .ledger-table th { background: #000; position: sticky; top: 0; z-index: 1; }
.ledger-night .ledger-total-row td { background: #000; position: sticky; bottom: 0; z-index: 1; }
