/* ─────────────────────────────────────────────────────────────────────
   Abilities tab v2 — adds: variation toggle on tab strip,
   cost-by-stat color, Edit-driven full filter drawer, status/rune/
   dmg/option filters, star filter + column + spacing, drag-drop
   column reorder, demoted Potential, row-coupled card expansion.
   ───────────────────────────────────────────────────────────────────── */

html, body { margin: 0; min-height: 100vh; background: var(--bg-field); color: var(--text); }
* { box-sizing: border-box; }

.page { max-width: 1440px; margin: 0 auto; padding: 10px 24px 20px; }

/* ── Header (page-head): brand + character + stats + Potential demoted ── */
.page-head {
  display: flex; align-items: flex-end; gap: 20px;
  padding-bottom: 14px; border-bottom: 1px solid var(--edge);
}
.brand-block { display: flex; align-items: baseline; gap: 14px; }
.brand-block .brand-wordmark { font-size: 22px; padding-top: 0; }
.brand-block .brand-sub {
  color: var(--faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em;
}
.char-block {
  flex: 1; display: flex; align-items: center; gap: 18px;
  padding-left: 18px; border-left: 1px solid var(--edge);
}
.char-name-wrap { display: flex; flex-direction: column; gap: 2px; }
.char-name { font-family: var(--font-display); font-weight: 700; font-size: 26px; letter-spacing: 0.04em; color: var(--text); }
.char-ancestry { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: var(--ls-caps); display: inline-flex; gap: 6px; align-items: baseline; flex-wrap: wrap; }
.char-archetype {
  font-size: 11px; text-transform: uppercase; letter-spacing: var(--ls-caps); font-weight: 700;
  color: var(--c-blue);
}
.char-archetype.berserker { color: var(--c-red); }

.char-stats { display: flex; gap: 14px; margin-left: auto; }
.char-stat {
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
  font-variant-numeric: tabular-nums;
}
.char-stat .lbl { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--faint); }
.char-stat .val { font: 800 18px/1 var(--font-sans); }
.char-stat[data-stat="str"] .val { color: var(--stat-str); }
.char-stat[data-stat="res"] .val { color: var(--stat-res); }
.char-stat[data-stat="agi"] .val { color: var(--stat-agi); }
.char-stat[data-stat="mem"] .val { color: var(--stat-mem); }
.char-stat[data-stat="wil"] .val { color: var(--stat-wil); }

/* Potential is now a secondary readout — small, monochrome, separated by a divider */
.potential-readout {
  margin-left: 14px;
  padding-left: 14px;
  border-left: 1px solid var(--edge);
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
  font-variant-numeric: tabular-nums;
}
.potential-readout .lbl { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--faint); }
.potential-readout .val { font: 600 13px/1 var(--font-sans); color: var(--muted); }
.potential-readout .val .max { color: var(--faint); }

/* ── Tab strip — now hosts the A/B variation toggle on the right ── */
.tab-bar {
  display: flex; align-items: center;
  border-bottom: 1px solid var(--edge);
  margin-top: 8px; margin-bottom: 12px;
}
.tabs { display: flex; gap: 0; flex: 1; }
.tab {
  appearance: none; background: transparent; border: 1px solid transparent; border-bottom: none;
  color: var(--muted); padding: 10px 18px;
  font: 600 13px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
  cursor: pointer; position: relative; top: 1px;
}
.tab:hover { color: var(--text); }
.tab.active {
  color: var(--text); background: var(--panel); border-color: var(--edge);
  border-radius: var(--r-3) var(--r-3) 0 0;
}
.tab .count {
  display: inline-block; margin-left: 8px; padding: 1px 7px;
  border-radius: var(--r-pill); background: rgba(255,255,255,0.06);
  color: var(--faint); font-size: 11px; font-variant-numeric: tabular-nums;
}
.tab.active .count { background: rgba(122,166,255,0.12); color: var(--c-blue); }

.view-toggle {
  display: inline-flex;
  margin-bottom: -1px;
  background: var(--panel-deep);
  border: 1px solid var(--edge);
  border-bottom: none;
  border-radius: var(--r-3) var(--r-3) 0 0;
  padding: 3px;
  align-self: flex-end;
}
.view-toggle button {
  appearance: none; background: transparent; border: 0;
  color: var(--muted); padding: 6px 12px;
  font: 600 11px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
  cursor: pointer; border-radius: var(--r-2);
  display: inline-flex; align-items: center; gap: 6px;
}
.view-toggle button .icon { width: 14px; height: 14px; }
.view-toggle button.on { background: var(--c-blue); color: #0a1226; box-shadow: 0 0 12px rgba(122,166,255,0.20); }

/* ── Filter bar (compact row) ── */
.filter-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: nowrap;
  background: var(--panel); border: 1px solid var(--edge);
  border-radius: var(--r-3); padding: 10px 12px; margin-bottom: 14px;
}
.filter-search { position: relative; flex: 0 0 220px; margin-left: auto; min-width: 160px; }
.filter-search input {
  width: 100%; background: var(--panel-deep); border: 1px solid var(--edge);
  border-radius: var(--r-3); color: var(--text);
  padding: 8px 10px 8px 32px; font: 400 13px/1.2 var(--font-sans);
}
.filter-search input::placeholder { color: var(--faint); }
.filter-search input:focus {
  outline: none; border-color: rgba(122,166,255,0.5);
  box-shadow: 0 0 0 2px rgba(122,166,255,0.12);
}
.filter-search .icon {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  color: var(--faint); pointer-events: none;
}

/* Edit button — toggles the full filter drawer */
.edit-btn {
  appearance: none;
  background: var(--c-blue); color: #0a1226;
  border: 1px solid rgba(122,166,255,0.6);
  border-radius: var(--r-3); padding: 7px 9px;
  font: 700 12px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
  cursor: pointer;
  /* Center contents so "Edit" and "Done" sit identically inside the
     same fixed-width box — the toggle should not visually jump in size.
     The min-width is kept just wide enough to fit "DONE" + icon so the
     Edit/Filters pair stays compact and leaves room for chips. */
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-width: 72px;
  transition: transform 0.1s ease, box-shadow 0.12s ease;
  box-shadow: 0 0 14px rgba(122,166,255,0.18);
}
.edit-btn:hover { transform: translateY(-1px); box-shadow: 0 4px 18px rgba(122,166,255,0.25); }
.edit-btn.on { background: var(--panel-deep); color: var(--c-blue); box-shadow: none; }
.edit-btn .icon { width: 14px; height: 14px; }

