:root {
  /* Cold crypt palette: damp slate stone, oxidised-iron seams, cold bone text,
     verdigris / ice accents. */
  --bg: #090c0e;
  --bg-2: #0e151a;
  --panel: #111a1f;
  --panel-2: #18242b;
  --panel-3: #1f2e36;
  --line: #324249;
  --line-soft: #243137;
  --text: #d6dee3;
  --muted: #7e8e98;
  --accent: #5fb3b0;     /* verdigris (primary) */
  --accent-2: #8fd6d2;   /* icy highlight */
  --good: #5fb39a;       /* moss / verdigris green */
  --bad: #c4544e;        /* dried-blood red */
  --warn: #c2a07a;       /* cold bronze */
  /* Role colors — kept cool to match the crypt theme. */
  --role-tank: #6f9bc4;    /* steel blue */
  --role-healer: #5fb39a;  /* verdigris */
  --role-dps: #a784bf;     /* crypt violet */
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: "Roboto", system-ui, -apple-system, "Segoe UI", sans-serif;
  overflow: hidden;
  /* Crisper DOM text, esp. on mobile WebKit. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Stop the iOS long-press text-selection / copy-lookup callout when playing as
     a home-screen web app. Re-enabled below for the editable text inputs. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  /* Disable double-tap-to-zoom (iOS ignores user-scalable=no); pinch is blocked
     via the gesture* listeners in main.js. The #menu keeps its own scroll. */
  touch-action: manipulation;
}

/* Editable fields still need selection + the callout to type/paste into them. */
input, textarea {
  -webkit-touch-callout: default;
  -webkit-user-select: auto;
  user-select: auto;
}

/* ── Menu screen ──────────────────────────────────────────────────── */
#menu {
  position: fixed; inset: 0;
  display: flex;
  /* Cold vignette + a faint spectral glow rising from below. */
  background:
    radial-gradient(ellipse 75% 55% at 50% 16%, rgba(95,179,176,0.08), transparent 62%),
    radial-gradient(ellipse at 50% 120%, var(--bg-2) 0%, var(--bg) 62%),
    var(--bg);
  overflow-y: auto;
  padding: 24px;
}
#menu[hidden] { display: none; }
/* "Menu Size" option: Large == the same scale as a 150% browser zoom. Applied to
   the card content so the full-screen background stays put and #menu keeps scrolling. */
#menu-card.menu-large { zoom: 1.5; }

#menu-card {
  position: relative;
  background:
    linear-gradient(180deg, rgba(143,214,210,0.03), transparent 28%),
    var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 32px 36px 28px;
  width: 100%;
  max-width: 480px;
  /* Centers when it fits, but scrolls (top reachable) when taller than the
     viewport -- margin auto clamps to 0 instead of clipping like flex centering. */
  margin: auto;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.5),
    inset 0 0 0 1px rgba(95,179,176,0.05),
    inset 0 1px 0 rgba(255,255,255,0.03),
    0 22px 56px rgba(0,0,0,0.65);
}
/* Carved corner flourishes. */
#menu-card::before, #menu-card::after {
  content: ""; position: absolute; width: 16px; height: 16px;
  border: 1px solid var(--accent); opacity: .3; pointer-events: none;
}
#menu-card::before { top: 10px; left: 10px; border-right: 0; border-bottom: 0; }
#menu-card::after  { bottom: 10px; right: 10px; border-left: 0; border-top: 0; }

#menu-card h1 {
  font-family: "Roboto Condensed", "Roboto", sans-serif;
  font-size: 34px;
  font-weight: 700;
  letter-spacing: 6px;
  text-transform: uppercase;
  text-align: center;
  margin-bottom: 20px;
  color: var(--accent-2);
  text-shadow: 0 0 16px rgba(95,179,176,0.30), 0 2px 3px rgba(0,0,0,0.8);
}

.card-section {
  border-top: 1px solid var(--line);
  padding-top: 16px;
  margin-top: 16px;
}
.card-section h2 {
  font-family: "Roboto Condensed", "Roboto", sans-serif;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .2em;
  color: var(--accent);
  margin-bottom: 10px;
  font-weight: 700;
}
details.card-section summary { cursor: pointer; list-style: none; display: flex; align-items: baseline; gap: 8px; }
details.card-section summary::-webkit-details-marker { display: none; }

label {
  display: block;
  font-size: 12px;
  color: var(--muted);
  margin: 10px 0;
}
label select, label input {
  display: block; width: 100%; margin-top: 4px; padding: 8px 10px;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px;
  font: inherit;
  transition: border-color .15s ease;
}
label select:hover, label input:hover { border-color: var(--accent); }
label select:focus, label input:focus { outline: none; border-color: var(--accent); }

/* Rounded-square chip pickers (Difficulty / Theme) — same selectable look as the
   class cards / control modes, driving a hidden <select>. */
