/* poe-regex workbench: hand-drawn PoE2-inspired dark panels. No game assets. */
:root {
    --bg: #14100c;
    --panel: #1e1812;
    --panel-edge: #6b5a34;
    --panel-edge-hi: #a68c4f;
    --ink: #d8cdb4;
    --dim: #8a7c5f;
    --slot: #241d14;
    --slot-active: #3a2f16;
    --accent: #c9a227;
    --cell: #201913;
}

html, body {
    margin: 0;
    height: 100%;
    background: var(--bg);
    color: var(--ink);
    font-family: Georgia, "Times New Roman", serif;
}

body { overflow: hidden; }
#app { height: 100%; }

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

.shell-bar {
    display: flex;
    gap: 1rem;
    align-items: center;
    padding: 0.6rem 1rem;
    border-bottom: 2px solid var(--panel-edge);
    background: linear-gradient(#241c10, #171208);
}

.shell-title { font-size: 1.2rem; letter-spacing: 0.06em; color: var(--accent); }
.shell-icon { width: 2.5rem; height: 2.5rem; flex: none; align-self: center; }
.shell-sub { color: var(--dim); font-size: 0.8rem; opacity: 0.75; }

.shell-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }

.bench {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1rem 1rem 0.25rem;
    flex: 1 1 auto;
    min-height: 0;
    /* The page never scrolls; when space runs out the backpack area
       scrolls instead. */
    overflow: hidden;
}

/* Inventory is the only panel: it fills the bench height; the row above the
   backpack stretches to absorb leftover space so the pack stays glued to
   the bottom of the panel. */
.panel.inventory {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: transparent;
    border-color: transparent;
    outline: none;
}

.panel {
    background: var(--panel);
    border: 1px solid var(--panel-edge);
    outline: 1px solid #000;
    padding: 0.75rem;
    min-width: 20rem;
}

.panel-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-size: 0.85rem;
    color: var(--accent);
    border-bottom: 1px solid var(--panel-edge);
    padding-bottom: 0.2rem;
    margin-bottom: 0.15rem;
}

.panel-sub { color: var(--dim); font-size: 0.8rem; margin: 0.1rem 0 0.1rem; }