/* Filters dropdown trigger. Shows count badge for active filters. */
.filters-btn { gap: 8px; }
.filters-btn .filter-active-count {
  display: inline-block;
  min-width: 16px;
  height: 16px;
  padding: 0 5px;
  border-radius: 8px;
  background: var(--c-orange, #f3a953);
  color: #0a1226;
  font: 700 10px/16px var(--font-mono);
  font-variant-numeric: tabular-nums;
  text-align: center;
  margin-left: -2px;
}
.filters-btn .caret { opacity: 0.7; margin-left: -2px; }
.edit-btn.on .filter-active-count { background: var(--c-orange, #f3a953); color: #0a1226; }

/* Chip rail (always-visible compact row). Allowed to shrink and scroll
   horizontally so the whole filter bar stays on one line; chips never
   wrap onto a second row. */
.chip-rail {
  display: inline-flex; gap: 6px; flex-wrap: nowrap; align-items: center;
  flex: 1 1 0; min-width: 0;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: thin;
  /* Hide the native scrollbar but keep scrolling functional — chips
     remain reachable via horizontal scroll/wheel. */
  scrollbar-color: var(--edge) transparent;
}
.chip-rail::-webkit-scrollbar { height: 4px; }
.chip-rail::-webkit-scrollbar-thumb { background: var(--edge); border-radius: 2px; }
.chip-rail::-webkit-scrollbar-track { background: transparent; }
.chip-rail > * { flex: 0 0 auto; }
.chip-rail .divider { width: 1px; height: 22px; background: var(--edge); margin: 0 2px; }

.count-readout {
  color: var(--faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}
.count-readout strong { color: var(--text); font-weight: 700; }

/* ── Filter drawer (revealed by Edit) ── */
.filter-drawer {
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: var(--r-3);
  padding: 14px 14px 10px;
  margin-bottom: 14px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px 18px;
}
/* A vertical stack of fd-groups inside a single column of the drawer.
   Three of these sit side-by-side: "others" (preset, archetype,
   columns, action types, display options) on the LEFT, statuses +
   damage types in the MIDDLE, runes on the RIGHT. The DOM order is
   left over from an earlier layout; CSS order swaps them visually so
   the JSX stays readable in its original grouping. */
.fd-col {
  display: flex; flex-direction: column; gap: 14px;
  min-width: 0;
}
.fd-col-others     { order: 1; }
.fd-col-conditions { order: 2; }
.fd-col-runes      { order: 3; }
.fd-group { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
/* Legacy stack class kept for any out-of-tree consumers; behaves the
   same as .fd-col. */
.fd-stack {
  display: flex; flex-direction: column; gap: 12px;
  min-width: 0;
}
@media (max-width: 900px) {
  .filter-drawer { grid-template-columns: 1fr; }
}
.fd-group .label {
  font: 700 10px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--faint); margin-bottom: 4px;
}
.fd-group .chips { display: flex; gap: 6px; flex-wrap: wrap; }
.fd-group .fd-sublabel {
  font: 700 9px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--faint); opacity: 0.7;
  margin: 4px 0 0;
}

/* ── Label tone override ──
   `data-label-tone="strong"` on the filter-drawer host bumps every
   section label and sub-label inside it to the bright --text color so
   the heading hierarchy reads with high contrast (matching the
   Display-options checkbox labels). "muted" (default) leaves the
   established faint treatment in place. The fd-check labels are
   already in --text, so they're unaffected either way. */
.filter-drawer[data-label-tone="strong"] .fd-group > .label,
.filter-drawer[data-label-tone="strong"] .fd-group .fd-sublabel,
.filter-drawer[data-label-tone="strong"] .fd-inline > .label,
.filter-drawer[data-label-tone="strong"] .fd-inline > .fd-sublabel {
  color: var(--text);
  opacity: 1;
}

/* Inline label+chips row. Pairs a heading (.label or .fd-sublabel) with
   the chip rail to its right on a single horizontal line so the drawer
   uses the available width instead of stacking each control on its own
   row. Used for the segmented toggles (rune/stat-cost/status display,
   display preset, view mode) where the chip rail is short and benefits
   from sitting on the label's baseline. */
.fd-group .fd-inline {
  display: flex; align-items: center; gap: 12px;
  margin-top: 6px;
  flex-wrap: wrap;
}
.fd-group .fd-inline > .label,
.fd-group .fd-inline > .fd-sublabel {
  margin: 0;
  flex: 0 0 auto;
}
.fd-group .fd-inline > .chips { margin: 0; }

/* Segmented variant — used for display-mode toggles (e.g. rune complexity).
   Buttons fuse into a single horizontal strip rather than reading as filter
   chips. Always single-select. The outer border is intentionally one step
   stronger than the global --edge token so the segmented strip reads as a
   first-class control alongside checkboxes and the search field, instead
   of fading into the drawer background. */
.fd-group .chips-segmented {
  display: inline-flex;
  flex-wrap: nowrap;
  gap: 0;
  border: 1px solid var(--edge-strong, rgba(255,255,255,0.22));
  border-radius: var(--r-2);
  overflow: hidden;
  width: fit-content;
}
.chip.chip-rune-mode,
.chip.chip-cost-mode,
.chip.chip-status-mode,
.chip.chip-preset-mode,
.chip.chip-view-mode,
.chip.chip-tone-mode,
.chip.chip-col {
  border: 0;
  /* Hairline divider between adjacent segmented buttons — match the
     stronger outer border so the divider doesn't look softer than the
     frame it sits inside. */
  border-right: 1px solid var(--edge-strong, rgba(255,255,255,0.22));
  border-radius: 0;
  background: transparent;
  /* Default segmented-chip text is at the --muted token, not --faint,
     so unselected options still read clearly. The .on state lifts
     them to --text. */
  color: var(--muted);
  padding: 6px 12px;
  font: 600 11px/1 var(--font-sans);
  letter-spacing: 0.04em;
}
.chip.chip-rune-mode:last-child,
.chip.chip-cost-mode:last-child,
.chip.chip-status-mode:last-child,
.chip.chip-preset-mode:last-child,
.chip.chip-view-mode:last-child,
.chip.chip-tone-mode:last-child,
.chip.chip-col:last-child { border-right: 0; }
.chip.chip-rune-mode:hover,
.chip.chip-cost-mode:hover,
.chip.chip-status-mode:hover,
.chip.chip-preset-mode:hover,
.chip.chip-view-mode:hover,
.chip.chip-tone-mode:hover,
.chip.chip-col:hover { background: rgba(255,255,255,0.04); color: var(--text); }
.chip.chip-rune-mode.on,
.chip.chip-cost-mode.on,
.chip.chip-status-mode.on,
.chip.chip-preset-mode.on,
.chip.chip-view-mode.on,
.chip.chip-tone-mode.on,
.chip.chip-col.on {
  background: color-mix(in oklch, var(--c-teal, #5ee0c2) 18%, transparent);
  color: var(--text);
}
/* Preset chips host an icon + label; align them on one row and give the
   icon a touch of breathing room. */
.chip.chip-preset-mode {
  display: inline-flex; align-items: center; gap: 6px;
}
.chip.chip-preset-mode .preset-icon { display: inline-block; }
.chip.chip-preset-mode .preset-label { display: inline-block; }
/* The columns toggle can hold up to a dozen entries — allow it to wrap
   onto multiple lines. Each chip grows to fill the line so the rows
   read as a clean filled-out grid rather than left-piled buttons. */
.fd-group .chips-segmented.chips-wrap {
  flex-wrap: wrap;
  width: 100%;
  max-width: 560px;
}
.fd-group .chips-segmented.chips-wrap .chip {
  flex: 1 1 0;
  min-width: 80px;
  text-align: center;
  justify-content: center;
  white-space: nowrap;
  /* When the chip rail wraps onto multiple rows, paint a bottom
     divider on every chip so the rows are separated by the same
     hairline used between columns. The outer container's bottom
     border covers the last row's hairline, so the doubled stroke
     is invisible. */
  border-bottom: 1px solid var(--edge-strong, rgba(255,255,255,0.22));
}

/* ── Strength-adjusted display toggle (a single labelled checkbox) ── */
.fd-check {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--edge); border-radius: var(--r-pill);
  background: var(--panel-deep);
  cursor: pointer;
  font: 600 11px/1 var(--font-sans);
  letter-spacing: 0.06em;
  color: var(--muted);
  text-transform: uppercase;
  user-select: none;
}
.fd-check input[type="checkbox"] { accent-color: var(--c-blue); cursor: pointer; }
.fd-check .fd-check-lbl { color: var(--text); }
.fd-check .fd-check-help { color: var(--faint); font-variant-numeric: tabular-nums; font-size: 10px; }
.fd-check:hover { border-color: var(--c-blue); }

/* ── Strength-adjusted metric highlight ──
   The toggle only changes the NUMBER, never the color — ATK/BRK/IMP keep
   their natural .m-* hues whether or not strength adjustment is applied,
   so the reader's color-by-stat mental model is preserved. We still expose
   the .str-adj hook on the cell for tooltips or future overlays, but it
   carries no color rule. */
.va-row td.num.str-adj,
.vb-metric.str-adj .v {
  /* intentionally no color override */
}

/* ── Healing metric (HEL) — yellow, per Bifröst palette ──
   Healing reads in the same warm-yellow as runes / crit / discovery so
   it's distinct from green AGI (which previously claimed --dmg-heal) and
   pairs visually with the rune system that drives many heals. */
.m-hel,
.vb-metric .v.m-hel { color: var(--c-yellow); }

/* ── Equip column header (visible only when Edit is on) ── */
.va-table thead th.col-equip {
  cursor: pointer;
  text-align: center;
  padding: 8px 6px;
  position: relative;
}
.va-table thead th.col-equip .equip-th {
  font-size: 12px;
  color: var(--c-blue);
  letter-spacing: 0;
}
.va-table thead th.col-equip.sorted { color: var(--c-blue); }
.va-table thead th.col-equip.sorted::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 1px; background: var(--c-blue);
}

/* ── Generic chip ── */
.chip {
  appearance: none;
  background: var(--panel-deep);
  border: 1px solid var(--edge);
  color: var(--muted);
  font: 600 11px/1 var(--font-sans);
  text-transform: uppercase; letter-spacing: 0.08em;
  padding: 6px 10px;
  border-radius: var(--r-pill);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: center; gap: 6px;
  transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease, box-shadow 0.12s ease;
}
.chip:hover { border-color: rgba(255,255,255,0.15); color: var(--text); }
.chip.on {
  color: var(--text);
  border-color: var(--accent, var(--c-blue));
  background: color-mix(in oklch, var(--accent, var(--c-blue)) 14%, transparent);
}

/* Type-categorized chips show their accent color even in their default state,
   so the mapping between a filter chip and its Type-column badge is visible
   without needing to toggle the chip on. The .on state intensifies the same
   color so selected vs. unselected still reads at a glance. */
.chip[data-type] {
  color: var(--accent, var(--muted));
  border-color: color-mix(in oklch, var(--accent, var(--edge)) 35%, var(--edge));
  background: color-mix(in oklch, var(--accent, transparent) 6%, var(--panel-deep));
}
.chip[data-type]:hover {
  color: var(--text);
  border-color: color-mix(in oklch, var(--accent, var(--edge)) 65%, var(--edge));
}
.chip[data-type].on {
  color: var(--text);
  border-color: var(--accent);
  background: color-mix(in oklch, var(--accent) 22%, transparent);
  box-shadow: 0 0 0 1px color-mix(in oklch, var(--accent) 60%, transparent),
              0 0 12px color-mix(in oklch, var(--accent) 30%, transparent);
}
.chip .ct {
  background: rgba(255,255,255,0.06);
  padding: 1px 6px; border-radius: var(--r-pill);
  color: var(--faint); font-size: 10px;
}
.chip.on .ct {
  background: color-mix(in oklch, var(--accent, var(--c-blue)) 18%, transparent);
  color: var(--text);
}

/* Star chip — just the glyph */
.chip-star { --accent: var(--c-yellow); padding: 6px 10px; }
.chip-star .star { display: inline-block; line-height: 1; color: var(--faint); font-size: 14px; }
.chip-star.on .star { color: var(--c-yellow); }
.chip-star.on { color: var(--text); border-color: var(--c-yellow); background: rgba(246,222,125,0.12); }
.chip-star .ct { margin-left: 2px; }

/* Type chips */
.chip[data-type="attack"]   { --accent: var(--c-red); }
.chip[data-type="reaction"] { --accent: var(--c-teal); }
.chip[data-type="seidr"]    { --accent: var(--c-purple); }
.chip[data-type="galdr"]    { --accent: var(--c-cyan); }
.chip[data-type="kenning"]  { --accent: var(--c-orange); }
.chip[data-type="stance"]   { --accent: var(--c-yellow); }
/* Trait types */
.chip[data-type="combat"]    { --accent: var(--c-red); }
.chip[data-type="defensive"] { --accent: var(--c-blue); }
.chip[data-type="arcane"]    { --accent: var(--c-purple); }
.chip[data-type="memory"]    { --accent: var(--c-cyan); }
.chip[data-type="social"]    { --accent: var(--c-teal); }
.chip[data-type="origin"]    { --accent: var(--c-yellow); }
/* Equipment slots */
.chip[data-type="mainhand"],
.chip[data-type="melee"]    { --accent: var(--c-red); }
.chip[data-type="ranged"]    { --accent: var(--c-orange); }
.chip[data-type="offhand"],
.chip[data-type="shield"]   { --accent: var(--c-cyan); }
.chip[data-type="head"],
.chip[data-type="helm"]     { --accent: var(--c-purple); }
.chip[data-type="body"],
.chip[data-type="armor"]    { --accent: var(--c-blue); }
.chip[data-type="hands"],
.chip[data-type="gloves"]   { --accent: var(--c-yellow); }
.chip[data-type="feet"],
.chip[data-type="boots"]    { --accent: var(--c-green); }
.chip[data-type="trinket"],
.chip[data-type="ring"]     { --accent: var(--c-grey); }
.chip[data-type="quick"]    { --accent: var(--c-magenta); }

/* Damage type chips — colored by their stat color always */
.chip-dmg {
  color: var(--accent, var(--muted));
  border-color: color-mix(in oklch, var(--accent, var(--edge)) 30%, var(--edge));
  background: color-mix(in oklch, var(--accent, transparent) 5%, var(--panel-deep));
}
.chip-dmg:hover {
  color: var(--text);
  border-color: color-mix(in oklch, var(--accent, var(--edge)) 60%, var(--edge));
}
.chip-dmg.on {
  color: var(--text);
  border-color: var(--accent);
  background: color-mix(in oklch, var(--accent) 22%, transparent);
}
.chip-dmg .glyph { font-size: 12px; }
.chip-dmg[data-d="f"] { --accent: var(--status-burning); }
.chip-dmg[data-d="i"] { --accent: var(--status-freezing); }
.chip-dmg[data-d="g"] { --accent: var(--status-poisoned); }
.chip-dmg[data-d="t"] { --accent: var(--c-yellow); }
.chip-dmg[data-d="s"] { --accent: var(--c-purple); }
.chip-dmg[data-d="y"] { --accent: var(--c-cyan); }
.chip-dmg[data-d="e"] { --accent: var(--c-red); }
.chip-dmg[data-d="r"] { --accent: var(--c-grey); }
.chip-dmg[data-d="b"] { --accent: var(--c-blue); }
.chip-dmg[data-d="a"] { --accent: var(--c-red); }
.chip-dmg[data-d="h"] { --accent: var(--c-green); }
.chip-dmg[data-d="d"] { --accent: var(--c-teal); }

/* Status chips — default state already shows the status color (was previously
   only shown when selected). When toggled ON, the chip becomes white with a
   colored glow so the selection state still reads. Squared corners. */
.chip-status {
  padding: 5px 10px 5px 6px;
  border-radius: var(--r-1);
  color: var(--text);
  border-color: var(--accent, var(--edge));
  background: color-mix(in oklch, var(--accent, transparent) 22%, var(--panel-deep));
  text-transform: none;
  letter-spacing: 0.04em;
  font-weight: 700;
}
.chip-status:hover {
  border-color: color-mix(in oklch, var(--accent, var(--edge)) 100%, white 10%);
  box-shadow: 0 0 10px color-mix(in oklch, var(--accent, transparent) 40%, transparent);
}
.chip-status.on {
  color: #0a1226;
  background: #ffffff;
  border-color: var(--accent, #fff);
  box-shadow: 0 0 0 1px var(--accent, transparent),
              0 0 18px color-mix(in oklch, var(--accent, transparent) 70%, transparent),
              0 0 32px color-mix(in oklch, var(--accent, transparent) 40%, transparent);
}
.chip-status .badge {
  width: 18px; height: 18px;
  border-radius: var(--r-1);
  background: rgba(0,0,0,0.55);
  display: inline-flex; align-items: center; justify-content: center;
}
.chip-status .badge img { width: 14px; height: 14px; display: block; }
.chip-status.on .badge { background: rgba(0,0,0,0.85); }
.chip-status .ct {
  background: rgba(0,0,0,0.35);
  color: var(--text);
}
.chip-status.on .ct { background: rgba(10,18,38,0.18); color: #0a1226; }
.chip-status[data-s="burning"]  { --accent: var(--status-burning); }
.chip-status[data-s="freezing"] { --accent: var(--status-freezing); }
.chip-status[data-s="poisoned"] { --accent: var(--status-poisoned); }
.chip-status[data-s="decay"]    { --accent: var(--status-decay); }
.chip-status[data-s="thorned"]  { --accent: var(--status-thorned); }
.chip-status[data-s="shocked"]  { --accent: var(--status-shocked); }
.chip-status[data-s="jolted"]   { --accent: var(--status-jolted); }
.chip-status[data-s="bleeding"] { --accent: var(--status-bleeding); }

/* ── Rune chips ──
   Rune filter chips mirror the anatomy of status chips: a square badge
   holding the Elder Futhark glyph (in the runic font), the rune's
   Latin name in a regular sans, and a count. The Latin name is the
   primary read here — the runic glyph alone is hard to recognise at
   small sizes, so it lives in the badge as a decoration. */
.chip-rune {
  color: var(--c-yellow);
  border-color: rgba(94,224,194,0.35);
  background: rgba(94,224,194,0.04);
  font-family: var(--font-sans);
  letter-spacing: 0;
  padding: 5px 10px 5px 6px;
  border-radius: var(--r-1);
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: 700;
  text-transform: capitalize;
}
.chip-rune .badge {
  width: 22px; height: 22px;
  border-radius: var(--r-1);
  background: rgba(94,224,194,0.15);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.chip-rune .badge .rune-sym {
  font-family: var(--font-runic);
  font-size: 16px; line-height: 1;
  color: var(--c-yellow);
  margin: 0;
  font-weight: 400;
}
.chip-rune .chip-rune-name {
  color: var(--c-yellow);
  font-size: 11px;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  min-width: 0;
  flex: 1;
}
.chip-rune:hover {
  color: var(--c-yellow);
  border-color: rgba(94,224,194,0.65);
  background: rgba(94,224,194,0.08);
}
.chip-rune.on {
  color: #0a1226;
  background: var(--c-teal);
  border-color: var(--c-teal);
}
.chip-rune.on .badge { background: rgba(10,18,38,0.18); }
.chip-rune.on .badge .rune-sym,
.chip-rune.on .chip-rune-name { color: #0a1226; }
.chip-rune .ct {
  background: rgba(0,0,0,0.30);
  color: var(--c-yellow);
}
.chip-rune.on .ct { background: rgba(10,18,38,0.18); color: #0a1226; }

/* Option chips (attack-options / actions / passives — neutral) */
.chip-opt { --accent: var(--c-grey); text-transform: none; letter-spacing: 0.02em; }

/* Metric / type color classes */
.m-atk { color: var(--c-red); }
.m-brk { color: var(--c-blue); }
.m-prc { color: var(--text); }
.m-imp { color: var(--c-orange); }
.m-spd { color: var(--c-green); }
.m-rng { color: var(--c-pink); }
.m-def { color: var(--stat-res); }
.m-mag { color: var(--c-cyan); }
.m-wt  { color: var(--c-grey); }
.m-str { color: var(--stat-str); }
.m-res { color: var(--stat-res); }
.m-agi { color: var(--stat-agi); }
.m-mem { color: var(--stat-mem); }
.m-wil { color: var(--stat-wil); }

/* Type badge (small, label).
   Pill is 22px tall (4px taller than the original 18px). To keep the
   row height unchanged, we apply a -2px top/bottom margin so the pill's
   margin-box still contributes ~18px to the inline flow — the extra
   4px renders into the cell's natural overflow area on either side of
   the text baseline. Font-size and the inline damage glyphs scale up
   alongside so the dmg icons no longer clip the pill border. */
.type-badge {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  margin: -2px 0;
  border-radius: var(--r-2);
  font-size: 12px; text-transform: capitalize; letter-spacing: 0.02em; font-weight: 700;
  line-height: 1;
  box-sizing: border-box;
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--type-color, var(--c-blue));
  color: var(--type-color, var(--c-blue));
  background: color-mix(in oklch, var(--type-color, var(--c-blue)) 8%, transparent);
}
.type-badge[data-type="attack"]   { --type-color: var(--c-red); }
.type-badge[data-type="reaction"] { --type-color: var(--c-teal); }
.type-badge[data-type="seidr"]    { --type-color: var(--c-purple); }
.type-badge[data-type="galdr"]    { --type-color: var(--c-cyan); }
.type-badge[data-type="kenning"]  { --type-color: var(--c-orange); }
.type-badge[data-type="stance"]   { --type-color: var(--c-yellow); }
.type-badge[data-type="combat"]    { --type-color: var(--c-red); }
.type-badge[data-type="defensive"] { --type-color: var(--c-blue); }
.type-badge[data-type="arcane"]    { --type-color: var(--c-purple); }
.type-badge[data-type="memory"]    { --type-color: var(--c-cyan); }
.type-badge[data-type="social"]    { --type-color: var(--c-teal); }
.type-badge[data-type="origin"]    { --type-color: var(--c-yellow); }
.type-badge[data-type="mainhand"],
.type-badge[data-type="melee"]    { --type-color: var(--c-red); }
.type-badge[data-type="ranged"]    { --type-color: var(--c-orange); }
.type-badge[data-type="offhand"],
.type-badge[data-type="shield"]   { --type-color: var(--c-cyan); }
.type-badge[data-type="head"],
.type-badge[data-type="helm"]     { --type-color: var(--c-purple); }
.type-badge[data-type="body"],
.type-badge[data-type="armor"]    { --type-color: var(--c-blue); }
.type-badge[data-type="hands"],
.type-badge[data-type="gloves"]   { --type-color: var(--c-yellow); }
.type-badge[data-type="feet"],
.type-badge[data-type="boots"]    { --type-color: var(--c-green); }
.type-badge[data-type="trinket"],
.type-badge[data-type="ring"]     { --type-color: var(--c-grey); }
.type-badge[data-type="quick"],
.type-badge[data-type="quick items"] { --type-color: var(--c-magenta); }

/* ── Cost pill — colored per stat-cost ── */
.cost-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  font: 700 10px/1.4 var(--font-mono);
  letter-spacing: 0.04em;
  border: 1px solid var(--cost-color, var(--c-yellow));
  color: var(--cost-color, var(--c-yellow));
  background: color-mix(in oklch, var(--cost-color, var(--c-yellow)) 8%, transparent);
}
.cost-pill[data-stat="strength"]   { --cost-color: var(--stat-str); }
.cost-pill[data-stat="resilience"] { --cost-color: var(--stat-res); }
.cost-pill[data-stat="agility"]    { --cost-color: var(--stat-agi); }
.cost-pill[data-stat="memory"]     { --cost-color: var(--stat-mem); }
.cost-pill[data-stat="will"]       { --cost-color: var(--stat-wil); }
.cost-pill[data-stat="rune"]       { --cost-color: var(--c-yellow); }

/* ── Minimal cost display ──
   When the user picks "Minimal" in the cost-display selector, stat-cost
   pills collapse to just the integer. Style them as perfectly round
   circles — same 22×22 chip as the symbol-only rune pill — so the row
   reads as a tight string of identically-sized tokens. */
.cost-pill.cost-pill-minimal {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  padding: 0;
  min-width: 0;
  border-radius: 50%;
  font-size: 11px;
  letter-spacing: 0;
  box-sizing: border-box;
}

/* Damage icons (inline glyphs on ability rows / cards) */
.dmg-types { display: inline-flex; gap: 4px; align-items: center; }
.dmg-type {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--edge);
  font-size: 12px;
  cursor: help;
  filter: drop-shadow(0 0 2px rgba(0,0,0,0.6));
}

/* Status indicator token — mirrors the combat tab badge: icon centered in
   a squared chip with a colored border, the stack count overlapping the
   top-right corner in the same color. */
.status-token {
  display: inline-flex; align-items: center;
  margin-right: 4px;
  vertical-align: middle;
}
.status-token .status-icon {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  border-radius: var(--r-1);
  background: color-mix(in oklch, var(--status-color, var(--c-grey)) 14%, rgba(0,0,0,0.55));
  border: 1.5px solid var(--status-color, var(--c-grey));
  box-shadow: inset 0 0 6px color-mix(in oklch, var(--status-color, transparent) 25%, transparent);
  flex-shrink: 0;
}
.status-token .status-icon img {
  width: 14px; height: 14px; display: block;
  filter: drop-shadow(0 0 2px rgba(0,0,0,0.6));
}
.status-token .status-count {
  position: absolute;
  top: -5px; right: -5px;
  min-width: 13px; height: 13px;
  padding: 0 3px;
  border-radius: 999px;
  background: rgba(8,12,22,0.92);
  border: 1.5px solid var(--status-color, currentColor);
  color: var(--status-color, var(--text));
  font: 800 9px/10px var(--font-mono);
  text-align: center;
  font-variant-numeric: tabular-nums;
  box-sizing: border-box;
}
.status-token[data-s="burning"]  { --status-color: var(--status-burning); }
.status-token[data-s="freezing"] { --status-color: var(--status-freezing); }
.status-token[data-s="poisoned"] { --status-color: var(--status-poisoned); }
.status-token[data-s="decay"]    { --status-color: var(--status-decay); }
.status-token[data-s="thorned"]  { --status-color: var(--status-thorned); }
.status-token[data-s="shocked"]  { --status-color: var(--status-shocked); }
.status-token[data-s="jolted"]   { --status-color: var(--status-jolted); }
.status-token[data-s="bleeding"] { --status-color: var(--status-bleeding); }

/* "+N" overflow pill that replaces the tail of a status list when the
   Max status conditions setting truncates it. Reads as a quiet status-
   adjacent chip — same height as the .status-token icon (22px), no
   colored border (it's an aggregator, not a condition), tabular-nums
   counter so it lines up with the stack counts on its neighbours. */
.status-token-more {
  display: inline-flex; align-items: center; justify-content: center;
  height: 22px; min-width: 22px;
  padding: 0 6px;
  border-radius: var(--r-2, 6px);
  border: 1px dashed var(--edge);
  background: rgba(255,255,255,0.04);
  color: var(--muted);
  font: 700 11px/1 var(--font-mono);
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  cursor: default;
}
.status-token-more.compact { height: 18px; min-width: 18px; padding: 0 4px; font-size: 10px; }
.status-token-more:hover { color: var(--text); border-color: var(--muted); }

/* Side label for the tester results stacks readout */
.status-token-with-label {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 4px 10px 4px 6px;
  background: var(--panel-deep);
  border: 1px solid var(--edge);
  border-radius: var(--r-2);
}
.status-token-with-label .stacks-num {
  font: 800 13px/1 var(--font-mono);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* Edit-mode equip checkbox */
.equip-cbx {
  appearance: none;
  width: 16px; height: 16px;
  border: 1.5px solid var(--c-blue);
  border-radius: var(--r-1);
  background: var(--panel-deep);
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
}
.equip-cbx:checked {
  background: var(--c-blue);
}
.equip-cbx:checked::after {
  content: "✓";
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: #0a1226; font-weight: 800; font-size: 11px;
}

/* ─────────────────────────────────────────────────────────────────
   VARIATION A — Dense Table
   Star column added on the far left. Columns draggable.
   Table is auto-width: every column hugs its widest cell so no single
   column hoards horizontal space.
   ───────────────────────────────────────────────────────────────── */
.va-table-wrap { background: var(--panel); border: 1px solid var(--edge); border-radius: var(--r-3); overflow: auto; }
.va-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: auto;
  font-variant-numeric: tabular-nums;
}
/* Keywords col is the only one allowed to absorb leftover horizontal space. */
.va-table col.col-kw, .va-table th.col-kw, .va-table td.col-kw {
  width: auto;
}

.va-table thead th {
  background: var(--panel-deep);
  color: var(--muted);
  font: 700 10px/1 var(--font-sans);
  text-transform: uppercase; letter-spacing: 0.1em;
  padding: 10px 10px;
  text-align: left;
  border-bottom: 1px solid var(--edge);
  position: relative;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.va-table thead th[data-draggable="true"]::before {
  content: "⋮⋮";
  color: var(--faint);
  margin-right: 6px;
  letter-spacing: -2px;
  font-weight: 400;
}
.va-table thead th.dragging { opacity: 0.4; }
.va-table thead th.drop-target { background: rgba(122,166,255,0.18); }
/* Compact metric columns: 3-letter labels (ATK/BRK/PRC/IMP/SPD/RNG) only need
   a hair more than the digits themselves. Reduce side padding so the table
   doesn't waste horizontal space on these. */
.va-table thead th.num { text-align: right; padding-left: 6px; padding-right: 8px; }
.va-row td.num { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; padding-left: 6px; padding-right: 8px; }
.va-table thead th:hover { color: var(--text); }
.va-table thead th.sorted { color: var(--c-blue); }
.va-table thead th.sorted::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 1px; background: var(--c-blue);
}
.va-table thead th .arrow { display: inline-block; margin-left: 4px; font-size: 9px; }

/* Star + equip columns — narrow, fixed. Star is intentionally the
   thinnest column on the table because its glyph is a single 14px
   star with no header label — we don't want a chunky wedge of empty
   gutter to its left or right. */
.va-table .col-star { width: 22px; text-align: center; padding: 0 2px; cursor: default; }
.va-table .col-star::before { display: none !important; }
.va-table .col-equip { width: 32px; text-align: center; padding: 0 0 0 12px; cursor: default; }
.va-table .col-equip::before { display: none !important; }
.va-row td.col-equip { padding: 0 0 0 12px; text-align: center; vertical-align: middle; }

.va-row { border-bottom: 1px solid var(--edge); cursor: pointer; transition: background 0.1s ease; }
.va-row:last-child { border-bottom: none; }
.va-row:hover { background: var(--panel-raised); }
.va-row.expanded { background: var(--panel-raised); }
.va-row td {
  padding: 10px 10px;
  font: 400 13px/1.3 var(--font-sans);
  vertical-align: middle;
  white-space: nowrap;
}
.va-row td.num { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }
.va-row td.dash { color: var(--faint); font-weight: 400; }
.va-row td.col-star { text-align: center; padding: 0; }
.va-row .fav-btn {
  appearance: none; background: transparent; border: 0;
  color: var(--faint); font-size: 14px; cursor: pointer;
  /* Tight padding so the star glyph fits inside the narrow col-star
     gutter without forcing the column wider than the header. */
  padding: 4px 2px;
  line-height: 1;
}
.va-row .fav-btn:hover { color: var(--c-yellow); }
.va-row .fav-btn.on { color: var(--c-yellow); }
.va-row td.col-name { padding-left: 16px; }
.va-row .name { font-weight: 700; color: var(--text); font-size: 13px; }
.va-row .keywords {
  font-size: 11px; color: var(--faint); text-transform: lowercase;
  /* Stay on a single line; if the row's keyword set is longer than the
     column can show, we let the cell clip rather than growing the row
     into a second line (which destroys table rhythm). */
  white-space: nowrap;
  display: inline-flex; align-items: center; gap: 4px 6px;
}
.va-row td.col-kw {
  overflow: hidden;
  /* max-width: 0 with table-layout: auto would normally collapse the
     col, but col-kw also has `width: auto` (set above) so the layout
     algorithm still gives it the leftover horizontal space — content
     beyond that space is simply clipped. */
  max-width: 0;
  text-overflow: clip;
}
.va-row .keywords .status-token { margin-right: 2px; }

.va-detail { background: var(--panel-deep); border-bottom: 1px solid var(--edge); padding: 14px 16px 16px; }
.va-detail .desc { font-size: 13px; color: var(--text); line-height: 1.55; max-width: 80ch; margin: 0 0 10px; }
.va-detail .code-line {
  font: 600 11px/1 var(--font-mono); color: var(--c-yellow);
  background: rgba(0,0,0,0.35); border: 1px solid var(--edge);
  padding: 6px 9px; border-radius: var(--r-2); display: inline-block; letter-spacing: 0.04em;
}

/* ─────────────────────────────────────────────────────────────────
   VARIATION B — Card Grid
   ───────────────────────────────────────────────────────────────── */
.vb-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 12px;
}
.vb-card {
  background: linear-gradient(150deg, #0f1b33, #0c1325 60%, #0a1020);
  border: 1px solid var(--edge);
  border-radius: var(--r-4);
  overflow: hidden;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  display: flex; flex-direction: column;
  cursor: pointer;
}
.vb-card:hover { border-color: rgba(255,255,255,0.15); box-shadow: var(--shadow-sm); }
.vb-card.expanded {
  border-color: color-mix(in oklch, var(--type-color, var(--c-blue)) 45%, transparent);
  box-shadow: 0 0 0 1px color-mix(in oklch, var(--type-color, var(--c-blue)) 25%, transparent) inset,
              var(--shadow-md);
}
.vb-card[data-type="attack"]   { --type-color: var(--c-red); }
.vb-card[data-type="reaction"] { --type-color: var(--c-teal); }
.vb-card[data-type="seidr"]    { --type-color: var(--c-purple); }
.vb-card[data-type="galdr"]    { --type-color: var(--c-cyan); }
.vb-card[data-type="kenning"]  { --type-color: var(--c-orange); }
.vb-card[data-type="stance"]   { --type-color: var(--c-yellow); }
.vb-card[data-type="combat"]    { --type-color: var(--c-red); }
.vb-card[data-type="defensive"] { --type-color: var(--c-blue); }
.vb-card[data-type="arcane"]    { --type-color: var(--c-purple); }
.vb-card[data-type="memory"]    { --type-color: var(--c-cyan); }
.vb-card[data-type="social"]    { --type-color: var(--c-teal); }
.vb-card[data-type="origin"]    { --type-color: var(--c-yellow); }
.vb-card[data-type="mainhand"],
.vb-card[data-type="melee"]    { --type-color: var(--c-red); }
.vb-card[data-type="ranged"]    { --type-color: var(--c-orange); }
.vb-card[data-type="offhand"],
.vb-card[data-type="shield"]   { --type-color: var(--c-cyan); }
.vb-card[data-type="head"],
.vb-card[data-type="helm"]     { --type-color: var(--c-purple); }
.vb-card[data-type="body"],
.vb-card[data-type="armor"]    { --type-color: var(--c-blue); }
.vb-card[data-type="hands"],
.vb-card[data-type="gloves"]   { --type-color: var(--c-yellow); }
.vb-card[data-type="feet"],
.vb-card[data-type="boots"]    { --type-color: var(--c-green); }
.vb-card[data-type="trinket"],
.vb-card[data-type="ring"]     { --type-color: var(--c-grey); }
.vb-card[data-type="quick"]    { --type-color: var(--c-magenta); }

.vb-head {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  padding: 12px 14px 8px;
}
.vb-head .row1 {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  grid-column: 1 / -1;
}
.vb-head .row2 {
  display: flex; align-items: center; gap: 10px;
  grid-column: 1 / -1;
}
.vb-name { font: 700 15px/1.2 var(--font-sans); color: var(--text); }
.vb-kw-head {
  flex: 1; min-width: 0;
  display: flex; gap: 4px; flex-wrap: wrap; overflow: hidden;
}
.vb-icons-head {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 4px;
  flex-shrink: 0;
}
.vb-kw-head .kw {
  font-size: 10px; text-transform: lowercase; letter-spacing: 0.02em;
  color: var(--faint);
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--edge);
  border-radius: var(--r-pill);
  padding: 2px 7px;
  white-space: nowrap;
}
.vb-kw-head .kw.kw-chip { cursor: pointer; transition: color .12s, border-color .12s, background .12s; }
.vb-kw-head .kw.kw-chip:hover {
  color: var(--c-cyan);
  border-color: color-mix(in oklch, var(--c-cyan) 50%, var(--edge));
  background: color-mix(in oklch, var(--c-cyan) 8%, transparent);
}
.vb-fav {
  appearance: none; background: transparent; border: 0;
  color: var(--faint); font-size: 16px; cursor: pointer; padding: 4px; line-height: 1;
}
.vb-fav.on { color: var(--c-yellow); }

.vb-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  padding: 0 14px 12px;
}
.vb-metric {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  padding: 3px 7px;
  border-radius: 4px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.06);
  font-variant-numeric: tabular-nums;
}
.vb-metric .v { font: 800 13px/1 var(--font-sans); color: var(--text); }
.vb-metric .v.dash { color: var(--faint); font-weight: 500; }
.vb-metric .l {
  font: 700 9px/1 var(--font-sans);
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--faint);
}
/* Per-metric value colors mirror .m-* utility classes above. */
.vb-metric .v.m-atk { color: var(--c-red); }
.vb-metric .v.m-brk { color: var(--c-blue); }
.vb-metric .v.m-prc { color: var(--text); }
.vb-metric .v.m-imp { color: var(--c-orange); }
.vb-metric .v.m-spd { color: var(--c-green); }
.vb-metric .v.m-rng { color: var(--c-pink); }
.vb-metric .v.m-def { color: var(--stat-res); }
.vb-metric .v.m-mag { color: var(--c-cyan); }

.vb-foot { padding: 0; display: flex; flex-direction: column; gap: 8px; }
.vb-card.expanded .vb-foot { padding: 0 14px 12px; }
.vb-detail {
  display: none;
  border-top: 1px dashed var(--edge);
  padding-top: 10px;
  font-size: 12.5px; line-height: 1.5; color: var(--text);
}
.vb-card.expanded .vb-detail { display: block; }
.vb-detail .full-kw {
  margin: 0 0 8px;
  font-size: 11px; color: var(--faint); text-transform: lowercase;
}
.vb-detail .code-line {
  margin-top: 8px;
  display: inline-block;
  font: 600 11px/1 var(--font-mono); color: var(--c-yellow);
  background: rgba(0,0,0,0.45); border: 1px solid var(--edge);
  padding: 5px 8px; border-radius: var(--r-2); letter-spacing: 0.04em;
}

.empty-state {
  text-align: center; color: var(--faint); padding: 48px 16px;
  font: 400 13px/1.5 var(--font-sans);
  background: var(--panel); border: 1px dashed var(--edge); border-radius: var(--r-3);
}
.empty-state strong { color: var(--text); font-weight: 700; display: block; margin-bottom: 6px; font-size: 14px; }

/* ── Star col header & resize handles ── */
.va-table thead th .col-resize {
  position: absolute; top: 0; right: 0; width: 6px; height: 100%;
  cursor: col-resize; user-select: none;
}
.va-table thead th .col-resize:hover { background: rgba(122,166,255,0.3); }
.va-table .star-th { color: var(--c-yellow); font-size: 13px; }
.va-table thead th.col-star { width: 22px; text-align: center; padding: 8px 2px; }
.va-table thead th.col-star::before { display: none; }
.va-table thead th.col-type, .va-table thead th.col-cost { padding: 8px 8px; }
/* The type column now sits tight against its neighbor — its right
   padding only needs to reach the badge edge, not span an em of letter-
   spaced uppercase whitespace. */
.va-table thead th.col-type { padding-right: 4px; }
.va-row td.col-type        { padding-right: 4px; }

/* Type cell with dmg icons inline */
.type-cell { display: inline-flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
.type-cell .dmg-type { width: 18px; height: 18px; font-size: 10px; }

/* Cost cell — multiple pills */
.cost-cell { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
/* Symbol mode pins the cost column wide enough to seat at least two 22px
   rune symbols on the same line — two chips + 4px gap + 4px breathing room.
   nowrap keeps them flush even when the table column is wider than needed. */
.cost-cell.cost-cell-symbol {
  flex-wrap: nowrap;
  min-width: 52px;
}

/* Rune cost pill — yellow text, teal outline; perfectly round chip. The full
   rune name appears on hover (title attr) and in the expanded detail. */
.cost-pill.rune-pill {
  color: var(--c-yellow);
  border-color: var(--c-teal, #5ee0c2);
  background: rgba(94,224,194,0.08);
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono);
  text-transform: none; letter-spacing: 0;
  padding: 0;
  width: 22px; height: 22px;
  min-width: 0;
  border-radius: 50%;
  box-sizing: border-box;
}
.cost-pill.rune-pill .rune-sym {
  font-family: var(--font-runic); color: var(--c-yellow);
  font-size: 15px; line-height: 1;
  display: inline-block;
}
/* Three-letter and full variants drop the round shape so the name has room. */
.cost-pill.rune-pill.rune-pill-three,
.cost-pill.rune-pill.rune-pill-full {
  width: auto;
  border-radius: var(--r-pill, 999px);
  padding: 0 8px 0 6px;
  gap: 5px;
}
.cost-pill.rune-pill.rune-pill-three .rune-name,
.cost-pill.rune-pill.rune-pill-full .rune-name {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--c-yellow);
  line-height: 1;
}
/* Compressed multi-rune pill — round chip displaying the rune count;
   click/hover reveals the full rune list in a popover. */
.cost-pill.rune-pill.rune-pill-multi { cursor: pointer; }
.cost-pill.rune-pill.rune-pill-multi:hover {
  background: rgba(94,224,194,0.18);
  border-color: var(--c-teal, #5ee0c2);
}
.cost-pill.rune-pill.rune-pill-multi .rune-count {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 800;
  color: var(--c-yellow);
  line-height: 1;
  letter-spacing: 0;
}

/* Rune popover (shown on hover/click of a compressed multi-rune pill) */
.rune-tooltip {
  position: absolute;
  z-index: 999;
  background: var(--panel-deep, #0a1224);
  border: 1px solid color-mix(in oklch, var(--c-teal, #5ee0c2) 50%, var(--edge));
  border-radius: var(--r-2);
  padding: 8px 10px;
  min-width: 140px;
  max-width: 280px;
  box-shadow: var(--shadow-md, 0 8px 24px rgba(0,0,0,0.4));
  font: 400 12px/1.4 var(--font-sans);
  color: var(--text);
  display: flex; flex-direction: column; gap: 6px;
  pointer-events: auto;
}
.rune-tooltip strong {
  color: var(--c-teal, #5ee0c2);
  text-transform: uppercase;
  font: 700 10px/1 var(--font-sans);
  letter-spacing: 0.08em;
}
.rune-tooltip-body { display: flex; flex-direction: column; gap: 4px; }
.rune-tt-row {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-sans);
  font-size: 12px; color: var(--text);
}
.rune-tt-row .rune-sym {
  font-family: var(--font-runic);
  font-size: 18px; color: var(--c-yellow); line-height: 1;
  min-width: 18px; text-align: center;
}
.rune-tt-row .rune-tt-name {
  font-weight: 600; letter-spacing: 0.02em;
}

/* Full rune readout at the top of an expanded ability row. Pairs the symbol
   with the full rune name so the player learns the glyph by association. */
/* Full rune readout at the top of an expanded ability row. Each rune sits on
   its own subtle chip so the player can scan the costs as discrete items
   rather than one merged block. Capped to a single horizontal row — abilities
   never carry more than six runes, so wrapping is never needed. */
.rune-list {
  display: flex;
  flex-wrap: nowrap;
  gap: 4px 8px;
  margin: 0 0 10px;
  padding: 0;
  background: transparent;
  border: 0;
  overflow: hidden;
}
.rune-list-item {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--text);
  letter-spacing: 0.02em;
  white-space: nowrap;
  padding: 4px 10px 4px 8px;
  background: rgba(94,224,194,0.05);
  border: 1px solid rgba(94,224,194,0.22);
  border-radius: var(--r-pill, 999px);
}
.rune-list-item .rune-sym {
  font-family: var(--font-runic);
  font-size: 18px;
  color: var(--c-yellow);
  line-height: 1;
}
.rune-list-item .rune-list-name {
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0.02em;
  color: var(--text);
}

/* Keyword inline link */
.kw-link {
  color: var(--c-cyan);
  border-bottom: 1px dotted var(--c-cyan);
  cursor: pointer;
}
.kw-link:hover { color: var(--text); border-bottom-color: var(--text); }

/* Keyword tooltip popover */
.kw-tooltip {
  position: absolute;
  z-index: 999;
  max-width: 340px;
  background: var(--panel-raised, #1a2742);
  border: 1px solid var(--c-cyan);
  border-radius: var(--r-2);
  padding: 10px 12px;
  color: var(--text);
  font: 400 12.5px/1.5 var(--font-sans);
  box-shadow: var(--shadow-md);
  display: flex; flex-direction: column; gap: 4px;
}
.kw-tooltip strong { color: var(--c-cyan); text-transform: lowercase; font: 700 11px/1.2 var(--font-sans); letter-spacing: 0.04em; }
.kw-tooltip .kw-tt-body { color: var(--muted); }

/* Status hover tooltip (filter chips) — colored to the status it describes */
.status-tip {
  position: absolute;
  z-index: 1000;
  transform: translateX(-50%);
  pointer-events: none;
  max-width: 260px;
  background: var(--panel-raised, #1a2742);
  border: 1.5px solid var(--status-color, var(--c-teal));
  border-radius: var(--r-2);
  padding: 8px 12px;
  color: var(--text);
  font: 400 12px/1.45 var(--font-sans);
  box-shadow: 0 8px 24px rgba(0,0,0,0.4),
              0 0 22px color-mix(in oklch, var(--status-color, transparent) 35%, transparent);
  display: flex; flex-direction: column; gap: 3px;
}
.status-tip::before {
  content: "";
  position: absolute;
  top: -6px; left: 50%; transform: translateX(-50%) rotate(45deg);
  width: 10px; height: 10px;
  background: var(--panel-raised, #1a2742);
  border-left: 1.5px solid var(--status-color, var(--c-teal));
  border-top: 1.5px solid var(--status-color, var(--c-teal));
}
.status-tip strong {
  color: var(--status-color, var(--c-teal));
  font: 700 11px/1 var(--font-sans);
  text-transform: uppercase; letter-spacing: 0.1em;
}
.status-tip .status-tip-body { color: var(--muted); }
.status-tip[data-s="burning"]  { --status-color: var(--status-burning); }
.status-tip[data-s="freezing"] { --status-color: var(--status-freezing); }
.status-tip[data-s="poisoned"] { --status-color: var(--status-poisoned); }
.status-tip[data-s="decay"]    { --status-color: var(--status-decay); }
.status-tip[data-s="thorned"]  { --status-color: var(--status-thorned); }
.status-tip[data-s="shocked"]  { --status-color: var(--status-shocked); }
.status-tip[data-s="jolted"]   { --status-color: var(--status-jolted); }
.status-tip[data-s="bleeding"] { --status-color: var(--status-bleeding); }

/* ── Combat embed (iframe of live mockup) ────────────────────────
   Three layout variants explore how the combat tracker can sit inside
   the surrounding tabs. They switch via the .combat-embed wrapper class:
     .v-window  — framed window, padded, drop-shadow (current default)
     .v-seamless— edge-to-edge, no border, fills the tab
     .v-page    — matches the other tabs' page padding + chrome paradigm
*/
.combat-embed-wrap {
  display: flex; flex-direction: column; gap: 12px;
}
.combat-embed-toolbar {
  display: flex; align-items: center; gap: 10px;
  font-size: 11px; color: var(--faint);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.combat-embed-toolbar .lbl { font-weight: 700; }
.combat-embed-toolbar .seg {
  display: inline-flex; gap: 2px;
  background: var(--panel-deep);
  border: 1px solid var(--edge);
  border-radius: var(--r-2);
  padding: 2px;
}
.combat-embed-toolbar .seg button {
  all: unset; cursor: pointer;
  padding: 4px 10px;
  border-radius: 4px;
  font: 600 11px/1 var(--font-sans);
  color: var(--muted);
  letter-spacing: 0.04em;
  text-transform: none;
}
.combat-embed-toolbar .seg button:hover { color: var(--text); }
.combat-embed-toolbar .seg button.on {
  background: color-mix(in oklch, var(--c-cyan) 14%, transparent);
  color: var(--c-cyan);
  box-shadow: inset 0 0 0 1px color-mix(in oklch, var(--c-cyan) 35%, transparent);
}
.combat-embed-toolbar .hint { color: var(--faint); text-transform: none; letter-spacing: 0; font-size: 11px; }

.combat-embed {
  border: 1px solid var(--edge);
  border-radius: var(--r-3);
  overflow: hidden;
  background: var(--panel-deep);
  box-shadow: var(--shadow-2);
}
.combat-embed iframe {
  display: block;
  width: 100%;
  height: calc(100vh - 260px);
  min-height: 520px;
  border: 0;
  background: var(--bg);
}

/* v-seamless — strip the window chrome so the tracker fills the tab.
   The iframe is also made transparent so the host page's aurora gradient
   (--bg-field) shows through; combat-ui.html stamps data-embedded on its
   <html> and combat-ui.css drops its own background in that mode. The
   iframe stretches to fill the viewport from its top edge down to the
   page's bottom padding so there's no "black bar" gap below it. */
.combat-embed.v-seamless {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  margin: 0 calc(var(--page-pad, 16px) * -1);
}
.combat-embed.v-seamless iframe {
  background: transparent;
  /* 88px = top of the iframe inside the tabs/page chrome; 24px =
     comfortable breathing room at the bottom of the viewport. Adjusted
     down from `100vh - 200px` which left a visible empty band. */
  height: calc(100vh - 112px);
}

/* v-page — framed window with a page header strip + filter-bar-style
   placeholder above. Makes Combat read more like the other tabs. */
.combat-embed-page-head {
  display: none;
  align-items: center; gap: 10px;
  padding: 10px 14px;
  border: 1px solid var(--edge);
  border-bottom: 0;
  border-radius: var(--r-3) var(--r-3) 0 0;
  background: var(--panel-deep);
  font: 600 12px/1 var(--font-sans);
  color: var(--muted);
  letter-spacing: 0.04em;
}
.combat-embed-page-head .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--c-green);
  box-shadow: 0 0 6px color-mix(in oklch, var(--c-green) 45%, transparent);
}
.combat-embed-page-head .sep { flex: 1; }
.combat-embed-page-head .meta { font-size: 11px; color: var(--faint); }
.v-page .combat-embed-page-head { display: flex; }
.v-page .combat-embed {
  border-radius: 0 0 var(--r-3) var(--r-3);
  border-top: 0;
}


/* ── Tester tab ── */
.tester {
  display: flex; flex-direction: column; gap: 14px;
}
.tester-setup {
  display: grid;
  grid-template-columns: 1fr 220px 1fr;
  gap: 14px;
  align-items: stretch;
}
.tester-card {
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: var(--r-3);
  padding: 14px;
  display: flex; flex-direction: column; gap: 10px;
}
.tester-att { border-left: 3px solid var(--c-red); }
.tester-def { border-left: 3px solid var(--c-blue); }
.tc-eyebrow {
  font: 700 10px/1 var(--font-sans);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--faint);
}
.tester-card select {
  width: 100%;
  background: var(--panel-deep);
  border: 1px solid var(--edge);
  color: var(--text);
  padding: 8px 10px;
  border-radius: var(--r-2);
  font: 500 13px var(--font-sans);
  cursor: pointer;
}
.tester-card select:focus { outline: none; border-color: rgba(122,166,255,0.5); }
.tc-stats {
  display: flex; gap: 16px; flex-wrap: wrap;
  font: 700 12px/1 var(--font-mono); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.tc-stats b { color: var(--faint); font-weight: 700; margin-right: 4px; }
.tc-ability-stats {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
}
.ts-pill {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--panel-deep);
  border: 1px solid var(--edge);
  border-radius: var(--r-2);
  padding: 4px 8px;
  font: 700 11px/1 var(--font-mono);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.tc-mini-vitals { display: flex; flex-direction: column; gap: 6px; margin-top: auto; }
.tc-mini-vitals .vital { display: flex; align-items: center; gap: 8px; }
.tc-mini-vitals .vbar { flex: 1; height: 6px; background: var(--panel-deep); border-radius: 3px; overflow: hidden; }
.tc-mini-vitals .vfill { height: 100%; }
.tc-mini-vitals .m-str { background: var(--c-red); }
.tc-mini-vitals .m-res { background: var(--c-blue); }
.tc-mini-vitals .vlbl {
  font: 700 10px/1 var(--font-mono); color: var(--muted);
  width: 60px;
}

/* Versus / Run column */
.tester-versus {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 12px;
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: var(--r-3);
  padding: 18px 12px;
}
.run-btn {
  appearance: none;
  width: 110px; height: 110px;
  border-radius: 50%;
  border: 2px solid var(--c-orange);
  background: radial-gradient(circle at 35% 30%, color-mix(in oklch, var(--c-orange) 50%, transparent), var(--panel-deep) 75%);
  color: var(--text);
  font: 800 22px/1 var(--font-display);
  letter-spacing: 0.18em;
  cursor: pointer;
  box-shadow: 0 0 22px color-mix(in oklch, var(--c-orange) 35%, transparent);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.run-btn:hover:not(:disabled) { transform: scale(1.04); box-shadow: 0 0 32px color-mix(in oklch, var(--c-orange) 55%, transparent); }
.run-btn:disabled { opacity: 0.6; cursor: wait; }
.iter-pick {
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px;
  width: 100%;
}
.itc {
  appearance: none;
  background: var(--panel-deep);
  border: 1px solid var(--edge);
  color: var(--muted);
  padding: 6px 4px;
  border-radius: var(--r-2);
  font: 700 10.5px/1 var(--font-mono);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.itc.on { color: var(--c-orange); border-color: var(--c-orange); background: color-mix(in oklch, var(--c-orange) 15%, transparent); }
.iter-label {
  font: 700 9px/1 var(--font-sans);
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--faint);
}

/* Empty + results */
.tester-empty {
  text-align: center; color: var(--faint); padding: 36px 16px;
  font: 400 12.5px/1.5 var(--font-sans);
  background: var(--panel); border: 1px dashed var(--edge); border-radius: var(--r-3);
}
.tester-empty strong { color: var(--text); display: block; margin-bottom: 4px; }

.tester-results {
  display: flex; flex-direction: column; gap: 14px;
}
.results-stats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;
}
.rs {
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: var(--r-2);
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 4px;
}
.rs .lbl {
  font: 700 9.5px/1 var(--font-sans); text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--faint);
}
.rs .val {
  font: 800 26px/1 var(--font-mono);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.rs .val .unit { font-size: 14px; color: var(--faint); margin-left: 2px; }
.rs .val.m-atk { color: var(--c-red); }
.rs .val.m-brk { color: var(--c-blue); }

.results-hist, .results-statuses {
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: var(--r-3);
  padding: 14px;
}
.rh-title {
  font: 700 11px/1 var(--font-sans); text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--faint); margin-bottom: 10px;
}
.rh-bars {
  display: flex; gap: 4px; align-items: stretch;
  height: 180px;
  border-bottom: 1px solid var(--edge);
  padding-bottom: 4px;
}
.rh-col { flex: 1; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 4px; min-width: 0; }
.rh-bar {
  width: 100%; max-width: 48px;
  background: linear-gradient(180deg, var(--c-red), color-mix(in oklch, var(--c-red) 40%, var(--panel-deep)));
  border-radius: 2px 2px 0 0;
  position: relative;
  min-height: 4px;
}
.rh-col.miss .rh-bar {
  background: linear-gradient(180deg, var(--faint), color-mix(in oklch, var(--faint) 30%, var(--panel-deep)));
}
.rh-ct {
  position: absolute; top: -16px; left: 50%; transform: translateX(-50%);
  font: 700 10px/1 var(--font-mono); color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.rh-lbl {
  font: 700 10px/1 var(--font-mono); color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.stacks { display: flex; gap: 12px; flex-wrap: wrap; }
.stacks .status-token .count { font-size: 13px; }

/* ── Archetype pill (trait column) ─────────────────────────────
   Neutral by default; the four known archetypes get one of the
   established hue assignments from the design system. */
.archetype-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-pill, 999px);
  border: 1px solid color-mix(in oklch, var(--arch-color, var(--muted)) 35%, transparent);
  background: color-mix(in oklch, var(--arch-color, var(--muted)) 8%, transparent);
  color: var(--arch-color, var(--muted));
  font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: var(--ls-caps, 0.08em);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.archetype-pill[data-arch="knight"]    { --arch-color: var(--c-blue); }
.archetype-pill[data-arch="berserker"] { --arch-color: var(--c-red); }
.archetype-pill[data-arch="valsja"]    { --arch-color: var(--c-purple); }
.archetype-pill[data-arch="skald"]     { --arch-color: var(--c-cyan); }
.archetype-pill[data-arch="seer"]      { --arch-color: var(--c-yellow); }
.archetype-pill[data-arch="any"]       { --arch-color: var(--muted); }

/* Archetype filter chips inherit the same color mapping */
.chip-arch[data-arch="knight"]    { color: var(--c-blue); }
.chip-arch[data-arch="berserker"] { color: var(--c-red); }
.chip-arch[data-arch="valsja"]    { color: var(--c-purple); }
.chip-arch[data-arch="skald"]     { color: var(--c-cyan); }
.chip-arch[data-arch="seer"]      { color: var(--c-yellow); }
.chip-arch.on[data-arch="knight"]    { border-color: var(--c-blue);    background: color-mix(in oklch, var(--c-blue)    14%, transparent); }
.chip-arch.on[data-arch="berserker"] { border-color: var(--c-red);     background: color-mix(in oklch, var(--c-red)     14%, transparent); }
.chip-arch.on[data-arch="valsja"]    { border-color: var(--c-purple);  background: color-mix(in oklch, var(--c-purple)  14%, transparent); }
.chip-arch.on[data-arch="skald"]     { border-color: var(--c-cyan);    background: color-mix(in oklch, var(--c-cyan)    14%, transparent); }
.chip-arch.on[data-arch="seer"]      { border-color: var(--c-yellow);  background: color-mix(in oklch, var(--c-yellow)  14%, transparent); }

/* Potential-cost chips — yellow like the cost pill family */
.chip-cost {
  color: var(--c-yellow);
  border-color: rgba(247,200,115,0.32);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
}
.chip-cost:hover  { border-color: rgba(247,200,115,0.55); background: rgba(247,200,115,0.08); }
.chip-cost.on     { border-color: var(--c-yellow);        background: rgba(247,200,115,0.18); }
.chip-cost .ct    { color: var(--faint); }
.chip-cost.on .ct { color: var(--c-yellow); }

/* ── Equipment slot strip ──────────────────────────────────────
   Surfaces above the equipment table, showing each of the eight
   ordained slots and whether it is filled or missing. Empty slots
   read as a muted dashed cell — present but unfulfilled. */
/* ── Slot strip — header chrome ───────────────────────────────
   The strip wraps a row count (filled/total subslots) and a small
   segmented control that swaps the layout variant beneath it. All
   three variants share this header, so the chrome stays steady while
   the body re-renders. */
.slot-strip {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 10px 0 14px;
  padding: 10px 12px;
  border: 1px solid var(--edge);
  border-radius: var(--r-3, 8px);
  background: var(--panel);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04);
}
.slot-strip-head {
  display: flex; align-items: center; gap: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--edge);
  border-right: none;
  min-width: 0; padding-right: 0;
  flex-direction: row;
}
.slot-strip-head .ss-label {
  font-size: 10px; text-transform: uppercase; letter-spacing: var(--ls-caps, 0.08em);
  color: var(--muted);
}
.slot-strip-head .ss-count {
  font-size: 16px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.slot-strip-head .ss-of { color: var(--faint); margin: 0 1px; font-weight: 400; }

/* Segmented layout switcher inside the strip head. */
.slot-layout-toggle {
  display: inline-flex;
  margin-left: auto;
  border: 1px solid var(--edge);
  border-radius: var(--r-2, 6px);
  overflow: hidden;
}
.slot-layout-btn {
  appearance: none; background: transparent; border: 0;
  color: var(--muted);
  padding: 5px 10px;
  font: 700 9px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
  cursor: pointer;
  border-right: 1px solid var(--edge);
  transition: background 0.12s, color 0.12s;
}
.slot-layout-btn:last-child { border-right: 0; }
.slot-layout-btn:hover { color: var(--text); background: rgba(255,255,255,0.03); }
.slot-layout-btn.on {
  background: rgba(122,166,255,0.12);
  color: var(--c-blue);
}

/* Legacy cells layout (kept for the cards variant body). */
.slot-strip-cells {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 8px;
  flex: 1;
  min-width: 0;
}

/* ── Variant A: Rail ──────────────────────────────────────────
   A wrap-friendly flex row of slot chips. Each chip is one inline
   pill carrying icon + label + (n/m for multi-cap) + items inline.
   Reads densest; great for desktop. */
.slot-rail {
  display: flex; flex-wrap: wrap;
  gap: 6px;
}
.slot-rail-chip {
  position: relative;
  display: inline-flex; align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border: 1px solid var(--edge);
  border-radius: var(--r-pill, 999px);
  background: rgba(255,255,255,0.02);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
  font: 400 12px/1 var(--font-sans);
  min-width: 0;
}
.slot-rail-chip:hover { background: rgba(255,255,255,0.04); }
.slot-rail-chip.open {
  border-color: var(--c-blue);
  background: rgba(122,166,255,0.06);
  z-index: 10;
}
.slot-rail-chip .slot-icon { width: 14px; height: 14px; flex-shrink: 0; }
.slot-rail-chip .slot-rail-label {
  font: 700 9px/1 var(--font-sans);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--muted);
  flex-shrink: 0;
}
.slot-rail-chip .slot-rail-count {
  font: 700 11px/1 var(--font-mono);
  color: var(--text);
  padding: 2px 6px;
  border-radius: var(--r-1, 4px);
  background: rgba(255,255,255,0.04);
  font-variant-numeric: tabular-nums;
}
.slot-rail-chip .slot-rail-items {
  color: var(--text);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  max-width: 180px;
}
.slot-rail-chip .slot-rail-missing {
  color: var(--c-red); font-style: italic; font-weight: 500;
}
.slot-rail-chip[data-slot="ranged"].empty .slot-rail-missing,
.slot-rail-chip[data-slot="ring"].empty   .slot-rail-missing { color: var(--muted); font-style: normal; }
.slot-rail-chip.empty { border-style: dashed; }
.slot-rail-chip .slot-caret { font-size: 10px; color: var(--faint); flex-shrink: 0; }
.slot-rail-chip[data-slot="melee"].filled  { border-color: color-mix(in oklch, var(--c-red)     35%, var(--edge)); }
.slot-rail-chip[data-slot="ranged"].filled { border-color: color-mix(in oklch, var(--c-orange)  35%, var(--edge)); }
.slot-rail-chip[data-slot="shield"].filled { border-color: color-mix(in oklch, var(--c-cyan)    35%, var(--edge)); }
.slot-rail-chip[data-slot="head"].filled,
.slot-rail-chip[data-slot="body"].filled   { border-color: color-mix(in oklch, var(--c-blue)    35%, var(--edge)); }
.slot-rail-chip[data-slot="hands"].filled  { border-color: color-mix(in oklch, var(--c-yellow)  35%, var(--edge)); }
.slot-rail-chip[data-slot="feet"].filled   { border-color: color-mix(in oklch, var(--c-green)   35%, var(--edge)); }
.slot-rail-chip[data-slot="ring"].filled   { border-color: color-mix(in oklch, var(--c-grey)    45%, var(--edge)); }
.slot-rail-chip[data-slot="quick"].filled  { border-color: color-mix(in oklch, var(--c-magenta) 35%, var(--edge)); }

/* ── Variant B: Cards (compact) ───────────────────────────────
   8-up grid of stubby cards. Pips show the slot's capacity at a
   glance; the primary item name takes the visible line and any
   secondary items collapse into a "+N" badge to keep a fixed height. */
.slot-cards {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 8px;
  min-width: 0;
}
.slot-card {
  display: flex; flex-direction: column;
  gap: 4px;
  padding: 6px 8px 8px;
}
.slot-card .slot-card-head {
  display: flex; align-items: center; gap: 6px;
}
.slot-card .slot-card-head .slot-icon { width: 14px; height: 14px; }
.slot-card .slot-card-head .slot-lbl {
  font: 700 9px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--muted);
  white-space: nowrap;
}
.slot-card .slot-card-count {
  margin-left: auto;
  font: 700 10px/1 var(--font-mono); color: var(--text);
  font-variant-numeric: tabular-nums;
}
.slot-card .slot-pips {
  display: flex; gap: 3px;
}
.slot-card .slot-pip {
  width: 8px; height: 6px;
  border-radius: 2px;
  border: 1px solid var(--edge);
  background: transparent;
}
.slot-card .slot-pip.on {
  background: color-mix(in oklch, var(--slot-tint, var(--c-blue)) 50%, transparent);
  border-color: color-mix(in oklch, var(--slot-tint, var(--c-blue)) 70%, var(--edge));
}
.slot-card .slot-val {
  font-size: 12px; font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.slot-card .slot-extra {
  font: 700 10px/1 var(--font-mono); color: var(--muted);
  margin-left: 4px;
}
.slot-card .slot-caret {
  position: absolute; top: 6px; right: 8px;
  font-size: 10px; color: var(--faint);
  transition: transform 0.15s, color 0.15s;
}
.slot-card.open .slot-caret { transform: rotate(180deg); color: var(--c-blue); }

/* ── Variant C: Tiles ─────────────────────────────────────────
   Each slot is rendered as a header row over a horizontal strip of
   one-tile-per-subslot. Single-cap slots and collapsed multi-cap
   slots take an equal share; an expanded multi-cap slot grows to its
   sub-slot count (Ring → 2 shares, Quick Items → 3 shares) so each
   sub-tile renders at the same width as the surrounding worn slots. */
.slot-tiles {
  display: flex;
  /* Items align to the top so an expanded multi-slot can grow
     downward without dragging its single-cap siblings taller. The
     siblings keep their natural height; only the expanded slot
     stacks its sub-tiles vertically beneath itself. */
  align-items: flex-start;
  gap: 8px;
  min-width: 0;
}
.slot-tiles-group {
  display: flex; flex-direction: column; gap: 4px;
  flex: 1 1 0;
  min-width: 0;
  position: relative;
}
/* Expanded multi-cap slots: NO horizontal growth (so their neighbours
   keep their column widths). The sub-tiles stack vertically beneath
   the slot head instead, courtesy of `flex-direction: column` on
   .slot-tiles-row below. */

/* Multi-cap tile body: item name centered (same shape as single-cap
   tiles) with a small pip row pinned to the bottom-right corner so
   the slot still communicates how many sub-slots are filled at a
   glance. The pip-row is absolute so it doesn't crowd the name. */
.slot-tile.slot-tile-multi {
  flex-direction: row;
  align-items: center;
  justify-content: center;
  padding: 6px 6px;
  position: relative;
}
.slot-pip-row {
  display: inline-flex; align-items: center; gap: 4px;
}
.slot-pip-row.slot-pip-row-corner {
  position: absolute;
  right: 4px;
  bottom: 3px;
  gap: 3px;
  pointer-events: none;
}
.slot-pip-row.slot-pip-row-corner .slot-mini-pip {
  width: 5px; height: 5px;
}
.slot-mini-pip {
  width: 7px; height: 7px;
  border-radius: 50%;
  border: 1px solid color-mix(in oklch, var(--c-yellow) 45%, var(--edge));
  background: transparent;
  box-sizing: border-box;
}
.slot-mini-pip.on {
  background: var(--c-yellow);
  border-color: var(--c-yellow);
  box-shadow: 0 0 6px color-mix(in oklch, var(--c-yellow) 35%, transparent);
}
/* Per-slot pip color: Quick Items uses the magenta slot accent to match
   its tile-border treatment. Ring stays grey (default). */
.slot-mini-pip[data-slot="quick"] {
  border-color: color-mix(in oklch, var(--c-magenta) 45%, var(--edge));
}
.slot-mini-pip[data-slot="quick"].on {
  background: var(--c-magenta);
  border-color: var(--c-magenta);
  box-shadow: 0 0 6px color-mix(in oklch, var(--c-magenta) 35%, transparent);
}

/* ── Multi-cap expansion popup ──
   When the user opens Ring or Quick Items, a floating popup anchored
   to the slot group renders the per-sub-slot tiles (Ring 1, Ring 2,
   etc.) plus the shared SlotPicker. The popup is absolutely
   positioned beneath the tile so it overlays neighbouring rows
   instead of inflating the slot strip. */
.slot-multi-pop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 25;
  display: flex; flex-direction: column; gap: 6px;
  min-width: max(220px, 100%);
  padding: 8px;
  background: var(--panel-raised, #121b33);
  border: 1px solid var(--edge-strong, rgba(255,255,255,0.22));
  border-radius: var(--r-2, 6px);
  box-shadow: 0 10px 24px rgba(0,0,0,0.45);
}
.slot-multi-subtiles {
  display: flex; flex-direction: column; gap: 4px;
}
.slot-tile-sub {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px;
  min-height: 30px;
  cursor: default;
}
.slot-tile-sub .slot-tile-sub-idx {
  font: 700 10px/1 var(--font-mono);
  color: var(--faint);
  width: 14px;
  text-align: center;
  flex: 0 0 auto;
}
.slot-tile-sub .slot-tile-name {
  font: 600 11px/1.2 var(--font-sans);
  color: var(--text);
  text-align: left;
  flex: 1 1 auto;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.slot-tile-sub.empty .slot-tile-name { color: var(--faint); font-weight: 400; }
/* Inside the popup, the SlotPicker is a normal inline child (not
   absolutely positioned), so it stacks below the sub-tile list. The
   selector is intentionally chained through .slot-tiles-group to
   beat the absolutely-positioned rule that single-cap slots use. */
.slot-tiles-group .slot-multi-pop .slot-picker {
  position: static;
  top: auto; left: auto; right: auto;
  margin: 0;
  box-shadow: none;
  border: 0;
  background: transparent;
  padding: 0;
}

.slot-tiles-head {
  display: flex; align-items: center; gap: 6px;
  font: 700 9px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--muted);
}
.slot-tiles-head .slot-icon { width: 12px; height: 12px; }
.slot-tiles-count {
  margin-left: auto;
  font: 700 10px/1 var(--font-mono); color: var(--text);
  font-variant-numeric: tabular-nums;
}
.slot-tile {
  display: flex; align-items: center; justify-content: center;
  padding: 6px 6px;
  border: 1px solid var(--edge);
  border-radius: var(--r-2, 6px);
  background: rgba(255,255,255,0.02);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
  min-width: 0; min-height: 32px;
  position: relative;
}
.slot-tile:hover { background: rgba(255,255,255,0.04); }
.slot-tile.empty { border-style: dashed; }
.slot-tile .slot-tile-name {
  font: 600 11px/1.2 var(--font-sans);
  color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0; width: 100%;
  text-align: center;
}
.slot-tile.empty .slot-tile-name { color: var(--faint); font-weight: 400; }
.slot-tile[data-slot="melee"].filled  { border-color: color-mix(in oklch, var(--c-red)     35%, var(--edge)); }
.slot-tile[data-slot="ranged"].filled { border-color: color-mix(in oklch, var(--c-orange)  35%, var(--edge)); }
.slot-tile[data-slot="shield"].filled { border-color: color-mix(in oklch, var(--c-cyan)    35%, var(--edge)); }
.slot-tile[data-slot="head"].filled,
.slot-tile[data-slot="body"].filled   { border-color: color-mix(in oklch, var(--c-blue)    35%, var(--edge)); }
.slot-tile[data-slot="hands"].filled  { border-color: color-mix(in oklch, var(--c-yellow)  35%, var(--edge)); }
.slot-tile[data-slot="feet"].filled   { border-color: color-mix(in oklch, var(--c-green)   35%, var(--edge)); }
.slot-tile[data-slot="ring"].filled   { border-color: color-mix(in oklch, var(--c-grey)    45%, var(--edge)); }
.slot-tile[data-slot="quick"].filled  { border-color: color-mix(in oklch, var(--c-magenta) 35%, var(--edge)); }

/* Picker dropdown anchoring — each variant attaches the same picker
   to a different host element. Anchor the absolute picker to whichever
   host carries .open. */
.slot-rail-chip .slot-picker,
.slot-tiles-group .slot-picker {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: auto;
}
.slot-tiles-group { position: relative; }
/* ── Equipment-slot icons placed inside slot-cell ──
   The .slot-icon utility class lives in colors_and_type.css. Component-
   specific sizing/placement overrides go here: the in-cell icon is
   larger (20px) and sits flush with the slot label; the picker-head
   icon is the default size and floats inline with the label. When the
   slot is filled, the icon picks up the slot tint; when empty it dims
   to faint so the cell reads as a quiet placeholder. */
.slot-cell .slot-icon {
  width: 20px; height: 20px;
  margin-bottom: 2px;
}
.slot-cell.empty .slot-icon { opacity: 0.45; }
.slot-cell.filled .slot-icon { opacity: 1; }
.slot-picker-head .sph-title {
  display: inline-flex; align-items: center; gap: 6px;
}
.slot-picker-head .slot-icon { width: 14px; height: 14px; }

.slot-cell {
  display: flex; flex-direction: column; gap: 4px;
  min-width: 0; padding: 8px 8px 6px;
  border: 1px solid var(--edge);
  border-radius: var(--r-2, 6px);
  background: rgba(255,255,255,0.02);
  position: relative;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.slot-cell:hover { background: rgba(255,255,255,0.04); }
.slot-cell.open {
  border-color: var(--c-blue);
  background: rgba(122,166,255,0.06);
  z-index: 10;
}
.slot-cell .slot-caret {
  position: absolute; top: 6px; right: 8px;
  font-size: 10px; color: var(--faint);
  pointer-events: none;
  transition: transform 0.15s, color 0.15s;
}
.slot-cell.open .slot-caret { transform: rotate(180deg); color: var(--c-blue); }

/* Slot picker — dropdown listing every item that satisfies the slot. */
.slot-picker {
  position: absolute;
  top: calc(100% + 6px);
  left: -1px;
  right: -1px;
  min-width: 240px;
  max-height: 340px;
  overflow-y: auto;
  background: var(--panel-raised, #121b33);
  border: 1px solid var(--c-blue);
  border-radius: var(--r-2, 6px);
  box-shadow: 0 12px 32px rgba(0,0,0,0.55);
  z-index: 100;
  cursor: default;
  padding: 4px;
  display: flex; flex-direction: column; gap: 1px;
}
.slot-picker-head {
  display: flex; align-items: center; justify-content: space-between;
  font: 700 9px/1 var(--font-sans);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--muted);
  padding: 6px 8px 4px;
  border-bottom: 1px solid var(--edge);
  margin-bottom: 2px;
}
.slot-picker-clear {
  appearance: none; background: transparent; border: 1px solid var(--edge);
  color: var(--c-red); padding: 2px 8px;
  border-radius: var(--r-pill, 999px);
  font: 700 9px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
  cursor: pointer;
}
.slot-picker-clear:hover { border-color: var(--c-red); background: rgba(248,106,99,0.12); }
.slot-picker-empty {
  padding: 10px 12px; color: var(--faint); font-size: 11px; font-style: italic;
}
.slot-picker-row {
  appearance: none;
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 8px;
  border: 1px solid transparent;
  border-radius: var(--r-1, 4px);
  background: transparent;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  font: 400 12px/1.3 var(--font-sans);
}
.slot-picker-row:hover { background: rgba(255,255,255,0.04); border-color: var(--edge); }
.slot-picker-row.selected {
  border-color: color-mix(in oklch, var(--c-green) 50%, var(--edge));
  background: rgba(108,212,140,0.08);
}
.slot-picker-row.owned, .slot-picker-row[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  filter: grayscale(0.4);
}
.slot-picker-row.owned:hover { background: transparent; border-color: transparent; }
.slot-picker-row .sp-name { font-weight: 700; color: var(--text); }
.slot-picker-row .sp-meta { display: inline-flex; gap: 6px; font-variant-numeric: tabular-nums; }
.slot-picker-row .sp-stat {
  font: 700 10px/1 var(--font-mono);
  padding: 2px 5px;
  border-radius: var(--r-1, 4px);
  background: rgba(255,255,255,0.04);
  color: var(--muted);
}
.slot-picker-row .sp-stat.m-atk { color: var(--c-red); }
.slot-picker-row .sp-stat.m-def { color: var(--c-blue); }
.slot-picker-row .sp-stat.m-mag { color: var(--c-cyan); }
.slot-picker-row .sp-stat.m-spd { color: var(--c-green); }
.slot-picker-row .sp-tag {
  font: 700 9px/1 var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em;
  padding: 3px 6px; border-radius: var(--r-pill, 999px);
}
.slot-picker-row .sp-tag.sp-yours { background: rgba(108,212,140,0.18); color: var(--c-green); }
.slot-picker-row .sp-tag.sp-owner { background: rgba(255,255,255,0.04); color: var(--faint); border: 1px solid var(--edge); }
.slot-cell .slot-lbl {
  font-size: 9px; text-transform: uppercase; letter-spacing: var(--ls-caps, 0.08em);
  color: var(--muted); white-space: nowrap;
}
.slot-cell .slot-val {
  font-size: 12px; font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.slot-cell.filled { --slot-tint: var(--c-green); }
.slot-cell.filled { border-color: color-mix(in oklch, var(--slot-tint) 30%, var(--edge)); }
.slot-cell.empty {
  border-style: dashed;
  background: rgba(255,255,255,0.01);
}
.slot-cell.empty .slot-val { color: var(--c-red); font-style: italic; font-weight: 500; }
.slot-cell.empty[data-slot="ranged"] .slot-val,
.slot-cell.empty[data-slot="ring"]   .slot-val { color: var(--muted); font-style: normal; font-weight: 500; }
.slot-cell[data-slot="melee"].filled  { --slot-tint: var(--c-red);    }
.slot-cell[data-slot="ranged"].filled { --slot-tint: var(--c-orange);  }
.slot-cell[data-slot="shield"].filled { --slot-tint: var(--c-cyan);    }
.slot-cell[data-slot="head"].filled,
.slot-cell[data-slot="body"].filled   { --slot-tint: var(--c-blue);    }
.slot-cell[data-slot="hands"].filled  { --slot-tint: var(--c-yellow);  }
.slot-cell[data-slot="feet"].filled   { --slot-tint: var(--c-green);   }
.slot-cell[data-slot="ring"].filled   { --slot-tint: var(--c-grey);    }
.slot-cell[data-slot="quick"].filled  { --slot-tint: var(--c-magenta); }

@media (max-width: 860px) {
  .tester-setup { grid-template-columns: 1fr; }
  .tester-versus { padding: 16px 12px; }
  .run-btn { width: 96px; height: 96px; font-size: 20px; }
  .iter-pick { grid-template-columns: 1fr 1fr 1fr 1fr; }
  .results-stats { grid-template-columns: 1fr 1fr; }
  .rh-col .rh-lbl { font-size: 9px; }
  .combat-embed iframe { height: 70vh; }
}

@media (max-width: 720px) {
  .page { padding: 14px 12px 20px; }
  .page-head { flex-wrap: wrap; gap: 10px; }
  .char-block { width: 100%; border-left: none; padding-left: 0; border-top: 1px solid var(--edge); padding-top: 10px; flex-wrap: wrap; gap: 10px; }
  .char-name { font-size: 20px; }
  .char-stats { margin-left: 0; flex-wrap: wrap; gap: 10px; width: 100%; order: 3; }
  .char-stats .char-stat { align-items: center; }
  .potential-readout { margin-left: 0; padding-left: 0; border-left: 0; }
  .filter-bar { gap: 8px; padding: 8px; flex-wrap: wrap; }
  .filter-search { width: 100%; flex: 1 1 100%; min-width: 0; margin-left: 0; }
  .chip-rail { gap: 4px; flex: 1 1 100%; }
  .chip { font-size: 10px; padding: 5px 8px; }
  .count-readout { width: 100%; text-align: right; }
  .va-table-wrap { overflow-x: auto; }
  .va-table { min-width: 0; }
  /* On mobile the table scrolls horizontally; let every column scroll into
     view (including Keywords) rather than hiding them outright. */
  .va-row td { padding: 8px 6px; font-size: 12px; }
  .va-row .name { font-size: 12px; max-width: 120px; display: inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
  .va-table thead th { padding: 8px 6px; font-size: 9px; }
  .type-badge { font-size: 9px; padding: 2px 5px; }
  .cost-pill { font-size: 9px; padding: 2px 5px; }
  .vb-grid { grid-template-columns: 1fr; }
  .vb-kw-head { display: none; }
  .tab { padding: 9px 12px; font-size: 11px; }
  .view-toggle button { padding: 5px 8px; font-size: 10px; }
  .slot-strip { flex-direction: column; gap: 8px; padding: 8px; }
  .slot-strip-head { flex-direction: row; align-items: baseline; gap: 8px;
                     padding-right: 0; border-right: 0;
                     border-bottom: 1px solid var(--edge); padding-bottom: 6px; }
  .slot-strip-cells { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .slot-cell .slot-lbl { font-size: 8px; }
  .slot-cell .slot-val { font-size: 11px; }
}

/* ─────────────────────────────────────────────────────────────────────
   Header variation explorations
   Five layouts for the brand/character/stats block. Scoped by
   .page[data-header-variant="vN"] so they coexist without leaking.
   ───────────────────────────────────────────────────────────────────── */

/* Inline switcher chip rail (sits above everything; design-time only) */
.header-variant-switcher {
  display: flex; align-items: center; gap: 12px;
  padding: 6px 10px; margin: 0 0 12px;
  background: var(--panel-deep); border: 1px dashed var(--edge);
  border-radius: var(--r-2);
}
.header-variant-switcher .hvs-label {
  font: 600 10px/1 var(--font-sans); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--faint);
}
.header-variant-switcher .hvs-chips { display: flex; gap: 4px; flex-wrap: wrap; }
.header-variant-switcher .hvs-chip {
  appearance: none; background: transparent;
  border: 1px solid var(--edge); border-radius: var(--r-pill);
  color: var(--muted); padding: 5px 10px;
  font: 600 10px/1 var(--font-sans); letter-spacing: 0.06em;
  text-transform: uppercase; cursor: pointer;
}
.header-variant-switcher .hvs-chip:hover { color: var(--text); border-color: var(--c-blue); }
.header-variant-switcher .hvs-chip.on {
  background: var(--c-blue); color: #0a1226;
  border-color: rgba(122,166,255,0.6);
}

/* ── Shared identity-line + stat-strip primitives used by v2–v5 ── */
.identity-line {
  display: inline-flex; align-items: baseline; gap: 8px;
  flex-wrap: wrap; min-width: 0;
}
.identity-line .char-name-inline {
  font-family: var(--font-display); font-weight: 700;
  font-size: 20px; letter-spacing: 0.04em; color: var(--text);
  line-height: 1.05;
}
.identity-line.compact .char-name-inline { font-size: 15px; }
.identity-line .char-ancestry-inline {
  font: 600 11px/1 var(--font-sans);
  text-transform: uppercase; letter-spacing: var(--ls-caps);
  color: var(--muted);
}
.identity-line .id-sep {
  color: var(--faint); font-size: 12px; line-height: 1;
  user-select: none;
}
.identity-line .archetype-line {
  display: inline-flex; align-items: baseline; gap: 6px;
}
.identity-line .archetype-plus {
  color: var(--faint); font-size: 11px;
}
/* Override the default block-level archetype styling to inline-fit */
.identity-line .char-archetype {
  font-size: 11px; text-transform: uppercase;
  letter-spacing: var(--ls-caps); font-weight: 700;
  color: var(--c-blue);
}
.identity-line .char-archetype.berserker { color: var(--c-red); }

.stat-strip {
  display: inline-flex; align-items: baseline; gap: 10px;
  font-variant-numeric: tabular-nums;
}
.stat-strip .ss-stat {
  display: inline-flex; align-items: baseline; gap: 4px;
  white-space: nowrap;
}
.stat-strip .ss-lbl {
  font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--faint);
}
.stat-strip .ss-val { font: 700 13px/1 var(--font-sans); color: var(--text); }
.stat-strip .ss-stat[data-stat="str"] .ss-val { color: var(--stat-str); }
.stat-strip .ss-stat[data-stat="res"] .ss-val { color: var(--stat-res); }
.stat-strip .ss-stat[data-stat="agi"] .ss-val { color: var(--stat-agi); }
.stat-strip .ss-stat[data-stat="mem"] .ss-val { color: var(--stat-mem); }
.stat-strip .ss-stat[data-stat="wil"] .ss-val { color: var(--stat-wil); }
.stat-strip .ss-pot .ss-val { color: var(--muted); font-weight: 600; }
.stat-strip .ss-pot .ss-max { color: var(--faint); }
.stat-strip .ss-sep {
  display: inline-block; width: 1px; height: 14px;
  background: var(--edge); align-self: center;
}

.hv-sep {
  display: inline-block; width: 1px; height: 18px;
  background: var(--edge); align-self: center;
}

/* ── Header (locked layout, former V7): brand on the tab-bar's right,
        identity + stats in a panel beneath the tabs. ─────────────── */
.tab-bar-brand {
  display: inline-flex; align-items: center;
  margin-left: auto;
  padding: 0 12px 6px;
  align-self: flex-end;
}
.tab-bar-brand .brand-wordmark {
  font-size: 18px;       /* matches .combat-logo size in the Combat tab */
  line-height: 1;
  letter-spacing: 0.12em;
  padding-top: 0;
}
.sub-identity.v7 {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 14px; margin-bottom: 14px;
  background: var(--panel); border: 1px solid var(--edge);
  border-radius: var(--r-3);
}
.sub-identity.v7 .stat-strip {
  margin-left: auto;
}
.tab-bar { margin-bottom: 10px; }

/* The view-toggle inside the filter bar uses the regular pill styling —
   drop the connecting "tab"-style negative margin so it sits as a
   self-contained control rather than fusing onto a row above it. */
.view-toggle.in-filter-bar {
  margin-bottom: 0;
  border-radius: var(--r-3);
  align-self: center;
}
.view-toggle.in-filter-bar button { padding: 6px 10px; font-size: 10px; }

/* View-mode toggle inside the Display preset filter group. Matches the
   segmented chip style used by the preset / cost / status / rune
   pickers — squared corners, hairline divider between buttons, teal
   fill for the active option. The icon is the only thing that
   differentiates it visually from the neighbouring chips. */
.chips.chips-view-toggle {
  width: fit-content;
}
.chip.chip-view-mode {
  gap: 6px;
}
.chip.chip-view-mode svg { width: 12px; height: 12px; flex-shrink: 0; }

/* ── Responsive: collapse stat strip values onto two rows on narrow ── */
@media (max-width: 720px) {
  .stat-strip { gap: 8px; }
  .stat-strip .ss-lbl { font-size: 9px; }
  .stat-strip .ss-val { font-size: 12px; }
  .sub-identity.v7 { gap: 8px; }
  .sub-identity.v7 .stat-strip {
    margin-left: 0; width: 100%;
    flex-wrap: wrap;
    padding-top: 6px; border-top: 1px solid var(--edge);
  }
  .identity-line .char-name-inline { font-size: 17px; }
}

/* ── Equal-width status condition grid in the filter drawer ──
   Lays the eight status condition chips out as a 2-column grid where
   every cell sizes to the widest label so the rail reads as a clean
   block rather than ragged-right rows of mismatched-width buttons. */
.fd-group .chips.chips-status-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  flex-wrap: initial; /* override flex defaults */
}
.fd-group .chips.chips-status-grid .chip-status {
  width: 100%;
  justify-content: flex-start;
}

/* Rune chip grid — 4 across to match the 24-symbol rune set neatly
   (visible 6 runes = 1.5 rows worth when collapsed, 6 rows of 4 when
   Edit reveals all 24). Forces equal-width columns so every line is
   the same shape, mirroring the status grid. */
.fd-group .chips.chips-rune-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  flex-wrap: initial;
}
.fd-group .chips.chips-rune-grid .chip-rune {
  width: 100%;
  justify-content: flex-start;
}

/* Damage type chip grid — 3 across so each row carries the same
   number of chips (11 damage types fit across 4 rows: 3+3+3+2).
   Same layout philosophy as the status grid (2-up) and rune grid
   (4-up): equal columns so the chip rail reads as a clean block
   instead of a ragged-right wrap. */
.fd-group .chips.chips-dmg-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  flex-wrap: initial;
}
.fd-group .chips.chips-dmg-grid .chip-dmg {
  width: 100%;
  justify-content: flex-start;
}

/* Action-types chip grid — 4 across, matching the rune grid so the
   middle column reads as a single coherent block of equal-shaped
   chips. Each chip stretches to fill its grid cell instead of
   shrink-wrapping to its label. */
.fd-group .chips.chips-opts-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  flex-wrap: initial;
}
.fd-group .chips.chips-opts-grid .chip-opt {
  width: 100%;
  min-width: 0;
  justify-content: flex-start;
}
/* Truncate long action-type labels so they never push the chip past
   its grid cell. The label is the flexible flex item; the count pill
   stays at its natural width. Native title attribute provides the
   tooltip with the full name on hover. */
.chip.chip-opt .chip-opt-label {
  display: inline-block;
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chip.chip-opt .ct { flex: 0 0 auto; }

/* Item-types chip grid — equipment-tab filter that mirrors the top
   slot chip rail. Three columns wide — the nine inventory slots
   arrange cleanly into a 3×3 grid (no orphan row). Each chip
   inherits the existing data-type accent palette (melee → red, helm
   → purple, etc.). Labels can be a single word, so a flex layout
   with truncation keeps long ones from breaking the cell. */
.fd-group .chips.chips-itemtypes-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  flex-wrap: initial;
}
.fd-group .chips.chips-itemtypes-grid .chip-itemtype {
  width: 100%;
  min-width: 0;
  justify-content: flex-start;
}
.chip.chip-itemtype .chip-itemtype-label {
  display: inline-block;
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chip.chip-itemtype .ct { flex: 0 0 auto; }

/* Potential-cost chip grid — bucketed integer pills (1..10 exact,
   then 10+, 15+, 20+, etc. for higher ranges). Each chip is its own
   integer-style button; the rail wraps onto multiple lines if the
   bucket count outgrows the column width. Sized snug so a row of
   single-digit chips reads as a number line rather than a button
   array. */
.fd-group .chips.chips-potcost-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.chip.chip-potcost {
  min-width: 38px;
  padding: 5px 9px;
  gap: 5px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  text-transform: none;
}
.chip.chip-potcost .chip-potcost-label {
  font: 700 12px/1 var(--font-mono);
}

/* ── Status grid: 2 columns by default, 3 when the column has room.
   Container query reads the fd-col's width so the grid swaps as the
   user resizes the drawer / viewport. Threshold (~360px) is the
   smallest width at which three full status chips fit on a single
   line without truncating their name. */
.fd-col-conditions { container-type: inline-size; container-name: condcol; }
@container condcol (min-width: 360px) {
  .fd-group .chips.chips-status-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ── Status column cell in the dense table ──
   Holds one or more status tokens inline; flex so each token sits next
   to its sibling without dropping to a new line until forced to. */
.va-row td.col-status,
.va-table thead th.col-status {
  padding-left: 8px;
  padding-right: 8px;
}
.status-cell {
  display: inline-flex; align-items: center; gap: 4px;
  flex-wrap: wrap;
}

/* ── StatusToken variants (Short / Full) ──
   Both "short" and "full" render the same chip-status pill shape —
   icon badge + name + count. Short truncates the name to three
   characters. The two share .status-token-pill so any styling tweak
   applies to both. */
.status-token.status-token-pill,
.chip.status-token-pill {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0 4px 0 0;
}
.status-token-pill .status-name {
  text-transform: capitalize;
}
.status-token-short .status-name {
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ── TypeBadge: damage-type addendum ──
   When the Display option "Damage type in ability type" is on, the
   damage-type icons render to the right of the badge label, inside the
   same pill so they read as one unit. The pill keeps its fixed 18px
   height — the emoji glyphs are scaled down to fit so adding them does
   not grow the row. */
.type-badge {
  display: inline-flex; align-items: center; gap: 6px;
}
.type-badge .type-badge-dmg {
  display: inline-flex; align-items: center; gap: 2px;
  padding-left: 6px;
  margin-left: 2px;
  border-left: 1px solid color-mix(in oklch, currentColor 35%, transparent);
  font-size: 11px;
  line-height: 1;
}

/* When a slot icon is rendered on the left side of the type pill (used
   by the equipment tab to surface a slot's signature glyph next to its
   text label), give it the same vertical centering as the label and
   keep its color independent from the pill's borrow color so the icon
   keeps its own slot tint instead of inheriting the pill's accent. */
.type-badge .type-badge-slot {
  width: 14px; height: 14px;
  margin: 0 4px 0 -2px;
  flex-shrink: 0;
}
.type-badge .type-badge-dmg .dmg-type {
  line-height: 1;
  font-size: 12px;     /* fit comfortably inside the 22px-tall pill */
  display: inline-flex; align-items: center;
}

/* ── Rune-as-keyword chip ──
   A compact rune-symbol pill that appears inside the keyword strip for
   any ability that costs or charges a rune. Always rendered in minimal
   (symbol-only) form regardless of the rune-cost-display setting — the
   purpose is glanceable presence, not full naming. */
.rune-kw-strip {
  display: inline-flex; align-items: center; gap: 4px;
  margin-right: 6px;
}
.rune-kw {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px;
  padding: 0 5px;
  border-radius: var(--r-pill, 999px);
  border: 1px solid color-mix(in oklch, var(--c-yellow) 50%, transparent);
  background: color-mix(in oklch, var(--c-yellow) 10%, transparent);
}
.rune-kw .rune-sym {
  font-family: var(--font-runic);
  font-size: 13px;
  line-height: 1;
  color: var(--c-yellow);
}

/* ── fd-num: a labelled numeric input inside Display options ──
   Same visual lineage as fd-check, just hosts a <input type="number">
   on the right side instead of a checkbox on the left. */
.fd-check.fd-num {
  gap: 10px;
}
.fd-check.fd-num input[type="number"] {
  width: 52px;
  padding: 4px 6px;
  background: var(--panel-deep, var(--panel));
  border: 1px solid var(--edge);
  border-radius: var(--r-1);
  color: var(--text);
  font: 700 12px/1 var(--font-mono);
  text-align: right;
}
.fd-check.fd-num input[type="number"]:focus {
  outline: none;
  border-color: var(--c-blue);
}

/* ── Save / Load / Refresh chrome (Phase 2 increment 2) ──
   Mounted on the right edge of the sub-identity bar after the
   stat strip. Matches v1's hero-head save-controls layout, ported
   to the v2 design tokens. The buttons are intentionally compact
   so they don't crowd the identity strip on narrow viewports;
   the stat strip and save-controls both wrap below the identity
   line on mobile (sub-identity is flex-wrap). */
.sub-identity.v7 .save-controls {
  display: inline-flex; gap: 6px; align-items: center;
  margin-left: 8px;
}
.save-btn {
  font: 600 11px/1 var(--font-ui, system-ui, sans-serif);
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 6px 10px; border-radius: var(--r-2, 6px);
  background: transparent; color: var(--text, #e2e8f0);
  border: 1px solid var(--edge, rgba(167,139,250,0.5));
  cursor: pointer; transition: background 120ms, border-color 120ms;
}
.save-btn:hover:not(:disabled) { background: rgba(167,139,250,0.10); }
.save-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.save-btn.load-btn,
.save-btn.refresh-btn {
  color: #a78bfa; border-color: rgba(167,139,250,0.5);
}
.save-btn.refresh-btn {
  font-size: 14px; padding: 4px 8px;
  /* The ↻ glyph is a hair smaller than full-cap text — bump up to
     match the visual weight of the neighbour buttons. */
}

/* ── CharSelectOverlay modal ──
   Full-screen modal that lists every saved_builds row. Background
   is a dim scrim; the inner panel uses the page panel token so
   the look matches the rest of v2. Click background to dismiss.
   v1's overlay has richer per-row enrichment (ancestry/archetype
   inline); we ship the minimal "name + date + current badge"
   version and defer richer metadata to the persistence-bridge
   increment. */
.char-select-overlay {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(8, 11, 24, 0.78);
  backdrop-filter: blur(2px);
  padding: 24px;
}
.char-select-inner {
  width: min(560px, 100%);
  background: var(--panel, #0f172a);
  border: 1px solid var(--edge, rgba(167,139,250,0.5));
  border-radius: var(--r-3, 10px);
  padding: 22px; box-shadow: 0 8px 40px rgba(0,0,0,0.45);
  display: flex; flex-direction: column; gap: 14px;
  max-height: calc(100vh - 48px);
}
.cs-branding { text-align: center; }
.cs-logo {
  font: 800 22px/1 var(--font-display, "Cinzel", serif);
  letter-spacing: 0.08em; color: var(--text, #e2e8f0);
}
.cs-sub {
  margin-top: 4px; font-size: 11px; color: var(--faint, #94a3b8);
  letter-spacing: 0.04em; text-transform: uppercase;
}
.cs-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11px; color: var(--faint, #94a3b8);
}
.cs-count { letter-spacing: 0.04em; text-transform: uppercase; }
.cs-close-btn {
  background: transparent; color: var(--faint, #94a3b8);
  border: 1px solid var(--edge, rgba(148,163,184,0.3));
  border-radius: var(--r-2, 6px); padding: 5px 10px;
  font-size: 11px; cursor: pointer;
  letter-spacing: 0.04em; text-transform: uppercase;
}
.cs-close-btn:hover { color: var(--text, #e2e8f0); border-color: var(--text, #e2e8f0); }
.char-list {
  overflow-y: auto; display: flex; flex-direction: column; gap: 6px;
  margin-top: 4px;
}
.char-empty-state {
  padding: 18px; text-align: center; color: var(--faint, #94a3b8);
  font-size: 12px;
}
.char-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 12px; border-radius: var(--r-2, 6px);
  border: 1px solid var(--edge, rgba(148,163,184,0.2));
  background: rgba(255,255,255,0.02); cursor: pointer;
  transition: background 120ms, border-color 120ms;
}
.char-row:hover { background: rgba(167,139,250,0.10); border-color: rgba(167,139,250,0.5); }
.char-row-current { border-color: rgba(167,139,250,0.7); background: rgba(167,139,250,0.08); }
.char-row-info { display: flex; flex-direction: column; gap: 2px; }
.char-row-name {
  font: 600 14px/1.2 var(--font-display, "Cinzel", serif);
  color: var(--text, #e2e8f0);
}
.char-row-meta { font-size: 10px; color: var(--faint, #94a3b8); letter-spacing: 0.04em; }
.char-row-current-badge {
  font-size: 9px; padding: 3px 6px; border-radius: 3px;
  background: rgba(167,139,250,0.18); color: #a78bfa;
  letter-spacing: 0.06em; text-transform: uppercase;
}

/* SaveModal reuses .char-select-overlay scrim + .char-select-inner
   panel so the look matches the Load overlay. The .save-modal-* bits
   below are just the input + button-row specifics. */
.save-modal-inner { width: min(440px, 100%); }
.save-modal-input {
  width: 100%; padding: 10px 12px;
  font: 500 14px/1 var(--font-ui, system-ui, sans-serif);
  background: rgba(255,255,255,0.04);
  color: var(--text, #e2e8f0);
  border: 1px solid var(--edge, rgba(167,139,250,0.5));
  border-radius: var(--r-2, 6px);
  outline: none; transition: border-color 120ms, background 120ms;
}
.save-modal-input:focus {
  border-color: #a78bfa; background: rgba(255,255,255,0.07);
}
.save-modal-actions {
  display: flex; gap: 8px; justify-content: flex-end;
}
.save-modal-confirm { color: #a78bfa; border-color: rgba(167,139,250,0.5); }
.save-modal-confirm:hover:not(:disabled) { background: rgba(167,139,250,0.10); }