.chip-group { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 10px; }
.chip {
  padding: 7px 12px; font: inherit; font-size: 12px; font-weight: 600;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px; cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.chip:hover { border-color: var(--accent); }
.chip.active { border-color: var(--accent); color: var(--accent); background: rgba(95,179,176,0.12); }

.toggle-label { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.toggle-label input { display: inline-block; width: auto; margin: 0; padding: 0; accent-color: var(--accent); }

/* Control mode: three mutually-exclusive radios (Direct / Survivor-like / Idle).
   Styled as a vertical segmented control (matching the .segmented toggles): one
   rounded pill container with stacked option rows; the selected one gets the
   accent-gradient highlight. Exactly one is always selected. */
.control-modes {
  display: flex; flex-direction: column; gap: 3px; margin-top: 4px; padding: 3px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 9px;
}
.ctrl-mode {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 12px; cursor: pointer;
  color: var(--text); background: transparent; border: none; border-radius: 6px;
  transition: background .15s ease, color .15s ease;
}
.ctrl-mode input { display: none; }
.ctrl-mode .ctrl-title { font-weight: 600; font-size: 13px; color: inherit; }
.ctrl-mode .hint-inline { font-size: 11px; color: var(--muted); }
.ctrl-mode:hover:not(:has(input:checked)) { background: rgba(255,255,255,0.05); }
.ctrl-mode:has(input:checked) {
  background: linear-gradient(180deg, var(--accent-2), var(--accent) 60%);
  color: #08201f;
}
.ctrl-mode:has(input:checked) .hint-inline { color: #08201f; opacity: .82; }

.hint-inline { font-size: 11px; color: var(--muted); }
.hint { font-size: 11px; color: var(--muted); margin: 6px 0 10px; }
.cosmetics-panel .hint a { color: var(--accent-2); text-decoration: none; border-bottom: 1px solid rgba(143,214,210,.4); }
.cosmetics-panel .hint a:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* Cosmetics-panel footer toggle, separated from the per-class controls above. */
.cos-randomize { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }

button {
  padding: 10px 18px;
  background: var(--good); color: #0b0d14;
  border: 1px solid var(--good); border-radius: 8px;
  cursor: pointer; font: 600 13px/1 inherit;
  transition: opacity .15s, transform .1s;
}
button:hover { opacity: .85; transform: translateY(-1px); }
button:active { transform: scale(.98); }

#start-btn {
  width: 100%; margin-top: 14px; padding: 13px;
  font-family: "Roboto Condensed", "Roboto", sans-serif;
  font-size: 15px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: #06100f;
  background: linear-gradient(180deg, var(--accent-2), var(--accent) 55%, #3c7f7c);
  border: 1px solid #2c5d5a; border-radius: 7px;
  box-shadow: 0 0 20px rgba(95,179,176,0.25), inset 0 1px 0 rgba(255,255,255,0.35), inset 0 -2px 6px rgba(0,0,0,0.3);
  text-shadow: 0 1px 0 rgba(255,255,255,0.2);
}
#start-btn:hover { opacity: 1; filter: brightness(1.08); box-shadow: 0 0 28px rgba(95,179,176,0.4), inset 0 1px 0 rgba(255,255,255,0.35); }

/* Secondary action button (menu) — outlined, less loud than the green Start. */
.secondary-btn {
  width: 100%; margin-top: 8px; padding: 10px;
  background: transparent; color: var(--accent);
  border: 1px solid var(--line); border-radius: 8px;
  font-weight: 600;
}
.secondary-btn:hover:not(:disabled) { border-color: var(--accent); }
.secondary-btn:disabled { opacity: .45; cursor: default; color: var(--muted); }
.secondary-btn .hint-inline { font-weight: 400; }

/* Two-step class picker: role tabs + class cards */
.picker-label { font-size: 12px; color: var(--muted); margin: 10px 0 6px; }
.role-tabs { display: flex; gap: 6px; }
.role-tab {
  flex: 1; padding: 9px 6px;
  background: var(--panel-2); color: var(--muted);
  border: 1px solid var(--line); border-radius: 8px;
  font: 600 12px/1 inherit;
}
.role-tab:hover { border-color: currentColor; transform: none; opacity: 1; }
.role-tab.active { background: rgba(255,255,255,0.04); border-color: currentColor; }
/* The role color tints the tab text only when active (muted otherwise). */
.role-tab.active.role-tank   { color: var(--role-tank); }
.role-tab.active.role-healer { color: var(--role-healer); }
.role-tab.active.role-dps    { color: var(--role-dps); }

.class-cards { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.class-card {
  padding: 9px 12px;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px;
  font: 600 12px/1 inherit; width: auto;
}
.class-card:hover { border-color: currentColor; transform: none; opacity: 1; }
.class-card.active { background: rgba(255,255,255,0.05); }
.class-card.active.role-tank   { border-color: var(--role-tank); color: var(--role-tank); }
.class-card.active.role-healer { border-color: var(--role-healer); color: var(--role-healer); }
.class-card.active.role-dps    { border-color: var(--role-dps); color: var(--role-dps); }

/* Class preview: an animated depiction of the selected class casting (left) next
   to its description (right). */
/* One big box, no internal dividers: left column holds the class name + role (on
   top) and the description text (below); the animation fills the whole right column. */
.class-preview {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-areas:
    "head anim"
    "desc anim";
  grid-template-rows: auto 1fr;
  column-gap: 12px;
  margin: 12px 0 4px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px;
  padding: 14px;
}
.class-head { grid-area: head; text-align: center; }
.class-head h3 { margin: 0 0 3px; font-size: 16px; color: var(--text); }
.class-head .cd-role {
  font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
.class-head .cd-role.role-tank   { color: var(--role-tank); }
.class-head .cd-role.role-healer { color: var(--role-healer); }
.class-head .cd-role.role-dps    { color: var(--role-dps); }
/* Borderless + transparent so the token reads as floating in the right column. */
.class-anim {
  grid-area: anim; align-self: center; justify-self: stretch;
  width: 100%; max-width: 100%; height: 220px;
  background: transparent; border: none;
}
.class-desc { grid-area: desc; margin-top: 18px; text-align: center; }
.class-desc p { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text); opacity: .9; }

.menu-status { font-size: 11px; color: var(--bad); margin-top: 8px; min-height: 16px; }
.menu-status.ok { color: var(--good); }

.menu-footer { margin-top: 20px; display: flex; justify-content: space-between; align-items: center; }
.build-label { font-size: 10px; color: var(--muted); opacity: .6; letter-spacing: .3px; }
.menu-footer a { font-size: 11px; color: var(--muted); text-decoration: none; transition: color .15s; }
.menu-footer a:hover { color: var(--accent); }

/* Wiki link — centered at the very bottom of the menu card. */
.menu-wiki { margin-top: 14px; text-align: center; }
.wiki-btn {
  display: inline-block; padding: 8px 20px;
  font-size: 13px; font-weight: 600; color: var(--accent); text-decoration: none;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px;
  transition: border-color .15s, background .15s;
}
.wiki-btn:hover { border-color: var(--accent); background: rgba(95,179,176,.06); }

/* Cosmetics store */
.store-balance { font-size: 13px; color: var(--warn); font-weight: 700; margin: 4px 0 10px; }
.store-group { margin-bottom: 10px; }
.store-row { display: flex; flex-wrap: wrap; gap: 8px; }
.store-card {
  flex: 1 1 120px; min-width: 110px; max-width: 160px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
}
.store-thumb {
  width: 56px; height: 56px;
  background: radial-gradient(ellipse at 50% 120%, var(--panel-3), var(--panel) 70%);
  border-radius: 6px;
}
.store-name { font-size: 11px; color: var(--text); }
.store-btn {
  width: 100%; padding: 6px 8px; font-size: 11px; border-radius: 6px;
  background: var(--panel-3); color: var(--text); border: 1px solid var(--line);
  transition: border-color .15s, background .15s;
}
.store-btn:hover:not(:disabled) { border-color: var(--accent); }
.store-btn:disabled { opacity: .45; }
.store-btn.owned { color: var(--good); border-color: var(--line-soft); }

/* Class / Cosmetics tabs above the preview */
.loadout-tabs { display: flex; gap: 6px; margin: 4px 0 10px; }
.loadout-tab {
  flex: 1; padding: 9px 6px;
  background: var(--panel-2); color: var(--muted);
  border: 1px solid var(--line); border-radius: 8px;
  font: 600 12px/1 inherit;
}
.loadout-tab:hover { border-color: var(--accent); opacity: 1; transform: none; }
.loadout-tab.active { background: rgba(255,255,255,0.04); border-color: var(--accent); color: var(--accent); }

/* Options: a normal card (<h2> header like the others) holding three full-width
   accordion rows (native <details>) that each expand in place. */
.opt-sec > summary { list-style: none; cursor: pointer; user-select: none; }
.opt-sec > summary::-webkit-details-marker { display: none; }

.opt-body { display: flex; flex-direction: column; gap: 8px; }

.opt-pill {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  font-size: 12px; font-weight: 600; color: var(--text);
  padding: 9px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2);
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.opt-pill::after { content: "▸"; font-size: 10px; color: var(--muted); transition: transform .15s; }
.opt-sec[open] > .opt-pill::after { transform: rotate(90deg); }
.opt-pill:hover { border-color: var(--accent); color: var(--accent); }
.opt-sec[open] > .opt-pill { color: var(--accent); border-color: var(--accent); background: rgba(95,179,176,0.10); }

.opt-sec-body { padding: 10px 4px 2px; }
.opt-sec-body #priority-editor { margin-top: 4px; }
.opt-sec-body #parties-list { margin-bottom: 4px; }

/* Parties: saved lineups list */
#party-save-btn { margin-top: 2px; }
/* Party builder: the 4 click-to-fill slot squares */
.party-rand { margin-bottom: 10px; }
.party-slots { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.party-slot {
  position: relative; flex: 1 1 64px; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 9px 4px 8px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); cursor: pointer;
}
.party-slot:hover { border-color: var(--accent); }
.party-slot.random { cursor: default; }            /* rolled each run — not pickable */
.party-slot.random:hover { border-color: var(--line); }
.ps-role { font-size: 9px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.party-slot.role-tank .ps-role   { color: var(--role-tank); }
.party-slot.role-healer .ps-role { color: var(--role-healer); }
.party-slot.role-dps .ps-role    { color: var(--role-dps); }
.ps-token { width: 32px; height: 32px; border-radius: 8px; box-shadow: inset 0 6px 0 rgba(255,255,255,.18); border: 1px solid rgba(0,0,0,.35); }
.ps-name { font-size: 11px; font-weight: 600; color: var(--text); text-align: center; line-height: 1.1; word-break: break-word; }
.ps-tag { font-size: 8px; font-weight: 700; letter-spacing: .05em; color: var(--accent); border: 1px solid var(--accent); border-radius: 6px; padding: 0 4px; }
.ps-select { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.party-slot.random .ps-token { filter: grayscale(1); opacity: .4; }
.party-slot.random .ps-name { color: var(--muted); font-style: italic; }

.parties-list { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.party-row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px; border: 1px solid var(--line); border-radius: 9px; background: var(--panel-2);
}
.party-row.fav { border-color: var(--warn); }
.party-star {
  flex: 0 0 auto; width: 26px; height: 26px; padding: 0; font-size: 16px; line-height: 1;
  background: transparent; border: none; color: var(--muted); cursor: pointer;
}
.party-star.on { color: var(--warn); }
.party-star:hover { color: var(--warn); }
.party-body { flex: 1 1 auto; min-width: 0; }
.party-name-row { display: flex; align-items: center; gap: 4px; }
.party-name {
  flex: 1 1 auto; min-width: 0; font: 600 13px/1.2 inherit; color: var(--text);
  background: transparent; border: 1px solid transparent; border-radius: 5px; padding: 2px 4px;
}
.party-reroll {
  flex: 0 0 auto; width: 22px; height: 22px; padding: 0; font-size: 14px; line-height: 1;
  background: transparent; color: var(--muted); border: 1px solid var(--line-soft); border-radius: 5px; cursor: pointer;
}
.party-reroll:hover { color: var(--accent); border-color: var(--accent); }
.party-name:hover { border-color: var(--line-soft); }
.party-name:focus { outline: none; border-color: var(--accent); background: var(--panel); }
.party-chips { display: flex; flex-wrap: wrap; gap: 5px 9px; margin: 5px 0 0 4px; }
.party-chip { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--muted); white-space: nowrap; }
.party-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.party-actions { flex: 0 0 auto; display: flex; flex-direction: column; gap: 5px; }
.party-load {
  padding: 5px 12px; font: 600 12px/1 inherit; cursor: pointer;
  background: rgba(95,179,176,.12); color: var(--accent); border: 1px solid var(--accent); border-radius: 7px;
}
.party-load:hover { background: rgba(95,179,176,.2); }
.party-del {
  padding: 4px 8px; font-size: 12px; line-height: 1; cursor: pointer;
  background: transparent; color: var(--muted); border: 1px solid var(--line-soft); border-radius: 7px;
}
.party-del:hover { color: var(--bad); border-color: var(--bad); }

/* Per-class cosmetic equip pickers (Cosmetics tab) */
.cosmetics-panel { margin-bottom: 4px; }
/* Class Info tab: the same stat block as the wiki (meta line + ability table). */
.classinfo-panel { margin-bottom: 4px; }
.ci-meta { font-size: 11px; color: var(--muted); margin: 2px 0 8px; }
.ci-abil { width: 100%; border-collapse: collapse; font-size: 12px; }
.ci-abil th { text-align: left; color: var(--muted); font-weight: 600; font-size: 9px; text-transform: uppercase; letter-spacing: .06em; padding: 2px 8px 3px 0; border-bottom: 1px solid var(--line-soft); }
.ci-abil td { padding: 4px 8px 4px 0; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
.ci-abil .ci-name { font-weight: 600; white-space: nowrap; }
.ci-abil .ci-eff { color: var(--accent-2); }
.ci-abil .ci-cd, .ci-abil .ci-rng { white-space: nowrap; color: var(--muted); }
@media (max-width: 880px) {
  .block-preview .classinfo-panel { max-width: 440px; margin-left: auto; margin-right: auto; }
}
.cos-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.cos-item {
  position: relative;
  width: 48px; height: 48px; padding: 0; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px;
  cursor: pointer; transition: border-color .12s, box-shadow .12s;
  /* The press-and-hold-to-lock gesture would otherwise trip iOS's long-press
     selection loupe / image callout. Kill the callout + selection on the tile. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.cos-item:hover { border-color: var(--accent); }
.cos-item.active { border-color: var(--good); box-shadow: 0 0 0 1px var(--good); }
/* Let the hold land on the button, not the canvas (canvases get their own iOS
   long-press image callout/loupe even when the parent suppresses it). */
.cos-item canvas {
  width: 48px; height: 48px; display: block;
  pointer-events: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
.cos-item.cos-none {
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; color: var(--muted);
}
.cos-empty { font-size: 11px; color: var(--muted); align-self: center; }
/* Locked (unowned) items: dimmed thumbnail with a price badge; buy in place. */
.cos-item.locked { border-style: dashed; }
.cos-item.locked canvas { opacity: 0.5; filter: grayscale(0.35); }
.cos-item .cos-price {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center; gap: 2px;
  font-size: 9px; font-weight: 700; color: var(--warn);
  background: rgba(0,0,0,0.62); padding: 1px 0; line-height: 1.3;
}
.cos-item .cos-price .bux-coin { width: 9px; height: 9px; }
/* Favorite star (owned items): top-left corner; favorites sort to the front. Dim
   outline when off so it's unobtrusive, gold when on. */
.cos-item .cos-fav {
  position: absolute; top: 0; left: 0;
  width: 16px; height: 16px; line-height: 16px; text-align: center;
  font-size: 11px; color: rgba(255,255,255,0.55);
  background: rgba(0,0,0,0.5); border-bottom-right-radius: 6px;
  cursor: pointer; transition: color .12s;
}
.cos-item .cos-fav:hover { color: var(--accent); }
.cos-item .cos-fav.on { color: #ffcf4a; text-shadow: 0 0 3px rgba(255,207,74,0.6); }
/* Padlock (owned items): top-right corner. Shown only when the item is locked to
   every class (press-and-hold a tile to lock). Indicator only — not clickable. */
.cos-item .cos-lock {
  position: absolute; top: 0; right: 0;
  width: 16px; height: 16px; line-height: 16px; text-align: center;
  font-size: 9px; color: var(--good); text-shadow: 0 0 3px rgba(110,231,183,0.6);
  background: rgba(0,0,0,0.5); border-bottom-left-radius: 6px;
  pointer-events: none;
}
.cos-item.cant-afford { cursor: not-allowed; }
.cos-item.cant-afford .cos-price { color: var(--muted); }
.cos-item.cant-afford:hover { border-color: var(--line); }

/* In-game Dungeon Bux counter — its own widget just under the Menu/Pause buttons
   (left-aligned so it never reaches the centred IN COMBAT badge), sized to roughly
   match the width of the Menu+Pause button cluster. */
#coin-hud {
  position: absolute;
  top: calc(40px + env(safe-area-inset-top));
  left: calc(8px + env(safe-area-inset-left));
  display: flex; align-items: center; gap: 5px;   /* single line; widens to fit */
  background: rgba(11,13,20,0.85);
  border: 1px solid var(--warn);
  border-radius: 6px;
  padding: 4px 9px;
  color: var(--warn);
  pointer-events: auto;   /* tappable: flips between this-run earnings and total owned */
  cursor: pointer;
  user-select: none; -webkit-user-select: none;
  z-index: 5;
}
#coin-hud[hidden] { display: none; }
#coin-hud .bux-coin { margin-right: 0; }   /* flex gap handles spacing here */

/* Boon tracker — semi-opaque icons under the minimap's floor/enemy box. */
#boon-tracker {
  position: absolute;
  display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px;
  opacity: .5; z-index: 4; transition: opacity .15s;
}
#boon-tracker:hover { opacity: .95; }
#boon-tracker[hidden] { display: none; }
.boon-chip {
  width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
  background: rgba(11,13,20,0.55); border: 1px solid var(--line); border-radius: 6px; cursor: pointer;
  transition: border-color .3s ease;   /* fades back to neutral in step with the tip text */
}
/* Only real pointers get the hover highlight — on touch :hover sticks after a tap
   and would keep the border lit after the tip text has faded. */
@media (hover: hover) { .boon-chip:hover { border-color: var(--accent); } }
.boon-chip.active { border-color: var(--accent); }
/* Rarity ring on the in-run tracker chips (matches the boon-card borders). */
.boon-chip.rarity-common    { border-color: #d8dee3; }
.boon-chip.rarity-uncommon  { border-color: #4fb05a; }
.boon-chip.rarity-rare      { border-color: #4f8fd6; }
.boon-chip.rarity-legendary { border-color: #c79a2e; }
.boon-chip canvas { display: block; }
#boon-tip {
  position: absolute; max-width: 230px; z-index: 6; pointer-events: none;
  background: rgba(11,13,20,0.96); border: 1px solid var(--accent); border-radius: 6px;
  padding: 6px 9px; font-size: 11px; line-height: 1.4; color: var(--text);
  box-shadow: 0 4px 14px rgba(0,0,0,0.5);
  opacity: 0; transition: opacity .3s ease;
}
#boon-tip.show { opacity: 1; }
#boon-tip[hidden] { display: none; }
#boon-tip b { color: var(--accent-2); }
/* "Dungeon Bux" label — small, mixed-case. Uses the SAME monospace font as the
   damage meter (its chunkier letterforms are why the meter looked "thicker" even
   when this was bolder than the meter's 400-weight numbers). */
.bux-label {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 7px; font-weight: 600; letter-spacing: .03em; opacity: .9;
}
.bux-amt   { font-size: 13px; font-weight: 700; }

/* Reliable gold coin glyph (the 🪙 emoji renders monochrome on many systems and
   just picks up the surrounding text colour). Scales with the font via em units. */
.bux-coin {
  display: inline-block; width: .95em; height: .95em; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff3b0 0%, #ffd23f 55%, #b8860b 100%);
  box-shadow: inset 0 0 0 1px rgba(138, 106, 20, .85);
  vertical-align: -.12em; margin-right: .28em;
}

/* Priority editor */
#priority-editor { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.priority-search {
  width: 100%; padding: 8px 10px;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px; font: inherit;
  transition: border-color .15s ease;
}
.priority-search:hover, .priority-search:focus { outline: none; border-color: var(--accent); }
.priority-blocks { display: flex; flex-direction: column; gap: 8px; }
.priority-block {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px 10px;
}
.priority-block > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em;
}
.priority-block > summary::-webkit-details-marker { display: none; }
.priority-block > summary::before { content: "▸"; font-size: 9px; transition: transform .15s; }
.priority-block[open] > summary::before { transform: rotate(90deg); }
.priority-block > summary:hover { color: var(--accent); }
.priority-block[open] > summary { margin-bottom: 6px; }
.priority-list { list-style: none; padding: 0; margin: 0; }
.priority-list li {
  background: var(--panel); border: 1px solid var(--line);
  padding: 5px 8px; margin: 3px 0; border-radius: 6px;
  font-size: 11px; cursor: grab; display: flex; justify-content: space-between;
  transition: border-color .15s;
}
.priority-list li:hover { border-color: var(--accent); }
.priority-list li.dragging { opacity: .4; }
.role-tank   { color: var(--role-tank); }
.role-healer { color: var(--role-healer); }
.role-dps    { color: var(--role-dps); }

/* ── Menu layout (mobile default → desktop three-column) ─────────────────────
   Mobile keeps the single ~480px card untouched: the .menu-col wrappers are
   display:contents so the blocks stack in one flex column, ordered for a natural
   read (class → preview → config/Start → menu). At ≥900px the wrappers become
   real columns and the card fans out. Every element id is unchanged. */
.menu-cols { display: flex; flex-direction: column; }
.menu-col { display: contents; }
.block-class    { order: 1; }
.block-preview  { order: 2; }
.block-party    { order: 3; }
.block-config   { order: 4; }
.block-menu     { order: 5; }

/* Save & Load section */
.save-text {
  width: 100%; min-height: 52px; margin-top: 8px; resize: vertical;
  font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 6px; padding: 7px 8px;
}
.save-text:focus { outline: none; border-color: var(--accent); }
.save-actions { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.save-actions .secondary-btn { width: auto; margin-top: 0; flex: 1 1 140px; text-align: center; }
.save-file-btn { cursor: pointer; }

@media (min-width: 900px) {
  #menu-card { max-width: 1180px; padding: 26px 30px 22px; }
  #menu-card h1 { font-size: 40px; margin-bottom: 22px; }

  .menu-cols { flex-direction: row; align-items: flex-start; gap: 18px; }
  .menu-col { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
  .menu-col-left   { flex: 0 0 280px; }
  .menu-col-center { flex: 1 1 auto; min-width: 0; }
  .menu-col-right  { flex: 0 0 320px; }

  /* Each block becomes a self-contained panel rather than a top-bordered row. */
  .menu-cols .card-section {
    margin-top: 0; padding: 18px; border-radius: 12px;
    border: 1px solid var(--line);
    background: linear-gradient(180deg, var(--panel) 0%, #0e161b 100%);
  }

  /* Roomy 2-up class grid in the narrow left column. */
  .block-class .class-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .block-class .class-card { text-align: center; }

  /* Preview: big centred token with the name/role/description stacked below. */
  .block-preview .class-preview {
    display: flex; flex-direction: column; align-items: center; text-align: center;
    background: radial-gradient(ellipse at 50% 72%, rgba(95,179,176,.08), transparent 66%);
    border: none; padding: 4px 0 0;
  }
  /* Token on top, sized to fill the preview card's free width so detail reads big. */
  .block-preview .class-anim { order: -1; width: 100%; max-width: 360px; height: 340px; }
  .block-preview .class-head { margin-top: 4px; }
  .block-preview .class-desc { margin: 8px auto 0; max-width: 420px; }
  .block-preview .loadout-tabs,
  .block-preview .cosmetics-panel { max-width: 440px; margin-left: auto; margin-right: auto; }
}

/* ── Game screen ──────────────────────────────────────────────────── */
#game {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  background: var(--bg);
}
#game[hidden] { display: none; }

#canvas-wrap {
  flex: 1;
  position: relative;
  overflow: hidden;
}
#game-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  background: #060810;
  /* The canvas owns all touch gestures (joystick drag, taps). Without this iOS
     treats a joystick drag as a pan and quick taps as double-tap-to-zoom, popping
     the OS magnification — `none` disables native scroll/zoom on the canvas while
     pointermove keeps firing through the drag. */
  touch-action: none;
  /* Let the browser smoothly resample the HiDPI backing store to the screen.
     In-canvas crispness (blocky minimap, smooth fog/sprites) is controlled
     per-draw via ctx.imageSmoothingEnabled, so nearest-neighbor here would only
     re-alias text/sprites when DPR is fractional or clamped. */
  image-rendering: auto;
}

#bottom-bar {
  background: var(--panel);
  border-top: 1px solid var(--line);
  padding: 6px 12px;
  padding-bottom: calc(6px + env(safe-area-inset-bottom));   /* clear the home indicator */
  display: flex;
  justify-content: center;
}
#hotbar { display: flex; gap: 6px; touch-action: manipulation; }
.hotbar-slot {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 12px; font-size: 11px; min-width: 70px; text-align: center; cursor: pointer;
  transition: border-color .15s, background .1s;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
}
.hotbar-slot:hover { border-color: var(--accent); }
.hotbar-slot:active { background: var(--panel); border-color: var(--accent); }
/* Dim cooldown via colour only — NOT opacity, which would also fade the border
   and make the outline pulse as the spell ticks on/off cooldown. */
.hotbar-slot.cooldown { color: var(--muted); background: var(--panel); }
/* Resource-gated (e.g. Static Runner without enough charges): greyed harder than
   a cooldown so "can't use yet" reads at a glance. Charges change at most ~1×/s,
   so the opacity here can't pulse the way a per-tick cooldown would. */
.hotbar-slot.disabled { color: var(--muted); background: var(--panel); opacity: 0.5; cursor: default; }
.hotbar-slot.disabled:hover { border-color: var(--line); }
.hotbar-slot.disabled .cd { color: var(--accent); opacity: 0.8; }
/* Active stance toggle (Totem Stance ON): a steady highlight so the mode reads at a glance. */
.hotbar-slot.active { border-color: var(--good); color: var(--good); background: rgba(102,224,140,0.10); }
.hotbar-slot.active .cd { color: var(--good); }
.hotbar-slot kbd { display: block; color: var(--accent); font-size: 9px; }
/* Tabular figures keep the countdown a constant width as it ticks. */
.cd { font-size: 10px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* Floating overlays */
#status-log {
  position: absolute;
  bottom: calc(48px + env(safe-area-inset-bottom));
  left: calc(8px + env(safe-area-inset-left));   /* bottom-left, clear of the minimap (top-right) */
  font-size: 10px; color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: rgba(11,13,20,0.85);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 5px 8px;
  max-width: 260px;
  max-height: 90px;
  overflow-y: auto;
  pointer-events: none;
}
/* No message → don't show the empty dark box (read as a stray black blob in the
   bottom-left corner, mirroring the fps readout opposite it). */
#status-log:empty {
  display: none;
}
#fps {
  position: absolute;
  bottom: calc(48px + env(safe-area-inset-bottom));
  right: calc(8px + env(safe-area-inset-right));
  font-size: 10px; color: var(--muted);
  pointer-events: none;
}
#top-controls {
  position: absolute;
  top: calc(8px + env(safe-area-inset-top));
  left: calc(8px + env(safe-area-inset-left));
  display: flex; gap: 6px;
}
#menu-btn, #pause-btn {
  position: static;
  background: rgba(11,13,20,0.85);
  border: 1px solid var(--line);
  color: var(--muted); font-size: 11px;
  padding: 4px 10px; border-radius: 6px;
  width: auto;
  transition: color .15s, border-color .15s, background .15s;
}
#menu-btn:hover, #pause-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: rgba(86,224,255,0.08);
  transform: none;
  opacity: 1;
}

/* Pause overlay */
#pause-overlay {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(6,8,16,0.85);
  z-index: 5;
}
#pause-overlay[hidden] { display: none; }
/* ── Options panel (pause overlay), styled like a real game's settings screen:
   a header, a scrollable body of labelled setting rows, and a footer. ── */
#pause-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 0;
  display: flex; flex-direction: column;
  width: min(440px, calc(100vw - 32px));
  max-height: calc(100vh - 48px);
  box-shadow: 0 18px 50px rgba(0,0,0,0.5);
  overflow: hidden;
}
.options-head {
  padding: 18px 22px 14px;
  border-bottom: 1px solid var(--line-soft);
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
}
.options-head h2 { margin: 0; letter-spacing: .06em; font-size: 18px; }
.options-stats {
  margin-top: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; color: var(--muted); line-height: 1.6;
}
.options-body { padding: 4px 22px 10px; overflow-y: auto; }
.options-group-title {
  font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); margin: 14px 0 0;
}
.options-foot {
  padding: 14px 22px;
  border-top: 1px solid var(--line-soft);
  display: flex; justify-content: flex-end;
}
.options-foot #resume-btn { width: auto; min-width: 120px; font-size: 14px; }