/* Mode strip: buttons left, compiled-query box filling the rest of the row. */
.mode-bar { display: flex; align-items: stretch; gap: 0.6rem; margin-bottom: 0.5rem; }
.mode-switch { display: flex; gap: 0.4rem; flex: none; }
.result-strip {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: #171208;
    border: 1px solid var(--panel-edge);
    padding: 0.15rem 0.5rem;
    min-height: 2.2rem;
}
.mode-btn {
    background: var(--slot);
    color: var(--dim);
    border: 1px solid var(--panel-edge);
    padding: 0.35rem 1.1rem;
    cursor: pointer;
    font: inherit;
    font-size: 0.95rem;
}
.mode-btn.active { color: #ffe9a8; border-color: var(--panel-edge-hi); background: var(--slot-active); }

/* Top box layout: centered mode strip above editor | doll | compiled queries;
   backpack and advanced below. */
.inv-top {
    flex: 1 1 auto;
    display: flex;
    gap: 0.75rem;
    align-items: stretch;
}
/* Editor | doll: the editor grows to consume the spare vertical room while the
   doll stays aspect-locked (max 72vh -- its own capped height). The central
   alignment is intentional: keeps the spare height as a single symmetric band
   around the doll rather than a void under the backpack. */
.inv-editor { flex: 1 1 24rem; min-width: 0; display: flex; flex-direction: column; gap: 0.5rem; container-type: inline-size; }
@media (max-width: 1200px) { .inv-editor { flex: 1 1 19rem; } }
/* Doll column sized only to its own height-derived width (Wave 6 cap) --
   no 96vw borrowing, otherwise the cap collapses the editor column. */
/* Doll column sized only to its own height-derived width (Wave 6 cap), but
   never at the expense of the editor's 22 rem minimum: 960-wide halfscreens
   reward a roomy editor while keeping the doll well inside its cap. */
.inv-doll { flex: 0 1 auto; min-width: 0; width: 100%; max-width: min(100%, 72vh, calc(100% - 17rem)); display: flex; flex-direction: column; justify-content: center; }

/* Paper doll: fixed-aspect panel with absolutely positioned slot frames
   (like the game, whose gear area is slightly wider than tall so item
   cells render square). Positions are in PaperDoll.razor. */
.doll {
    position: relative;
    width: 100%;
    aspect-ratio: 4 / 3;
    /* Capped by the column width / viewport height so the backpack below still
       gets a usable area. Slot geometry assumes 4:3 (slot positions use
       top/height * 4/3); keep aspect-ratio even when scaling below. */
    max-width: min(100%, 72vh);
    margin: 0 auto;
    /* Subtle zoom so the slot frames actually REACH the panel edge; the canonical
   4:3 leaves a small corner margin. overflow: hidden trims frame edges that
   drift past ±6%. pointer-events stays on the slots only (no hit-steal over
   the backpack label/tools strip). */
    transform: scale(1.09);
    transform-origin: center center;
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
}
/* In the stacked (half-screen) layout the 1.09 zoom visually enlarges the doll
   past its column, spilling into the editor column (left weapon slot over the
   min-roll input). Drop it there: the tighter MarginFactor 0.70 alone already
   pushes the slots ~4% closer to the edge while keeping the 4:3 aspect pure. */
@media (max-width: 1499px) {
    .doll { transform: none; }
}
/* Keep slots interactive through the (pointer-events:none) scaled doll. */
.doll .gear-slot, .doll .slot-clear { pointer-events: auto; z-index: 1; }

/* Chrome that sits under/around the scaled doll's spill-over must paint and
   take clicks above it (right column only matters in the wide layout, but
   stacked positioning keeps them z-order-safe too). */
.panel.inventory > .panel-sub,
.panel.inventory > .modrow.pack-tools,
.pack-wrap {
    position: relative;
    z-index: 2;
}

.gear-slot {
    position: absolute;
    background: radial-gradient(circle at 50% 35%, #2e2517, var(--slot) 70%);
    border: 1px solid var(--panel-edge);
    color: var(--dim);
    cursor: pointer;
    font: inherit;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding: 0.15rem;
    box-sizing: border-box;
}
.gear-slot:hover { border-color: var(--panel-edge-hi); }
.gear-slot.active { border-color: var(--accent); background: radial-gradient(circle at 50% 35%, #4a3a18, var(--slot-active) 70%); }
.gear-slot.focused { border-color: #ffe9a8; box-shadow: inset 0 0 0 1px var(--panel-edge-hi); }
.slot-clear {
    position: absolute;
    background: #171208;
    color: var(--dim);
    border: 1px solid var(--panel-edge);
    cursor: pointer;
    font: inherit;
    font-size: 1.05rem;
    line-height: 1;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.slot-clear:hover { color: #ff9b9b; background: #3a1814; border-color: #8a3f3f; }
.doll.dimmed { opacity: 0.35; }
.doll.dimmed .gear-slot { cursor: not-allowed; }
.gear-label { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.08em; }
.gear-slot.active .gear-label { color: #ffe9a8; }

/* Backpack: fixed 12 x 5 cells (confirmed). The pack always spans the full
   width: cells are the width fit, snapped down to whole pixels (fractional
   cells drift against the pixel-snapped grid pattern, so lines and items
   stop agreeing). It hugs its natural height at the bottom of the panel;
   when the window is too short for the grid, the pack area itself scrolls —
   the page and bench never do. Cell lines are background; items are
   explicitly placed divs. */
.pack-wrap {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    overflow-y: auto;
}
.pack {
    --pack-cell: 2.6rem;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(12, var(--pack-cell));
    grid-auto-rows: var(--pack-cell);
    gap: 2px;
    background: #14100c;
    background-image:
        linear-gradient(#3d3220 1px, transparent 1px),
        linear-gradient(90deg, #3d3220 1px, transparent 1px);
    background-size: calc(var(--pack-cell) + 2px) calc(var(--pack-cell) + 2px);
    min-height: calc(5 * var(--pack-cell) + 4 * 2px);
    border: 1px solid #3d3220;
}
@supports (container-type: inline-size) {
    .pack-wrap { container-type: inline-size; }
    .pack {
        --pack-cell: calc((100cqw - 24px) / 12);
        font-size: clamp(0.6rem, 1.1cqw, 1.1rem);
    }
}
@supports (width: round(down, 10px, 1px)) {
    .pack {
        --pack-cell: round(down, calc((100cqw - 24px) / 12), 1px);
    }
}
.pack-placed {
    background: #2a2114;
    border: 1px solid var(--panel-edge-hi);
    color: var(--ink);
    font: inherit;
    font-size: 0.7rem;
    text-align: center;
    vertical-align: middle;
    overflow: hidden;
    padding: 0.15rem 0.1rem;
    cursor: pointer;
}
.pack-placed.hit { border-color: var(--accent); background: #4a3a18; }
/* Dim: the whole tile (background, border, text) fades uniformly, but stays
   clearly visible as an item against the empty cells. */
.pack-placed.dim { opacity: 0.55; filter: saturate(0.55); }
.pack-placed.selected { outline: 2px solid #ffe9a8; outline-offset: -2px; opacity: 1; filter: none; }

/* Wide layout (>=1500px): the backpack sits in a bounded right-hand column
   under the paper doll, the editor takes the full height at the left, and the
   panel's own height sizes the right-hand column so the 4:3 doll and the 12x5
   pack both fit (no scroll, no side bands). */
@media (min-width: 1500px) {
    .panel.inventory {
        container-type: size;
        display: grid;
        grid-template-columns: minmax(0, 1fr)
            clamp(28rem,
                calc((100cqh - 300px) * 6 / 7),
                min(60rem, 55vw));
        grid-template-rows: auto auto auto auto minmax(0, 1fr);
        column-gap: 0.75rem;
    }
    .inv-top { display: contents; } /* editor/doll become grid items */
    .panel.inventory > .panel-head { grid-column: 1 / -1; grid-row: 1; }
    .panel.inventory > .mode-bar { grid-column: 1 / -1; grid-row: 2; }
    .inv-editor { grid-column: 1; grid-row: 3 / 6; max-width: none; }
    .inv-doll { grid-column: 2; grid-row: 3; justify-content: flex-start; max-width: 100%; }
    .panel.inventory > .panel-sub { grid-column: 2; grid-row: 4; justify-self: start; align-self: center; margin: 0.1rem 0 0; }
    .panel.inventory > .modrow.pack-tools { grid-column: 2; grid-row: 4; justify-self: end; align-self: center; margin: 0.1rem 0; }
    .panel.inventory > .pack-wrap { grid-column: 2; grid-row: 5; }
    .doll { max-width: 100%; }
}

.queries { flex: 1; min-width: 22rem; }
#engine-status { color: var(--dim); margin-bottom: 0.4rem; }
.hint { color: var(--dim); font-style: italic; }

.field { display: flex; gap: 0.5rem; align-items: center; margin: 0; }
.field > span { color: var(--dim); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em; }
/* Global mode has no base class: a hidden mirror of the field (same global
   select styles) keeps the editor's rhythm pixel-identical so switching
   modes never shifts the picker. */
.field-blank { display: flex; visibility: hidden; }
select, input {
    background: #0d0a07;
    color: var(--ink);
    border: 1px solid var(--panel-edge);
    padding: 0.3rem 0.4rem;
    font: inherit;
    font-size: 0.85rem;
}

.chips { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0.4rem 0; }
.modpicker .chips { margin: 0 0 0.5rem; }
.chip { border: 1px solid var(--panel-edge); background: var(--slot); color: var(--ink); cursor: pointer; font-size: 0.75rem; padding: 0.15rem 0.5rem; }
.chip.inc { border-color: #4c7a3f; }
.chip.exc { border-color: #7a3f3f; }
.chip.clear { border-style: dashed; color: var(--dim); }

.modrow { display: flex; gap: 0.4rem; }
.modrow #mod-search { flex: 3; }
.modrow #mod-min { flex: 1; min-width: 6rem; }
.pack-tools { display: flex; justify-content: flex-end; gap: 0.4rem; margin: 0.1rem 0; }
/* The mod picker stretches to the bottom of the editor column; its list is
   the editor's scroll region (one column, or two in a wide editor). */
.modpicker { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* Basis 0: the mod list never inflates the editor's intrinsic height; it
   simply fills whatever the stretched editor gives it (and scrolls). */
/* Mod list grows to consume the editor's inherited height rather than 4rem. */
.mod-list { flex: 1 1 16rem; min-height: 0; overflow-y: auto; }
.suggest { list-style: none; margin: 0.25rem 0; padding: 0; }
@container (min-width: 34rem) {
    .modpicker .suggest { columns: 2; column-gap: 1rem; }
}
.gen-tag {
    flex: none; font-size: 0.8rem; line-height: 1.4; color: var(--ink);
    border: 1px solid var(--panel-edge); padding: 0 0.4rem; min-width: 4.2rem; text-align: center;
}
#suggest-all { margin: 0.3rem 0 0.1rem; }
.suggest-row { display: flex; gap: 0.4rem; align-items: center; padding: 0.15rem 0; border-bottom: 1px dotted #3d3220; break-inside: avoid; }
.suggest-line { flex: 1; font-size: 0.82rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.suggest-line.multi { display: flex; flex-direction: column; white-space: normal; gap: 0.05rem; }
.suggest-line.multi .mod-line { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Normal rarity: mods can't be picked, the list goes inert. */
.suggest.picker-off { opacity: 0.5; }

/* Family/tier pickers: one block per stat family; expanding shows its tiers.
   The family toggle reads as plain text (only +/- stay buttons) with a caret
   as the expand/collapse affordance. */
.fam-block { break-inside: avoid; }
.suggest-row.fam-row { border-bottom: 1px solid #3d3220; }
.suggest-row .fam-toggle {
    flex: 1; display: flex; gap: 0.45rem; align-items: baseline; text-align: left;
    font: inherit; font-size: 0.82rem; color: inherit; letter-spacing: normal; text-transform: none;
    background: transparent; border: none; padding: 0; cursor: pointer; overflow: hidden;
}
.suggest-row .fam-toggle:hover { background: transparent; border: none; color: inherit; }
.suggest-row .fam-toggle:hover .fam-text { color: #ffe9a8; }
.suggest-row .fam-toggle:hover .fam-caret { color: var(--ink); }
.fam-caret { flex: none; width: 0.9em; color: var(--dim); font-size: 0.72rem; }
.fam-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.82rem; }
.fam-text.multi { display: flex; flex-direction: column; white-space: normal; gap: 0.05rem; }
.fam-text.multi .mod-line { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tier-count {
    flex: none; font-size: 0.68rem; color: var(--dim);
    border: 1px solid var(--panel-edge); border-radius: 0.6rem; padding: 0 0.35rem;
}
.tier-list { list-style: none; margin: 0; padding: 0 0 0 1.2rem; }
.suggest-row.tier-row { border-bottom-style: none; padding: 0.05rem 0; }
.tier-row .tier-name {
    flex: none; max-width: 8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-style: italic; color: var(--accent); font-size: 0.82rem;
}
.tier-row .suggest-line { font-size: 0.78rem; color: var(--dim); }
.chip.inc.by-name { border-color: #3f6f7a; }
.suggest-row button, #suggest-all {
    background: var(--slot); color: var(--ink); border: 1px solid var(--panel-edge);
    cursor: pointer; padding: 0.1rem 0.5rem; font-size: 0.85rem;
}
.dlg .modrow + .modrow { margin-top: 0.4rem; }
.more, .field-error { font-size: 0.8rem; color: var(--dim); }
.field-error { color: #e08a8a; }

.qcard { border: 1px solid var(--panel-edge); margin-bottom: 0.8rem; background: #171208; }
.qcard-head { display: flex; gap: 0.6rem; align-items: center; padding: 0.4rem 0.6rem; text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem; color: var(--accent); }
.meter { flex: 1; height: 0.7rem; background: #0d0a07; border: 1px solid #3d3220; }
.meter-bar { display: block; height: 100%; }
.meter-green { background: #00c853; }
.meter-orange { background: #ff9800; }
.meter-red { background: #f44336; }
.meter-num { font-size: 0.75rem; color: var(--dim); }
.qquery {
    font-family: Consolas, monospace; font-size: 0.85rem; background: #0d0a07;
    margin: 0 0.6rem; padding: 0.5rem; overflow-wrap: anywhere;
}
.qactions { display: flex; gap: 0.5rem; align-items: center; padding: 0.4rem 0.6rem; }
.qactions button, .btn,
.suggest-row button, #suggest-all,
.mode-btn, .dlg button, .advcard button {
    text-transform: uppercase; letter-spacing: 0.03em;
}
.qactions button, .btn {
    background: var(--slot); color: var(--ink); border: 1px solid var(--panel-edge);
    cursor: pointer; font: inherit; font-size: 0.8rem; padding: 0.2rem 0.7rem;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.qactions button:hover, .btn:hover, .dlg button:hover, .advcard button:hover,
.result-strip button:hover, #slot-copy-multi:hover, #workbench-reset:hover {
    background: var(--slot-active); border-color: var(--panel-edge-hi); color: #ffe9a8;
}
#workbench-reset:hover, .btn-danger:hover {
    background: #532018; color: #ffb0b0; border-color: #b95555;
}
.qactions button:hover, .btn:hover, .dlg button:hover, .advcard button:hover,
.result-strip button:hover, #slot-copy-multi:hover, #workbench-reset:hover {
    background: var(--slot-active); border-color: var(--panel-edge-hi); color: #ffe9a8;
}
.btn:disabled, .btn:disabled:hover, .mode-btn:disabled, .mode-btn:disabled:hover,
.qactions button:disabled, .dlg button:disabled, .suggest-row button:disabled,
#pack-remove:disabled, #builder-save:disabled, #builder-cancel:disabled {
    background: #1a150f; border-color: #5b5b5b; color: #9d9d9d;
    opacity: 0.72; cursor: not-allowed;
    box-shadow: none;
}
#workbench-reset:disabled { background: #1a150f; color: var(--dim); border-color: #5b5b5b; opacity: 0.72; cursor: not-allowed; }
#workbench-reset, #workbench-reset:hover { background: #532018; color: #ffb0b0; border-color: #b95555; }
#workbench-reset:hover { background: #6a2222; }
#workbench-reset:disabled { background: #1a150f; color: #9d9d9d; border-color: #5b5b5b; opacity: 0.72; cursor: not-allowed; transition: none; }
#pack-remove:enabled:hover { background: #3a1814; color: #ff9b9b; border-color: #8a3f3f; transition: background .12s ease, color .12s ease, border-color .12s ease; }

.result-strip button,
#slot-copy-multi,
button[id^="slot-copy-"] {
    text-transform: uppercase; letter-spacing: 0.04em;
}
.suggest-row button:hover, #suggest-all:hover {
    background: var(--slot-active); border-color: var(--panel-edge-hi); color: #ffe9a8;
}
.result-strip button { color: var(--dim); }
.chip.clear:hover, .chip.inc:hover, .chip.exc:hover {
    background: #3a1814; color: #ff9b9b; border-color: #8a3f3f;
}
.mode-btn:hover { color: #ffe9a8; border-color: var(--panel-edge-hi); background: var(--slot-active); }
.btn-danger { background: #3a1814; color: #ff9b9b; border-color: #8a3f3f; font-weight: 600; }
.btn-danger:hover { background: #4a2018; color: #ffb0b0; border-color: #b95555; }
.qcopy-status, .qwarn { font-size: 0.8rem; color: var(--dim); }
.qdiag { font-size: 0.8rem; color: #e0c98a; padding: 0 0.6rem 0.3rem; }
.qerror { padding: 0.4rem 0.6rem; color: #e08a8a; }
.qexplain { border-top: 1px solid var(--panel-edge); padding: 0.4rem 0.6rem; font-size: 0.8rem; }
.qexplain-tokens { font-family: Consolas, monospace; margin-bottom: 0.4rem; }

textarea { width: 100%; box-sizing: border-box; }
.map-none { color: #e08a8a; font-size: 0.75rem; }
.map-one { color: var(--dim); font-size: 0.75rem; font-family: Consolas, monospace; }
.rarity-normal { color: #cfcfcf; }
.rarity-magic { color: #8888ff; }
.rarity-rare { color: #ffff77; }
.rarity-unique { color: #af6025; }
.import-batch { display: flex; flex-direction: column; }
.import-batch-head { display: flex; flex-direction: column; align-items: center; gap: 0.12rem; padding: 0.35rem 0 0.45rem; }
.import-nav-count { color: var(--dim); font-size: 0.95rem; }
.import-batch-status { text-align: center; }
.import-batch-ok { text-align: center; color: #a9c97a; font-size: 0.78rem; }
.import-carousel { display: flex; align-items: center; gap: 0.5rem; }
.import-carousel .iprev { flex: 1 1 auto; min-width: 0; }
.import-side-btn { flex: 0 0 auto; padding: 0.85rem 0.6rem; font-size: 1.15rem; line-height: 1; }
.titem-badges { display: flex; gap: 0.3rem; margin: 0.2rem 0; flex-wrap: wrap; }
.badge { font-size: 0.72rem; padding: 0.05rem 0.4rem; border: 1px solid var(--panel-edge); color: var(--dim); }
.badge.hit { color: #ffe9a8; border-color: var(--accent); }
.badge.miss { opacity: 0.7; }

/* Shared game-style item card (ItemPreview): tooltip, import preview and
   builder preview all draw the same box. */
.iprev {
    background: #100c08;
    border: 1px solid var(--panel-edge-hi);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.65);
    padding: 0.45rem 0.7rem 0.5rem;
    font-size: 0.8rem;
    box-sizing: border-box;
}
.iprev-name { text-align: center; font-weight: 600; font-size: 0.95rem; }
.item-tooltip .iprev-name { padding: 0 1.2rem; }
.iprev-sub { text-align: center; color: var(--dim); font-size: 0.78rem; margin-top: 0.1rem; }
.iprev-sep { border-top: 1px solid #3d3220; margin: 0.35rem 0; }
.iprev-stats { color: var(--ink); }
.iprev-meta { color: var(--dim); }
.iprev-mod + .iprev-mod { margin-top: 0.3rem; }
.iprev-cap { color: var(--dim); font-size: 0.72rem; margin: 0.15rem 0 0.1rem; }
.iprev-line { display: flex; gap: 0.5rem; align-items: baseline; padding: 0.06rem 0; }
.iprev-text { flex: 1; min-width: 0; overflow-wrap: anywhere; color: #9c9ce0; }
.iprev-annot { white-space: nowrap; }
.iprev-corrupt { text-align: center; color: #e08a8a; font-weight: 600; }

/* Game-style item tooltip: pinned overlay at the click point (never in
   layout), clamped to the viewport by poeRegexPlaceTooltip. The card inside
   is the tooltip's scroll region, so the border stays put. */
.item-tooltip {
    position: fixed;
    z-index: 40;
    width: 24rem;
    max-width: calc(100vw - 1rem);
    max-height: min(28rem, calc(100vh - 1rem));
}
.item-tooltip .iprev { max-height: inherit; overflow-y: auto; }
.tt-close {
    position: absolute;
    top: 0.2rem;
    right: 0.35rem;
    z-index: 1;
    background: none;
    border: none;
    color: var(--dim);
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    padding: 0.1rem 0.2rem;
}
.tt-close:hover { color: #ffe9a8; }

#blazor-error-ui { display: none; }

.dlg-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.72);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 50;
    overflow-y: auto;
}
.dlg {
    background: var(--panel);
    border: 1px solid var(--panel-edge-hi);
    outline: 1px solid #000;
    padding: 1rem 1rem 0.9rem;
    width: 38rem;
    max-width: 100%;
    margin: auto;
    max-height: 85vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.dlg textarea { min-height: 8rem; background: #0d0907; color: var(--ink); border: 1px solid var(--panel-edge); padding: 0.45rem 0.6rem; }
.dlg textarea::placeholder { color: var(--dim); }
.dlg .chips { margin: 0; padding: 0.4rem 0; border-bottom: 1px solid var(--panel-edge); }
.dlg .modrow { gap: 0.45rem; }

/* Import dialog single-item preview: a bounded game card, centered. */
#import-preview { max-width: 32rem; width: 100%; margin: 0 auto; }

/* Assemble dialog: two columns — controls and suggestions left, the live
   item card and its removal chips right. */
.dlg-builder { width: 56rem; }
.builder-cols { display: flex; gap: 1rem; align-items: stretch; min-height: 0; }
.builder-left { flex: 1.25; min-width: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.builder-right { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.5rem; }
/* No `columns` here on purpose: any columns declaration (even `columns: 1`)
   makes the list a multicol container, and a height-constrained multicol
   overflows into extra horizontal column boxes instead of scrolling down
   (the dialog's mod list showed phantom side-by-side columns + a horizontal
   scrollbar). Plain single column, vertical scroll only. */
.builder-left .suggest { overflow-y: auto; max-height: 46vh; min-height: 10rem; }
.builder-right .iprev { overflow-y: auto; max-height: 46vh; }

/* Advanced debugging panel opens as a bottom overlay so it never shoves body
   content. Grows upward from anchored bottom? no—top-to-bottom, from ~38vh down
   to a capped height, with the summary stuck as a visible collapse handle. */
details.advanced {
    position: fixed;
    bottom: 0.75rem;
    left: 0.75rem;
    right: 0.75rem;
    margin: 0;
    z-index: 60;
    flex: 0 0 auto;
    max-height: min(68vh, 690px);
    overflow-y: auto;
    background: var(--panel);
    border: 1px solid var(--panel-edge-hi);
    border-radius: 0.2rem;
    padding: 0 0.75rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
}
.advanced-reserve {
    flex: 0 0 auto;
    height: 2.6rem;
    margin: 0 1rem 1rem;
}
details.advanced > summary {
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-size: 0.85rem;
    color: var(--dim);
    padding: 0;
    position: sticky;
    top: 0;
    background: var(--panel);
    z-index: 1;
    margin: 0;
    text-align: center;
    min-height: 2.2rem;
    display: flex;
    align-items: center;
    justify-content: center;
}
details.advanced > summary:hover { color: var(--accent); }
details.advanced > .reset-row { margin-bottom: 1rem; }

/* Query strips inside the mode bar: one line each; the regex ellipsizes
   (full text via the native title tooltip; copy still copies all of it). */
.slot-query {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 1 1 100%;
    min-width: 0;
}
.slot-query code {
    font-family: Consolas, monospace; font-size: 0.85rem;
    flex: 1 1 auto; min-width: 0; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
}
.slot-query .meter-num { white-space: nowrap; }
.slot-query button {
    background: var(--slot); color: var(--ink); border: 1px solid var(--panel-edge);
    cursor: pointer; font: inherit; font-size: 0.8rem; padding: 0.2rem 0.7rem; white-space: nowrap;
}

/* Boot loading screen: covers the viewport until Blazor mounts. */
.boot-overlay {
    position: fixed;
    inset: 0;
    background: var(--bg);
    display: grid;
    place-items: center;
    z-index: 999;
}
.boot-text { text-align: center; }
.boot-title {
    font-size: 1.75rem;
    color: var(--accent);
    letter-spacing: 0.06em;
}
.boot-sub {
    font-size: 0.8rem;
    color: var(--dim);
    opacity: 0.75;
    margin-top: 0.5rem;
}
.boot-anim {
    width: 180px;
    height: 140px;
}
.boot-hammer {
    transform-origin: 130px 60px;
    animation: hammer-strike 1.6s ease-in-out infinite;
}
@keyframes hammer-strike {
    0%, 10% { transform: rotate(-30deg); }
    35%, 55% { transform: rotate(0deg); }
    75%, 100% { transform: rotate(-30deg); }
}
.boot-spark {
    animation: spark-flash 1.6s ease-in-out infinite;
}
@keyframes spark-flash {
    0%, 30% { opacity: 0; transform: scale(0.5); }
    38% { opacity: 1; transform: scale(1.3); }
    50%, 100% { opacity: 0; transform: scale(0.5); }
}

/* Forge loading screen (from forge-loader.html — dark palette forced) */
.forge-loader{
  --forge-size:min(380px,82vw);
  --forge-dur:1.4s;
  --iron-hi:#aab4c2;--iron-lo:#566070;--iron-edge:#0b0d11;
  --wood-hi:#86603a;--wood-lo:#52371f;
  --spark-hi:#fff1b8;--spark-lo:#ff9a22;
  --shadow:rgba(0,0,0,.5);--ink:#9aa4b2;
  width:var(--forge-size);display:grid;justify-items:center;gap:6px;
  font:500 14px/1 system-ui,-apple-system,"Segoe UI",sans-serif;letter-spacing:.02em;color:var(--ink);
}
.forge-loader svg{display:block;width:100%;height:auto;overflow:visible}
.forge-loader .sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.forge-loader .shadow{fill:var(--shadow)}
.forge-loader .grain{fill:none;stroke:#000;stroke-opacity:.2;stroke-width:1.2;stroke-linecap:round}
.forge-loader .anvil,.forge-loader .head{stroke:var(--iron-edge);stroke-width:1.5;stroke-linejoin:round}
.forge-loader .anvil{fill:url(#fg-iron)}
.forge-loader .head{fill:url(#fg-iron-h)}
.forge-loader .shine{fill:none;stroke:#fff;stroke-opacity:.35;stroke-width:1.6;stroke-linecap:round}
.forge-loader .bevel{fill:none;stroke:#fff;stroke-opacity:.22;stroke-width:1;stroke-linecap:round}
.forge-loader .notch{fill:var(--iron-edge)}
.forge-loader .grip{fill:#3d2b20}
.forge-loader .hot{fill:#fff1b8;opacity:0}
.forge-loader .star{fill:var(--spark-hi)}
.forge-loader .flash{opacity:0}
.forge-loader .glow{opacity:.45}
.forge-loader .label{margin:0}
.forge-loader .label i{font-style:normal;opacity:.25}

.forge-loader .hammer{transform:rotate(54deg);animation:fg-swing var(--forge-dur) infinite}
.forge-loader .body{animation:fg-jolt var(--forge-dur) linear infinite}
.forge-loader .bar{animation:fg-squash var(--forge-dur) linear infinite}
.forge-loader .glow{animation:fg-glow var(--forge-dur) ease-out infinite}
.forge-loader .hot{animation:fg-hot var(--forge-dur) linear infinite}
.forge-loader .flash{animation:fg-flash var(--forge-dur) linear infinite}
.forge-loader .s{opacity:0;animation:fg-fly var(--forge-dur) linear var(--d,0s) infinite}
.forge-loader .s>*{transform:rotate(var(--a0));animation:fg-turn var(--forge-dur) linear var(--d,0s) infinite}
.forge-loader .label i{animation:fg-dot var(--forge-dur) linear infinite}
.forge-loader .label i:nth-child(2){animation-delay:.06s}
.forge-loader .label i:nth-child(3){animation-delay:.12s}

@keyframes fg-swing{
  0%{transform:rotate(54deg);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}
  38%{transform:rotate(0deg);animation-timing-function:cubic-bezier(.2,.7,.4,1)}
  46%{transform:rotate(6deg);animation-timing-function:cubic-bezier(.45,0,.55,1)}
  88%,100%{transform:rotate(54deg)}
}
@keyframes fg-jolt{0%,37.9%{transform:none}39.5%{transform:translateY(1.6px)}41.5%{transform:translateY(-1px)}44%{transform:translateY(.5px)}47%,100%{transform:none}}
@keyframes fg-squash{0%,37.9%{transform:none}38%{transform:scale(1.05,.82)}47%{transform:scale(1.01,.96)}55%,100%{transform:none}}
@keyframes fg-glow{0%,37.9%{opacity:.45}38%{opacity:1}72%,100%{opacity:.45}}
@keyframes fg-hot{0%,37.9%{opacity:0}38%{opacity:1}64%,100%{opacity:0}}
@keyframes fg-flash{0%,37.9%{opacity:0;transform:scale(.3)}38%{opacity:1;transform:scale(.5)}42%{opacity:.85;transform:scale(1.15)}48%,100%{opacity:0;transform:scale(1.5)}}
@keyframes fg-fly{
  0%,37.9%{opacity:0;transform:translate(0,0)}
  38%{opacity:1;transform:translate(0,0) scale(1)}
  44%{transform:translate(calc(var(--x) * .28),calc(var(--u) * -.28 + var(--f) * .04)) scale(1)}
  50%{transform:translate(calc(var(--x) * .52),calc(var(--u) * -.52 + var(--f) * .16)) scale(1)}
  56%{opacity:1;transform:translate(calc(var(--x) * .72),calc(var(--u) * -.72 + var(--f) * .36)) scale(.9)}
  62%{transform:translate(calc(var(--x) * .88),calc(var(--u) * -.88 + var(--f) * .64)) scale(.75)}
  68%,100%{opacity:0;transform:translate(var(--x),calc(var(--f) - var(--u))) scale(.5)}
}
@keyframes fg-turn{0%,38%{transform:rotate(var(--a0))}68%,100%{transform:rotate(var(--a1)}}
@keyframes fg-dot{0%,37.9%{opacity:.25}38%,70%{opacity:1}80%,100%{opacity:.25}}

@media (prefers-reduced-motion:reduce){
  .forge-loader .hammer{animation:none;transform:rotate(28deg)}
  .forge-loader :is(.body,.bar,.hot,.flash,.s,.s>*,.label i){animation:none}
  .forge-loader .label i{opacity:.7}
  .forge-loader .glow{animation:fg-breathe 2.4s ease-in-out infinite}
}
@keyframes fg-breathe{0%,100%{opacity:.35}50%{opacity:1}}