/* Shared setting row — label (name + hint) on the left, control on the right.
   Used by both the menu Options card and the pause options panel. */
.opt-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 12px 0;
  border-bottom: 1px solid var(--line-soft);
}
.opt-row:last-child { border-bottom: none; }
.opt-row-label { display: flex; flex-direction: column; gap: 3px; flex: 1 1 150px; min-width: 0; }
.opt-row-name { font-size: 13px; font-weight: 600; color: var(--text); }
.opt-row-hint { font-size: 11px; color: var(--muted); line-height: 1.45; }
.opt-row-ctrl { flex: 0 0 auto; }
.opt-row-ctrl select {
  margin: 0; padding: 7px 10px;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px; font: inherit; cursor: pointer;
}
.opt-row-ctrl select:hover, .opt-row-ctrl select:focus { outline: none; border-color: var(--accent); }

/* Segmented toggle (Synced | Unsynced, Normal | Large, …). */
.segmented {
  display: inline-flex; padding: 3px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 9px;
}
.seg-btn {
  width: auto; margin: 0; padding: 6px 14px;
  background: transparent; color: var(--muted);
  border: none; border-radius: 6px;
  font: 600 12px/1 inherit; cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.seg-btn:hover { color: var(--text); }
.seg-btn.active {
  background: linear-gradient(180deg, var(--accent-2), var(--accent) 60%);
  color: #08201f;
}

/* Pause camera-zoom control (lives in a setting row). */
.zoom-ctrl { display: flex; flex-direction: column; gap: 8px; align-items: flex-end; }
.zoom-line { display: flex; align-items: center; gap: 8px; }
.zoom-line input[type="range"] { width: 150px; min-width: 0; }
.zoom-pct { color: var(--accent); font-weight: 700; font-size: 12px; min-width: 40px; text-align: right; }
.zoom-actions { display: flex; align-items: center; gap: 14px; }
.zoom-step {
  width: 30px; height: 30px; flex: 0 0 auto; padding: 0;
  font-size: 18px; line-height: 1; border-radius: 8px;
}
.linklike {
  width: auto; padding: 0; background: none; border: none;
  color: var(--accent); font-size: 12px; cursor: pointer; text-decoration: underline;
}
.linklike:hover { color: #fff; }
.zoom-done { display: none; width: auto; font-size: 13px; }

/* Zoom preview ("peek"): collapse the panel to a slim bottom bar over the live,
   still-paused game so you can see the zoom change as you drag. Shows only the
   zoom slider + Done; the rest of the panel is hidden. */
#pause-overlay.peek {
  background: transparent;
  align-items: flex-end;
  padding-bottom: max(16px, env(safe-area-inset-bottom));
  pointer-events: none;   /* let the live view show; the card re-enables its own */
}
#pause-overlay.peek #pause-card {
  pointer-events: auto;
  background: rgba(15,18,26,0.9);
  backdrop-filter: blur(2px);
  width: min(560px, calc(100vw - 24px));
}
#pause-overlay.peek .options-head,
#pause-overlay.peek .options-foot,
#pause-overlay.peek .options-group-title,
#pause-overlay.peek .opt-row-label,
#pause-overlay.peek #pause-zoom-btn,
#pause-overlay.peek #pause-zoom-reset { display: none; }
#pause-overlay.peek .options-body { padding: 10px 16px; }
#pause-overlay.peek .opt-row { padding: 0; border: none; }
#pause-overlay.peek .opt-row ~ .options-group-title,
#pause-overlay.peek .opt-row ~ .opt-row { display: none; }   /* keep only the zoom row */
#pause-overlay.peek .zoom-ctrl { width: 100%; align-items: stretch; }
#pause-overlay.peek .zoom-line input[type="range"] { width: auto; flex: 1; }
#pause-overlay.peek .zoom-done { display: inline-block; }

/* First-boot "how to play" popup (shown once via the seenHowTo flag). */
#howto-overlay {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(6,8,16,0.88);
  z-index: 50; padding: 16px;
}
#howto-overlay[hidden] { display: none; }
#howto-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 24px 26px;
  max-width: 440px; width: 100%;
  display: flex; flex-direction: column; gap: 14px;
  box-shadow: 0 8px 40px rgba(0,0,0,0.5);
}
#howto-card h2 { margin: 0; color: var(--accent); letter-spacing: .03em; }
.howto-steps { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 10px; font-size: 13px; line-height: 1.45; }
.howto-steps b { color: var(--text); }
.howto-steps i { color: var(--accent-2, var(--accent)); font-style: normal; font-weight: 600; }
.howto-tip {
  margin: 0; padding: 10px 12px; font-size: 12.5px; line-height: 1.45;
  color: var(--text); background: rgba(95,179,176,0.10);
  border: 1px solid var(--accent); border-left-width: 3px; border-radius: 8px;
}
.howto-tip b { color: var(--accent-2, var(--accent)); }
.howto-foot { margin: 0; font-size: 12px; color: var(--muted); }
#howto-close { width: 100%; margin-top: 2px; padding: 11px; font-size: 14px; font-weight: 600; }

/* In-combat indicator (top-center) */
#combat-indicator {
  position: absolute; top: 8px; left: 50%;
  transform: translateX(-50%);
  font-size: 11px; font-weight: 700; letter-spacing: 1px;
  color: var(--bad);
  background: rgba(11,13,20,0.85);
  border: 1px solid var(--bad);
  border-radius: 6px;
  padding: 4px 12px;
  pointer-events: none;
  animation: combat-pulse 1s ease-in-out infinite;
}
/* While the top-center boss banner (canvas, y 8–42) is up, drop the indicator
   below it so the two don't overlap. Toggled from main.js via RENDER.bossBannerShown. */
#combat-indicator.below-boss { top: 46px; }
#combat-indicator[hidden] { display: none; }
@keyframes combat-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}

/* Damage meter (top-left, below the menu button) — compact, roughly the
   footprint of the minimap + level badge cluster in the top-right. */
#meter {
  position: absolute; top: 72px; left: 8px;   /* below the Dungeon Bux counter */
  width: 150px;
  font-size: 8px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: rgba(11,13,20,0.85);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 4px 5px;
  pointer-events: auto;   /* allow hover for the cast-breakdown tooltip */
  cursor: pointer;        /* tap toggles damage/healing sort */
  user-select: none;      /* tapping to toggle shouldn't select the text */
  -webkit-user-select: none;
}
#meter:empty { display: none; }
.meter-title {
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .5px;
  font-size: 7px;
  margin-bottom: 3px;
}
/* Active sort key: the word being sorted by lights up in its stat color. */
.meter-title .dmg.active   { color: var(--warn); font-weight: 700; }
.meter-title .heal.active  { color: var(--good); font-weight: 700; }
.meter-title .taken.active { color: var(--bad);  font-weight: 700; }
.meter-row {
  margin-bottom: 3px;
}
.meter-row.dead { opacity: .45; }
.meter-name { font-weight: 600; }
.meter-bars {
  position: relative;
  height: 5px;
  margin: 1px 0;
  background: rgba(255,255,255,0.04);
  border-radius: 2px;
  overflow: hidden;
}
.meter-bar {
  position: absolute; left: 0;
  height: 2px;
  border-radius: 1px;
  min-width: 0;
}
.meter-bar.dmg   { top: 0;    background: var(--warn); }
.meter-bar.heal  { bottom: 0; background: var(--good); }
.meter-bar.taken { top: 1px;  height: 3px; background: var(--bad); }   /* single bar in the Taken view */
.meter-nums {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
}
.meter-nums .dmg   { color: var(--warn); }
.meter-nums .heal  { color: var(--good); }
.meter-nums .taken { color: var(--bad); }
.meter-nums small { color: var(--muted); font-size: 7px; }

/* Desktop: scale the damage meter up (~1.8x) so it isn't tiny on a big screen.
   Matches render.js isMobileView() — mobile is a coarse pointer OR a narrow
   viewport, so desktop is a fine pointer AND a wide viewport. The mobile size
   above stays the default. */
@media (min-width: 768px) and (pointer: fine) {
  #meter {
    top: 76px;
    width: 270px;
    font-size: 14px;
    border-radius: 7px;
    padding: 7px 9px;
  }
  .meter-title { font-size: 12px; margin-bottom: 5px; }
  .meter-row { margin-bottom: 5px; }
  .meter-bars { height: 9px; margin: 2px 0; border-radius: 3px; }
  .meter-bar { height: 4px; border-radius: 2px; }
  .meter-nums small { font-size: 12px; }
  .bux-label { font-size: 11px; }   /* a touch larger on desktop, still under the amount */
}

/* Game-over overlay */
/* Floor-cleared / descend overlay (mirrors pause-card styling) */
#floor-overlay {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(6,8,16,0.85);
  z-index: 6;
}
#floor-overlay[hidden] { display: none; }
#floor-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 24px 32px;
  display: flex; flex-direction: column;
  align-items: center; gap: 16px;
  min-width: 240px;
}
#floor-title {
  margin: 0; font-size: 22px; font-weight: 700;
  letter-spacing: .06em; color: var(--good);
}
#floor-sub {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px; color: var(--muted);
  text-align: center; line-height: 1.7;
}
#descend-btn { width: auto; font-size: 14px; }
#descend-btn:disabled { opacity: .5; cursor: default; }

/* Boon picker: a row of choosable cards on the floor-cleared overlay */
#boon-cards {
  display: flex; gap: 12px; flex-wrap: wrap;
  justify-content: center; max-width: 560px;
}
.boon-card {
  position: relative;                 /* anchors the legendary sparkle overlay */
  flex: 1 1 150px; max-width: 180px;
  background: var(--panel-2);
  border: 2px solid var(--rarity, var(--line));   /* rarity-colored border */
  border-radius: 8px;
  padding: 10px 12px;
  cursor: pointer;
  text-align: left;
  transition: transform .12s, background .12s, box-shadow .12s;
}
.boon-card:hover { transform: translateY(-2px); box-shadow: 0 0 0 1px var(--rarity, var(--accent)); }
.boon-card.selected {
  background: color-mix(in srgb, var(--rarity, var(--accent)) 16%, var(--panel-2));
  box-shadow: 0 0 0 2px var(--rarity, var(--accent));
}
.boon-card .boon-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: 6px; margin-bottom: 6px;
}
.boon-card .boon-rarity {
  font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--rarity, var(--accent));
}
.boon-card .boon-target {
  font-size: 9.5px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 999px; padding: 1px 7px; white-space: nowrap;
}
.boon-card .boon-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.boon-card .boon-card-icon { flex: 0 0 auto; }
.boon-card .boon-name { font-weight: 700; font-size: 14px; color: var(--accent); }
.boon-card.rarity-legendary .boon-name { color: var(--rarity); }
.boon-card .boon-desc { font-size: 12px; color: var(--text); line-height: 1.4; }
.boon-card .boon-spark {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; border-radius: 8px; z-index: 1;
}

#gameover-overlay {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  background: rgba(6,8,16,0.85);
  gap: 20px;
}
#gameover-overlay[hidden] { display: none; }
#gameover-text {
  font-size: 48px; font-weight: 800; letter-spacing: .04em;
  text-shadow: 0 0 20px currentColor;
}
#gameover-text.victory { color: var(--good); }
#gameover-text.defeat  { color: var(--bad); }
.go-buttons { display: flex; gap: 12px; }
.go-buttons button { width: auto; font-size: 14px; }
#back-btn {
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line);
}
#back-btn:hover { border-color: var(--accent); background: var(--panel); }

/* ── Touch spell circles ───────────────────────────────────────────
   A full-screen, click-through overlay holding the positioned ability tokens;
   only the circles themselves capture taps so movement/world taps pass through. */
#spell-circles {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 3;
  opacity: var(--sc-opacity, 1);   /* user-set via the layout editor's Opacity slider */
}
#spell-circles:empty { display: none; }

.spell-circle {
  position: absolute;
  /* --sc-scale (editor Size slider) scales the circle about its center; the
     translate keeps it anchored on its saved layout point. */
  transform: translate(-50%, -50%) scale(var(--sc-scale, 1));
  width: 64px; height: 64px;
  /* key pinned to the top, cooldown to the bottom, name fitted in the middle */
  display: flex; flex-direction: column; align-items: center; justify-content: space-between;
  text-align: center; padding: 5px 0;
  border-radius: 50%;
  background: rgba(20, 24, 38, 0.82);
  border: 2px solid var(--accent);
  color: var(--text);
  font: 600 10px/1.1 ui-monospace, SFMono-Regular, Menlo, monospace;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
  pointer-events: auto;
  touch-action: none;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.spell-circle:active { background: rgba(40, 48, 74, 0.92); transform: translate(-50%, -50%) scale(calc(var(--sc-scale, 1) * 0.94)); }
/* Stance toggle currently ON (e.g. Smart Heals). */
.spell-circle.active { border-color: var(--good); color: var(--good); }
.spell-circle.active .sc-cd { color: var(--good); }
.spell-circle.cooldown { border-color: var(--line); color: var(--muted); opacity: 0.7; }
/* Resource-gated (not enough charges): dim harder than a cooldown so it reads as
   unusable; the sc-cd label shows the charge meter (have/cost⚡). */
.spell-circle.disabled { border-color: var(--line); color: var(--muted); opacity: 0.4; }
.spell-circle.disabled .sc-key { color: var(--muted); }
.spell-circle.disabled .sc-cd { color: var(--accent); }
.spell-circle .sc-key { color: var(--accent); font-size: 9px; line-height: 1; flex: 0 0 auto; }
.spell-circle.cooldown .sc-key { color: var(--muted); }
/* Name fills the middle and wraps between WORDS only (never mid-word); circles.js
   shrinks the font (10→6px) until the longest word fits this 54×34 box. */
.spell-circle .sc-name {
  flex: 0 1 auto;
  width: 54px; max-height: 34px; overflow: hidden;
  white-space: normal; word-break: keep-all; overflow-wrap: normal; hyphens: none;
  text-align: center; line-height: 1.05; font-size: 10px;
}
.spell-circle .sc-cd { font-size: 9px; color: var(--warn); line-height: 1; min-height: 9px; flex: 0 0 auto; }

/* Desktop: phones keep the compact 64px circle; a wide screen has room for
   larger buttons + readable text (fitName starts from the bigger font set here).
   Width-based to match the desktop menu breakpoint (a touch-capable PC reports a
   coarse pointer, so a `pointer: fine` guard would wrongly exclude it). */
@media (min-width: 900px) {
  .spell-circle { width: 104px; height: 104px; padding: 11px 0; border-width: 3px; }
  .spell-circle .sc-key { font-size: 15px; }
  .spell-circle .sc-name { width: 88px; max-height: 58px; font-size: 18px; line-height: 1.1; }
  .spell-circle .sc-cd { font-size: 13px; min-height: 13px; }
}

/* ── Spell-circle layout editor ──────────────────────────────────── */
#circle-editor {
  position: fixed; inset: 0;
  z-index: 20;
  background:
    radial-gradient(circle at 50% 40%, rgba(86, 224, 255, 0.06), transparent 60%),
    var(--bg);
}
#circle-editor[hidden] { display: none; }
#circle-editor-field { position: absolute; inset: 0; opacity: var(--sc-opacity, 1); }
#circle-editor .spell-circle.editor {
  cursor: grab; border-style: dashed;
}
#circle-editor .spell-circle.editor.dragging { cursor: grabbing; border-style: solid; box-shadow: 0 0 0 3px rgba(86, 224, 255, 0.3); }

#circle-editor-bar {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  padding: 10px 14px;
  background: rgba(11, 13, 20, 0.9);
  border-bottom: 1px solid var(--line);
}
.circle-editor-hint { font-size: 12px; color: var(--muted); }
.circle-editor-opacity { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }
.circle-editor-opacity input[type="range"] { width: 130px; accent-color: var(--accent); }
.circle-editor-actions { display: flex; gap: 8px; }
.circle-editor-actions button { padding: 8px 14px; font-size: 12px; }
#circle-cancel { background: var(--panel-2); color: var(--text); border-color: var(--line); }
#circle-clear { background: transparent; color: var(--muted); border-color: var(--line); }

/* Follow-tuning sandbox panel (live trail sliders; sandbox runs only) */
#follow-tuner[hidden] { display: none; }   /* ID display:flex below would otherwise beat the [hidden] attribute and leak into normal runs */
#follow-tuner {
  position: absolute; left: 12px; bottom: 12px; z-index: 30;
  display: flex; flex-direction: column; gap: 8px;
  width: 210px; padding: 12px 14px;
  background: rgba(17, 26, 31, 0.92); border: 1px solid var(--line);
  border-radius: 10px; color: var(--text); font-size: 12px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.45);
}
#follow-tuner .ft-title {
  color: var(--accent-2); font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; font-size: 11px;
}
#follow-tuner label { display: flex; flex-direction: column; gap: 4px; color: var(--muted); }
#follow-tuner label span { color: var(--accent); font-variant-numeric: tabular-nums; }
#follow-tuner input[type="range"] { width: 100%; accent-color: var(--accent); }
#follow-tuner .ft-hint { color: var(--muted); font-size: 10px; opacity: .8; }
