/* ui/loadout/loadout.css — Mission Control overlay + roguelite picker. (M7)
   Extends src/styles.css CSS custom properties. No external assets, no font files.
   z-index 30 (ui-design-system §3: above HUD + touch layer).
   Mobile-first: all tap targets ≥44px; responsive grid. */

/* ── Extra palette vars (ui-design-system §1 additions) ────────────────────── */
:root {
  --green-dim:         rgba(51,255,102,.25);
  --amber-dim:         rgba(255,176,0,.30);
  --cream:             #f0e6c8;
  --panel-bg:          rgba(10,14,42,.92);
  --rarity-common:     #9aa0b5;
  --rarity-rare:       #4db5ff;
  --rarity-legendary:  #c08cff;
  --rarity-exotic:     #ffd34d;
  /* Cyan accent for the SORT control — visually separate from green filters and
     amber active states. */
  --sort-accent:       #4fd6ff;
  --sort-accent-dim:   rgba(79, 214, 255, .45);
}

/* ── Loadout overlay root ────────────────────────────────────────────────── */
/* The global .touch-btn (styles.css) is position:absolute for in-game HUD buttons.
   Inside the overlay those buttons must flow normally — neutralize it here. */
.loadout-overlay .touch-btn,
.roguelite-overlay .touch-btn { position: static; transform: none; }

.loadout-overlay {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: none;          /* toggled by JS */
  flex-direction: column;
  /* R2.1.2 — Fully opaque so the 3D scene behind doesn't bleed through.
   * --panel-bg stays translucent for inset cards/modals inside the overlay. */
  background: var(--void);
  color: var(--green);
  font-family: 'Courier New', Courier, monospace;
  font-size: 12px;
  letter-spacing: 1px;
  line-height: 1.45;
  text-transform: uppercase;
  overflow: hidden;
  pointer-events: none;   /* none by default; JS sets auto when open */
  padding: env(safe-area-inset-top, 0) env(safe-area-inset-right, 0)
           env(safe-area-inset-bottom, 0) env(safe-area-inset-left, 0);
}

/* Hairline frame (design-system §3) */
.lo-frame {
  position: absolute;
  inset: 8px;
  border: 1px solid var(--green-dim);
  pointer-events: none;
  z-index: 0;
}

/* ── Header ─────────────────────────────────────────────────────────────── */
.lo-header {
  display: flex;
  align-items: center;
  gap: 12px;
  /* Compact header (playtest R2 D2-flow feedback: "way too much space to main
     menu / settings / commence") — the header is chrome, the tabs are the work
     surface; keep it one slim row. */
  padding: 5px 16px;
  border-bottom: 1px solid var(--green-dim);
  position: relative;
  z-index: 1;
  flex-shrink: 0;
}
.lo-title-group {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex: 1;
  /* B4 (ui-scale-responsive) — a bare min-width:0 let this collapse to ~1px
     whenever the header hasn't wrapped yet but the 3 header-action buttons
     (MAIN MENU / SETTINGS / COMMENCE) leave it no room; the title then
     visually overlapped the buttons instead of just eliding. A small floor
     keeps "MISSION..." legible right up to the wrap breakpoint below. */
  min-width: 90px;
}
.lo-title {
  color: var(--amber);
  font-size: 15px;
  letter-spacing: 3px;
  white-space: nowrap;
}
.lo-subtitle {
  color: var(--green);
  opacity: .5;
  font-size: 11px;
  letter-spacing: 3px;
}
/* ── R2.1.2 — Persistent loadout strip (between header and tab bar) ───────── */
.lo-strip {
  display: flex;
  gap: 6px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--green-dim);
  flex-wrap: nowrap;
  z-index: 1;
  position: relative;
  background: rgba(10, 14, 42, 0.6);
}
/* Icon-only cells (playtest): names/labels moved to tooltips so the whole
 * loadout reads as one tidy row of glyphs. Cells flex to share the row width
 * and stay roughly square; the icon is centered. */
.lo-strip-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  min-height: 36px;
  font-family: inherit;
  color: var(--green);
  background: rgba(51, 255, 102, 0.04);
  border: 1px solid var(--green-dim);
  cursor: pointer;
  transition: border-color .12s, background .12s, color .12s;
  flex: 1 1 0;
  min-width: 36px;
  max-width: 64px;
}
.lo-strip-cell:hover,
.lo-strip-cell:focus-visible {
  border-color: var(--amber);
  background: rgba(255, 176, 0, 0.08);
  outline: none;
}
.lo-strip-empty { opacity: 0.55; }
.lo-strip-icon { width: 22px; height: 22px; flex-shrink: 0; }
.lo-strip-glyph {
  font-size: 20px;
  line-height: 1;
  color: var(--amber);
  flex-shrink: 0;
}
.lo-strip-name {
  font-size: 11px;
  color: var(--green);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.lo-strip-name-empty { color: var(--green-dim); }
/* Ability cells get a tighter look; class chip stays on the far right */
.lo-strip-ability { background: rgba(51, 255, 102, 0.06); }
.lo-strip-class {
  background: rgba(255, 176, 0, 0.06);
  border-color: var(--amber-dim);
}
.lo-strip-class .lo-strip-name { color: var(--amber); }

/* Rollup chip in the organizer filter row — distinct style so it reads as a
 * higher-tier filter than the individual slot chips. */
.organizer-chip[data-chip-id^="group:"] {
  background: rgba(255, 176, 0, 0.06);
  border-color: var(--amber-dim);
  color: var(--amber);
  letter-spacing: 2px;
}
.organizer-chip[data-chip-id^="group:"].active {
  background: rgba(255, 176, 0, 0.18);
  border-color: var(--amber);
  color: var(--amber);
}

/* ── Tab bar ─────────────────────────────────────────────────────────────── */
.lo-tabbar {
  display: flex;
  gap: 4px;
  padding: 0 20px;
  border-bottom: 1px solid var(--green-dim);
  flex-shrink: 0;
  /* z-index needs `position` to take effect. On wide screens the VAULT's SORT
     popover drops out of the tab bar into the panel area, so the tab bar must
     stack above .lo-panel-host (also z-index:1) or the menu renders behind the
     sticky table header. */
  position: relative;
  z-index: 5;
}
/* When the SORT (or wide-compact FILTER) menu is open on a wide screen, hoist
   the controls bar a touch further so the dropdown overlays the sticky `<th>`
   row cleanly — and lift the belt-and-braces overflow-x clip (a non-visible
   overflow-x forces vertical clipping too, which would swallow the dropdown;
   in the compact tier everything fits, so no scroll state is lost). */
.lo-tabbar:has(.vault-sort-open),
.lo-tabbar:has(.vault-filter-open) { z-index: 6; overflow: visible; }
.lo-tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--green);
  font-family: inherit;
  font-size: 13px;
  letter-spacing: 2px;
  padding: 10px 20px;
  cursor: pointer;
  min-height: 44px;
  transition: color .12s, border-color .12s;
}
.lo-tab.active,
.lo-tab:hover {
  color: var(--amber);
  border-bottom-color: var(--amber);
}

/* ── Panel host ─────────────────────────────────────────────────────────── */
.lo-panel-host {
  flex: 1;
  overflow: hidden;
  position: relative;
  z-index: 1;
}
.lo-panel {
  display: flex;
  height: 100%;
  overflow: hidden;
}

/* ── Focus / equipped cells (design-system §5) ──────────────────────────── */
.cell {
  border: 1px solid var(--green-dim);
  cursor: pointer;
  transition: border-color .12s, box-shadow .12s;
  position: relative;
  min-height: 44px;
  box-sizing: border-box;
}
.cell.ui-focused,
/* R2.1.3 — Controller-nav focus ring on cells that don't carry the .cell base
   class: strip cells, organizer chips & rows, loadout-card apply buttons,
   commence, hero commence/tinker, and the mid-run QUIT button. Without these
   the dpad moved focus invisibly. */
.lo-strip-cell.ui-focused,
.organizer-chip.ui-focused,
.organizer-row.ui-focused,
.lo-card-apply.ui-focused,
.lo-commence-btn.ui-focused,
.lo-hero-commence.ui-focused,
.lo-hero-tinker.ui-focused,
/* VAULT drill-down filter pills + the SORT button: these are in the controller-nav
   grid but carried no focus ring, so the d-pad reached them invisibly — the player
   couldn't tell the filters/sort were selectable (playtest: "a way to dpad navigate
   to the filters and sort"). The CARD/LIST view-toggle chip is in the same nav grid
   and was likewise ring-less — worse, it always carries .active, so d-pad focus was
   invisible (it read as stuck on the current view). */
.vault-pill.ui-focused,
.vault-sort-btn.ui-focused,
.vault-sort-dir.ui-focused,
.vault-sort-opt.ui-focused,
/* The collapsed FILTER button + its popover options (compact/wide tier) sit in
   the same controller-nav grid as SORT but were left out of this ring block, so
   d-pad focus reached them invisibly on the WEAPONS/ARMOR screen — the SORT twin
   above lit up, FILTER didn't (playtest: "when we have the filter selected with
   dpad it lights up"). */
.vault-filter-btn.ui-focused,
.vault-filter-opt.ui-focused,
.vault-view-btn.ui-focused,
/* The EQUIPPED avatar cell is a nav cell now (Cross → the full-screen
   inspector), so it needs the same ring every other focusable cell carries. */
.lo-eq-avatar-viewport.ui-focused,
.lo-main-menu-btn.ui-focused {
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
  box-shadow: 0 0 10px var(--amber-dim) inset;
  /* R-menu-dpad-ux — a static outline reads as "the cursor is somewhere on
     this cluttered panel," not "here." A slow pulse pulls the eye straight
     to the focused cell (ui-design-system.md §5's "obvious across a room"
     bar wasn't met by the outline alone). */
  animation: ui-focus-pulse 1.4s ease-in-out infinite;
}
@keyframes ui-focus-pulse {
  0%, 100% { box-shadow: 0 0 10px var(--amber-dim) inset; }
  50%      { box-shadow: 0 0 18px var(--amber-dim) inset, 0 0 12px rgba(255, 176, 0, .7); }
}
/* Edge-of-grid feedback (nav.js _bump) — a direction press that moves nothing
   (grid edge, single-cell row/col) flashes red-then-settle instead of doing
   nothing, so "that way is a dead end here" reads instantly instead of the
   player wondering whether the button press registered at all. Selector
   ties the specificity of the block above and wins on source order. */
.ui-focused.ui-nav-bump {
  animation: ui-nav-bump-anim .18s ease-out;
}
@keyframes ui-nav-bump-anim {
  0%   { box-shadow: 0 0 0 3px var(--red) inset; }
  100% { box-shadow: 0 0 10px var(--amber-dim) inset; }
}
@media (prefers-reduced-motion: reduce) {
  .ui-focused { animation: none; }
}
/* Hero card COMMENCE — the focused button reads more like a selected card,
   not just an outline (the eye expects whole-card highlight). */
.lo-hero-commence.ui-focused {
  background: var(--amber);
  color: var(--void);
  transform: scale(1.02);
}
/* Table rows are normally text-only; give the focused one a tinted background
   so the amber outline reads cleanly against the dark table backdrop.
   (equip-screen-cursor pass: tint +50% with the ring bolding below.) */
.organizer-row.ui-focused {
  background: rgba(255, 196, 0, .09);
}
.cell.ui-equipped {
  border-color: var(--green) !important;
}
.cell.ui-focused.ui-equipped {
  outline-color: var(--amber);
  border-color: var(--green) !important;
}

/* Element pip */
.elem-pip {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin: 0 3px;
  vertical-align: middle;
  flex-shrink: 0;
}
/* Element sigil variant (shared element-icon.js) — a shape, not a dot. */
.elem-pip-ic { width: 15px; height: 15px; margin: 0 2px; vertical-align: middle; flex-shrink: 0; }

/* NAMED element tag — sigil + the word, tinted (playtest 2026-07-22: the bare
 * pip put the damage type in a tooltip, which reads as nothing on touch). Used
 * wherever elements have to be cross-checked for synergy: weapon rows + ability
 * rows in the LOADOUTS build guide. */
.elem-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  padding: 1px 6px;
  border: 1px solid var(--elem-tc, var(--green-dim));
  background: color-mix(in srgb, var(--elem-tc, #8f9ac4) 12%, transparent);
  color: var(--elem-tc, var(--green));
  line-height: 1.4;
}
.elem-tag .elem-tag-ic { width: 13px; height: 13px; flex-shrink: 0; }
.elem-tag .elem-pip { width: 7px; height: 7px; margin: 0; }
.elem-tag-lbl {
  font-size: 10px;
  font-weight: bold;
  letter-spacing: 1px;
}
/* Right-align the tag on ability rows so weapons (whose flexible name column
 * already pushes it there) and abilities share ONE element column — the whole
 * kit's damage types read as a single vertical scan. */
.lo-card-ab-line .elem-tag { margin-left: auto; }

/* ── GEAR PANEL ─────────────────────────────────────────────────────────── */
.gear-panel {
  gap: 0;
}
.gear-slot-list {
  display: flex;
  flex-direction: column;
  width: 230px;
  min-width: 170px;
  border-right: 1px solid var(--green-dim);
  overflow-y: auto;
  flex-shrink: 0;
  padding: 12px;
  gap: 8px;
}
.gear-slot-cell {
  padding: 12px 14px;
  border-radius: 2px;
}
.gear-slot-label {
  font-size: 10px;
  color: var(--amber);
  letter-spacing: 3px;
  margin-bottom: 2px;
}
.gear-slot-item {
  font-size: 12px;
  color: var(--green);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gear-slot-meta {
  font-size: 10px;
  color: var(--green);
  opacity: .6;
  display: flex;
  align-items: center;
  gap: 2px;
  margin-top: 2px;
}
.item-rarity-tag {
  font-size: 9px;
  letter-spacing: 1px;
}

/* Diagnostic bars */
.gear-diag {
  width: 220px;
  min-width: 180px;
  border-right: 1px solid var(--green-dim);
  padding: 12px;
  overflow-y: auto;
  flex-shrink: 0;
}
.gear-diag-title {
  color: var(--amber);
  font-size: 10px;
  letter-spacing: 3px;
  margin-bottom: 10px;
}
.diag-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}
.diag-label {
  font-size: 9px;
  letter-spacing: 1.5px;
  color: var(--green);
  width: 70px;
  flex-shrink: 0;
  white-space: nowrap;
}
.diag-track {
  flex: 1;
  height: 10px;
  border: 1px solid var(--green-dim);
  background: rgba(51,255,102,.04);
  overflow: hidden;
}
.diag-fill {
  height: 100%;
  width: 0%;
  background: var(--green);
  transition: width .18s ease;
}
.diag-val {
  font-size: 9px;
  color: var(--amber);
  width: 38px;
  text-align: right;
  flex-shrink: 0;
}

/* Gear item grid */
.gear-item-grid {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 8px;
}
.gear-item-cell {
  width: calc(50% - 4px);
  padding: 10px 12px;
  border-radius: 2px;
}
.gear-no-items {
  color: var(--green-dim);
  font-size: 11px;
  padding: 20px;
  letter-spacing: 2px;
}
.cell-name {
  font-size: 11px;
  color: var(--green);
  margin-bottom: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cell-slot {
  font-size: 9px;
  color: var(--amber);
  letter-spacing: 1px;
  display: flex;
  align-items: center;
  gap: 3px;
}
.cell-top {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 2px;
}
.cell-rarity {
  font-size: 9px;
  font-weight: bold;
  letter-spacing: 1px;
}
.cell-new-tag {
  font-size: 8px;
  background: var(--amber);
  color: var(--void);
  padding: 1px 3px;
  letter-spacing: 1px;
}
.cell-fav {
  position: absolute;
  top: 4px;
  right: 6px;
  color: var(--amber);
  font-size: 12px;
}

/* ── ABILITIES PANEL ────────────────────────────────────────────────────── */
.abilities-panel {
  flex-direction: column;
  overflow-y: auto;
  padding: 12px 16px;
  gap: 10px;
}
.abilities-class-area {
  flex-shrink: 0;
}
.abilities-class-title {
  color: var(--amber);
  font-size: 10px;
  letter-spacing: 3px;
  margin-bottom: 6px;
}
.class-picker {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.class-card {
  padding: 8px 14px;
  border-radius: 2px;
  min-width: 160px;
  flex: 1;
}
.class-name {
  font-size: 13px;
  color: var(--amber);
  letter-spacing: 2px;
  margin-bottom: 3px;
}
.class-detail {
  font-size: 9px;
  color: var(--green);
  letter-spacing: 1px;
  line-height: 1.3;
  opacity: .8;
  margin-bottom: 2px;
}

/* E2(b) (menus-refit-spec.md) — this class's ability-variant preview row
   (classAbilityIds: primer + detonator), stacked so it fits inside the
   narrow class-card at any width (`.class-card` is `min-width:160px`). */
.class-ability-variants {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}
.class-ability-variant-card { cursor: pointer; }
/* Compact sizing scoped to this narrow context — the shared collapsed-card
   defaults (card.css) are tuned for the wider EQUIPPED/ABILITIES-slot cards. */
.class-ability-variant-card .fc-title,
.class-ability-variant-card .fc-collapsed-band { padding-left: 10px; padding-right: 10px; }
.class-ability-variant-card .fc-title { padding-top: 8px; padding-bottom: 2px; }
.class-ability-variant-card .fc-name { font-size: 11.5px; letter-spacing: .8px; }
.class-ability-variant-card .fc-icon { width: clamp(38px, 10vw, 54px); }
.class-ability-variant-card .fc-glyph > svg { width: 18px; height: 18px; }
.class-ability-variant-card .fc-glyph-role,
.class-ability-variant-card .fc-glyph-val { font-size: 7px; }
.class-ability-variant-card .fc-state-chip { font-size: 8px; }
/* Preview-only (a class that isn't currently equipped): dimmed + no pointer
   affordance — still focusable/hoverable for the perk-tip (B2), nothing to tap. */
.class-ability-variant-card.preview-only { opacity: .4; cursor: default; }
.class-ability-variant-card.ui-equipped { outline: 1px solid var(--green); outline-offset: -1px; }
.class-ability-variant-card.ui-focused {
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
  box-shadow: 0 0 10px var(--amber-dim) inset;
}

.ab-slots-area {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
  flex-wrap: wrap;
}
/* R2.1.1 — Slots take an exact 1/3 of the row so opening a drawer between
 * them (which wraps to its own line) doesn't cause the remaining slot to
 * stretch to the whole row. */
.ab-slot {
  flex: 0 1 calc(33.333% - 6px);
  min-width: 180px;
  padding: 10px 12px;
  border-radius: 2px;
}
.ab-slot-label {
  font-size: 9px;
  color: var(--amber);
  letter-spacing: 2px;
  margin-bottom: 4px;
}
/* E2 (menus-refit-spec.md) — `.ab-slot-info` now just hosts a shared
   collapsed card (card.css `.fc-collapsed`), which sets its own typography;
   this only needs to give it room to breathe. */
.ab-slot-info { display: flex; flex-direction: column; }
/* Prime/Detonate role badge — color-coded by loop role */
.ab-role-badge {
  display: inline-block;
  font-size: 8px;
  font-weight: bold;
  letter-spacing: 1px;
  padding: 1px 5px;
  border-radius: 2px;
  margin-right: 6px;
  vertical-align: middle;
  border: 1px solid currentColor;
}
.ab-role-badge.role-prime {
  color: var(--rarity-rare);          /* cyan — set up the loop */
}
.ab-role-badge.role-detonate {
  color: var(--amber);                /* amber — pop the loop */
}
.ab-role-badge.role-hybrid {
  color: var(--rarity-legendary);     /* purple — does both */
}
/* E2 (menus-refit-spec.md) — `.ab-slot-name`/`.ab-icon`/`.ab-archetype`/
   `.ab-slot-stats` were the bespoke equipped-slot name/icon/archetype/stats
   line this pass replaced with a shared collapsed card; nothing emits them
   anymore, so they're deleted rather than left as silent dead weight. */
.ab-slot-aspects {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.ab-aspect-chip {
  font-size: 8px;
  border: 1px solid var(--green-dim);
  padding: 2px 5px;
  letter-spacing: 1px;
  color: var(--green);
  opacity: .6;
}

/* Ability picker — full unified cards (ui/shared/card.js — "full cards
   everywhere"), one per row grouped by archetype (throw vs melee is the
   primary read). Grown from the original 2-up compact-card grid so the taller
   full card has room; the drawer itself scrolls internally. */
.ab-picker {
  display: none;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--green-dim);
  border-radius: 2px;
  padding: 10px;
  position: relative;
  max-height: 60vh;
  flex-shrink: 0;
}
.ab-picker-title {
  color: var(--amber);
  font-size: 12px;
  letter-spacing: 3px;
  margin-bottom: 8px;
  flex-shrink: 0;
}
.ab-picker-grid {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
  flex: 1;
}
/* Full-width archetype section header above each card stack. */
.ab-picker-group {
  color: var(--amber);
  font-size: 12px;
  letter-spacing: 3px;
  padding-bottom: 3px;
  margin-top: 6px;
  border-bottom: 1px solid var(--green-dim);
}
.ab-picker-group:first-child { margin-top: 0; }
.ab-picker-card {
  padding: 12px 14px;
  border-radius: 2px;
  width: 100%;
  min-width: 0;
}
.ab-picker-name {
  display: flex;
  align-items: center;
  font-size: 14px;
  color: var(--green);
  margin-bottom: 4px;
}
.ab-picker-name .ab-icon { width: 38px; height: 38px; }
.ab-picker-name .ab-role-badge { font-size: 10px; }
.ab-picker-name-text {
  vertical-align: middle;
}
.ab-picker-arch {
  font-size: 11px;
  color: var(--amber);
  opacity: .7;
  letter-spacing: 1px;
}
.ab-picker-stats {
  font-size: 11px;
  color: var(--green);
  opacity: .65;
  letter-spacing: .5px;
  margin-top: 6px;
  line-height: 1.4;
}
.ab-picker-desc {
  font-size: 12px;
  color: var(--cream);
  opacity: .8;
  line-height: 1.45;
  margin-top: 6px;
}
.ab-locked {
  opacity: .4;
  cursor: default;
}
.ab-locked-reason {
  font-size: 8px;
  color: var(--amber);
  margin-top: 4px;
  letter-spacing: 1px;
}
.ab-picker-close {
  position: absolute;
  top: 6px;
  right: 6px;
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 12px;
  padding: 4px 8px;
  cursor: pointer;
  min-width: 32px;
  min-height: 32px;
}

/* ── ABILITY DESCRIPTION PANEL (R2 item 1) ────────────────────────────────
   Persistent description at the bottom of the Abilities panel — follows focus,
   hover wins while active. Mirrors .gear-diag-title / .ab-picker-desc styling. */
.ab-desc-panel {
  margin-top: 8px;
  padding: 8px 10px;
  border: 1px solid var(--green-dim);
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.18);
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}
.ab-desc-title {
  color: var(--amber);
  font-size: 9px;
  letter-spacing: 2px;
  opacity: .8;
}
.ab-desc-name {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--green);
  font-size: 12px;
  letter-spacing: 1px;
}
.ab-desc-name strong {
  letter-spacing: 1.5px;
}
.ab-desc-body {
  font-size: 10px;
  color: var(--cream);
  opacity: .85;
  line-height: 1.45;
}
.ab-desc-equipped {
  font-size: 9px;
  color: var(--amber);
  letter-spacing: 1.5px;
  opacity: .85;
}

/* ── ABILITIES PANEL — R2.1 inline expansion + new sections (Agent B) ─────
   Focused slot expands inline (description + live CD/AP). New sections after
   the slots: SYNERGIES (auto bullets), BUILD NOTES (textarea), HOW TO PLAY
   (preformatted loop text). All selectors prefixed .ab-* per file ownership. */

/* R2.1.1 — All three ability slots render at uniform height. The drawer
 * (.ab-drawer / .ab-picker grid) pushes them apart when a slot is clicked. */
.ab-slot.ab-slot-open {
  background: rgba(255, 176, 0, 0.06);
  outline: 1px solid var(--amber);
  outline-offset: -1px;
}
/* Dim every slot OTHER than the one whose drawer is open, plus the class
 * chassis cards. Makes the active slot the visual anchor. */
.ab-slot.ab-slot-dimmed,
.class-card.ab-class-dimmed {
  opacity: 0.3;
  filter: saturate(0.4);
  transition: opacity .15s ease, filter .15s ease;
}

/* Drawer that opens immediately under the clicked ability slot. Lives in the
 * normal flow so it pushes the next slots down — no absolute positioning. */
.ab-drawer {
  flex-basis: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  margin: 4px 0 6px;
  border: 1px solid var(--amber);
  background: rgba(10, 14, 42, 0.92);
  position: relative;
}

/* SYNERGIES (auto) */
.ab-synergies {
  margin-top: 6px;
  padding: 6px 10px;
  border: 1px solid var(--green-dim);
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.18);
  flex-shrink: 0;
}
.ab-synergies-head {
  color: var(--amber);
  font-size: 9px;
  letter-spacing: 2px;
  opacity: .8;
  margin-bottom: 4px;
}
.ab-synergies-list {
  margin: 0;
  padding-left: 16px;
  list-style: square;
}
.ab-synergies-list li {
  font-size: 10px;
  color: var(--cream);
  opacity: .85;
  line-height: 1.45;
  letter-spacing: .5px;
  text-transform: none;
  margin: 2px 0;
}
.ab-synergies-list li.ab-synergy-empty {
  color: var(--green);
  opacity: .55;
  font-style: italic;
}

/* BUILD NOTES (yours) */
.ab-notes {
  margin-top: 4px;
  padding: 6px 10px;
  border: 1px solid var(--green-dim);
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.18);
  flex-shrink: 0;
}
.ab-notes-head {
  color: var(--amber);
  font-size: 9px;
  letter-spacing: 2px;
  opacity: .8;
  margin-bottom: 4px;
}
.ab-notes-hint {
  font-size: 9px;
  color: var(--green);
  opacity: .55;
  letter-spacing: 1px;
  text-transform: none;
  font-style: italic;
}
.ab-notes-input {
  width: 100%;
  min-height: 56px;
  background: rgba(10, 14, 42, 0.9);
  border: 1px solid var(--green-dim);
  color: var(--cream);
  font-family: inherit;
  font-size: 11px;
  letter-spacing: .5px;
  padding: 6px 8px;
  resize: vertical;
  box-sizing: border-box;
  text-transform: none;
  line-height: 1.4;
}
.ab-notes-input:focus { outline: 1px solid var(--amber); }
.ab-notes-input:disabled { opacity: .4; cursor: not-allowed; }

/* HOW TO PLAY */
.ab-howto {
  margin-top: 4px;
  padding: 6px 10px;
  border: 1px solid var(--green-dim);
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.18);
  flex-shrink: 0;
}
.ab-howto-head {
  color: var(--amber);
  font-size: 9px;
  letter-spacing: 2px;
  opacity: .8;
  margin-bottom: 4px;
}
.ab-howto-body {
  margin: 0;
  white-space: pre-wrap;
  font-family: inherit;
  font-size: 11px;
  line-height: 1.5;
  color: var(--cream);
  background: rgba(51, 255, 102, 0.04);
  border-left: 2px solid var(--green-dim);
  padding: 6px 10px;
  text-transform: none;
  letter-spacing: .5px;
}

/* ── Saved-loadout bar — locked-template affordances (R2.1 §Agent B item 7) ─ */
.lo-slot-locked {
  border-color: var(--amber) !important;
  background: rgba(255, 176, 0, 0.06);
}
.lo-slot-locked .lo-slot-num {
  color: var(--amber);
  font-size: 16px;
}
.lo-slot-locked .lo-slot-name {
  color: var(--amber);
  opacity: .85;
}
.lo-slot-template-chip {
  font-size: 7px;
  letter-spacing: 1px;
  color: var(--void);
  background: var(--amber);
  padding: 1px 4px;
  margin-top: 2px;
  border-radius: 1px;
  font-weight: bold;
}
.lo-slot-active {
  box-shadow: 0 0 8px var(--amber-dim) inset;
}

/* ── Info modal locked-state additions (R2.1) ─────────────────────────────── */
.lo-info-modal.lo-info-locked {
  border-color: var(--amber);
  box-shadow: 0 0 18px rgba(255, 176, 0, 0.22);
}
.lo-info-lock-glyph {
  font-size: 14px;
  margin-left: 6px;
}
.lo-info-locked-notice {
  font-size: 11px;
  letter-spacing: 1.5px;
  color: var(--amber);
  background: rgba(255, 176, 0, 0.08);
  border: 1px solid var(--amber);
  padding: 8px 12px;
  text-transform: uppercase;
}

/* ── VAULT PANEL ─────────────────────────────────────────────────────────── */
.vault-panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}
.vault-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--green-dim);
  flex-shrink: 0;
  align-items: flex-start;
}
.vault-filter-group {
  display: flex;
  gap: 3px;
  align-items: center;
  flex-wrap: wrap;
}
.vault-filter-label {
  font-size: 9px;
  color: var(--amber);
  letter-spacing: 2px;
  margin-right: 2px;
  opacity: .7;
}
.vault-filter-btn {
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 9px;
  letter-spacing: 1px;
  padding: 4px 8px;
  cursor: pointer;
  min-height: 32px;
  min-width: 32px;
  transition: background .1s, color .1s;
}
.vault-filter-btn.active,
.vault-filter-btn:hover {
  background: var(--amber-dim);
  color: var(--amber);
  border-color: var(--amber);
}
.vault-filter-row2 {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 12px;
  border-bottom: 1px solid var(--green-dim);
  flex-shrink: 0;
}
.vault-shard-display {
  font-size: 11px;
  color: var(--amber);
  letter-spacing: 2px;
  flex: 1;
}
.vault-bulk-btn {
  background: none;
  border: 1px solid rgba(255,90,77,.4);
  color: var(--red);
  font-family: inherit;
  font-size: 9px;
  letter-spacing: 1.5px;
  padding: 6px 12px;
  cursor: pointer;
  min-height: 44px;
}
.vault-bulk-btn:hover { background: rgba(255,90,77,.1); }

/* (Removed dead .vault-grid / .vault-cell — the legacy 5-col card grid; the vault
   renders the organizer table, and Card mode is the data-view grid below.
   docs/ui-scale-vault-view.md) */
.vault-empty {
  color: var(--green-dim);
  font-size: 11px;
  padding: 20px;
  letter-spacing: 2px;
}

/* Vault detail panel */
.vault-detail {
  flex-shrink: 0;
  max-height: 280px;
  overflow-y: auto;
  border-top: 1px solid var(--green-dim);
  background: rgba(10,14,42,.96);
  position: relative;
}
.vault-detail-wrap {
  padding: 14px;
}
.vault-detail-title {
  font-size: 15px;
  letter-spacing: 2px;
  margin-bottom: 3px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.vault-detail-sub {
  font-size: 10px;
  color: var(--green);
  opacity: .6;
  letter-spacing: 2px;
  margin-bottom: 10px;
}
.vault-detail-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin-bottom: 10px;
}
.vault-detail-stat-row {
  font-size: 10px;
  display: flex;
  gap: 6px;
  align-items: center;
}
.stat-key { color: var(--amber); letter-spacing: 1px; }
.stat-val { color: var(--green); }
.vault-detail-perks {
  font-size: 9px;
  color: var(--green);
  opacity: .6;
  letter-spacing: 1px;
  margin-bottom: 8px;
}
.vault-detail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.vault-action-btn {
  font-size: 10px;
  padding: 8px 12px;
  min-height: 44px;
  letter-spacing: 1.5px;
}
.vault-action-dismantle {
  border-color: rgba(255,90,77,.5) !important;
  color: var(--red) !important;
}
.vault-detail-close {
  position: absolute;
  top: 8px;
  right: 8px;
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 12px;
  padding: 4px 8px;
  cursor: pointer;
  min-width: 32px;
  min-height: 32px;
}
.vault-toast {
  padding: 14px 20px;
  color: var(--amber);
  font-size: 13px;
  letter-spacing: 2px;
  text-align: center;
}
.vault-toast-err {
  color: var(--red);
}

/* ── R2.1.1 — LOADOUTS tab (replaces bottom saved-loadout bar) ──────────────
 * Full-page list of 10 saved-loadout slot cards. Each card shows class +
 * abilities + gear + description/loop + notes textarea + per-card actions. */
.loadouts-panel {
  flex-direction: column;
  overflow-y: auto;
  padding: 12px 16px 20px;
  gap: 14px;
  /* Steam-deck readability: proximity scroll-snap so dpad / thumbstick paging
     lands cleanly on one card at a time instead of stranding the view mid-card
     (proximity, not mandatory, so it never fights nav.js's scrollIntoView on a
     focused apply button). */
  scroll-snap-type: y proximity;
}
/* Sticky (loadouts-filters): `.loadouts-panel` is the scroll container, and
   nav.js's scrollIntoView on the first focused APPLY already pushed the head
   off-screen on open. The filter bar lives here, so it has to survive scrolling
   — searching a long list from row 30 is the whole point. */
.lo-loadouts-head {
  flex-shrink: 0;
  position: sticky;
  top: -12px;              /* cancel .loadouts-panel's own top padding */
  z-index: 3;
  background: var(--void);
  padding: 12px 0 8px;
  margin: -12px 0 0;
  border-bottom: 1px solid var(--green-dim);
}
.lo-loadouts-title {
  color: var(--amber);
  font-size: 16px;
  letter-spacing: 3px;
}
.lo-loadouts-sub {
  color: var(--green);
  opacity: 0.6;
  font-size: 12px;
  letter-spacing: 1.5px;
  margin-top: 4px;
}
/* ── loadouts-filters (2026-07-26) ─────────────────────────────────────────
   The LOADOUTS tab's find-a-build bar: free-text search + class / element /
   status chips + a sort cycle. Two compact lines by design — the density pass
   above exists to fit more ROWS on screen, so the chrome that finds them must
   not eat the win back. Chips wrap; nav.js walks them by real screen rect. */
.lo-lofilter-host { margin-top: 8px; }
.lo-lofilter {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  max-width: 1040px;
  margin: 0 auto;
}
.lo-lofilter-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lo-lofilter-search {
  flex: 1;
  min-width: 180px;
  background: rgba(51, 255, 102, 0.05);
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 12px;
  letter-spacing: 1px;
  padding: 6px 10px;
  outline: none;
}
.lo-lofilter-search::placeholder { color: var(--green); opacity: 0.35; }
.lo-lofilter-search:focus,
.lo-lofilter-search.ui-focused {
  border-color: var(--amber);
  outline: 2px solid var(--amber);
  outline-offset: -2px;
}
.lo-lofilter-count {
  font-size: 11px;
  letter-spacing: 1.5px;
  color: var(--green);
  opacity: 0.55;
  flex-shrink: 0;
}
.lo-lofilter-count-on { color: var(--amber); opacity: 1; }
.lo-lofilter-clear { font-size: 11px; letter-spacing: 1.5px; padding: 5px 12px; flex-shrink: 0; }
.lo-lofilter-chip-line { gap: 5px; }
.lo-lofilter-chip {
  background: transparent;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 1.2px;
  padding: 3px 8px;
  cursor: pointer;
  opacity: 0.72;
}
.lo-lofilter-chip:hover { opacity: 1; background: rgba(51, 255, 102, 0.06); }
.lo-lofilter-chip-on {
  opacity: 1;
  color: var(--void);
  background: var(--green);
  border-color: var(--green);
}
.lo-lofilter-chip.ui-focused {
  outline: 2px solid var(--amber);
  outline-offset: -2px;
}
.lo-lofilter-chip-class { color: var(--amber); border-color: var(--amber-dim); }
.lo-lofilter-chip-class.lo-lofilter-chip-on { background: var(--amber); border-color: var(--amber); }
/* Element chips carry their own damage-type color so the row's element sigils
   and the filter that finds them read as the same vocabulary. */
.lo-lofilter-chip-elem.elem-burn    { color: var(--elem-burn);    border-color: currentColor; }
.lo-lofilter-chip-elem.elem-shock   { color: var(--elem-shock);   border-color: currentColor; }
.lo-lofilter-chip-elem.elem-rupture { color: var(--elem-rupture); border-color: currentColor; }
.lo-lofilter-chip-elem.lo-lofilter-chip-on {
  background: currentColor;
  /* `color` is the chip tint; the label needs the dark plate to stay legible. */
  -webkit-text-fill-color: var(--void);
}
.lo-lofilter-chip-sort { color: var(--cream); border-color: var(--cream); }
.lo-lofilter-chip-sort.lo-lofilter-chip-on { background: var(--cream); border-color: var(--cream); }
.lo-lofilter-sep {
  width: 1px;
  align-self: stretch;
  background: var(--green-dim);
  opacity: 0.5;
  margin: 0 3px;
}
.lo-lofilter-none {
  padding: 24px 18px;
  text-align: center;
  color: var(--amber);
  opacity: 0.7;
  font-size: 12px;
  letter-spacing: 2px;
  border: 1px dashed var(--amber-dim);
}
@media (min-width: 900px) {
  .lo-lofilter-search { font-size: 14px; padding: 7px 12px; }
  .lo-lofilter-count  { font-size: 13px; }
  .lo-lofilter-clear  { font-size: 12px; }
  .lo-lofilter-chip   { font-size: 12px; padding: 4px 10px; }
  .lo-lofilter-none   { font-size: 14px; }
}
/* Portrait/phone: the sticky head is now search + 3 chip groups, so the
   how-to-use subtitle is the first thing to go — the row list teaches itself,
   and every pixel here is a pixel the density pass just bought back. */
@media (max-width: 899px) {
  .lo-loadouts-sub    { display: none; }
  .lo-loadouts-title  { font-size: 13px; }
  .lo-lofilter-search { min-width: 120px; font-size: 11px; padding: 5px 8px; }
  .lo-lofilter-count  { font-size: 10px; }
  .lo-lofilter-clear  { font-size: 10px; padding: 4px 9px; }
  .lo-lofilter-chip   { font-size: 9.5px; padding: 3px 6px; letter-spacing: 0.8px; }
  .lo-lofilter-sep    { display: none; }
}
/* loadouts-screen-redesign (2026-07-21) — one full-width row per slot on every
   surface. The old 2-up grid made each card half-width and doubled the read
   length on iPhone portrait / Deck / desktop alike. */
.lo-cards-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  max-width: 1040px;
  margin: 0 auto;
}
.lo-card {
  border: 1px solid var(--green-dim);
  background: rgba(51, 255, 102, 0.025);
  padding: 18px 22px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  scroll-snap-align: start;
  /* Clear the sticky `.lo-loadouts-head` (measured into --lo-head-h in
     _refreshLoadoutsPanel) so a snap to a card's start doesn't park it
     underneath the filter bar. */
  scroll-margin-top: var(--lo-head-h, 0px);
}
.lo-card-empty   { opacity: 0.5; border-style: dashed; }
.lo-card-locked  { border-color: var(--amber-dim); background: rgba(255, 176, 0, 0.04); }
.lo-card-active  { border-color: var(--green); box-shadow: 0 0 8px rgba(51, 255, 102, 0.18) inset; }

.lo-card-hdr {
  display: flex;
  align-items: center;
  gap: 12px;
}
/* C (menus-refit-spec.md) — the collapsed row IS the expand/collapse toggle:
   `.lo-card-toggle` (num/name/chevron) is the WIDE mouse-clickable wrapper —
   convenient for a mouse, but it is deliberately NOT the registered nav cell.
   nav.js's geometry-first mover picks the nearest cell by bounding-rect
   CENTER, and a ~1000px-wide wrapper centers nowhere near the far-right APPLY
   button, so d-pad/keyboard LEFT from APPLY skipped clean past it to an
   unrelated header button (verified against the live rects). The small
   `.lo-card-chevron` below (parked right next to APPLY) is the actual
   registered cell — both rects stay tight and genuinely adjacent, and the
   chevron's click bubbles up to this wrapper's listener either way. */
.lo-card-toggle {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
  cursor: pointer;
}
.lo-card-empty .lo-card-toggle { cursor: default; }
.lo-card-toggle:hover { background: rgba(51, 255, 102, .04); }
.lo-card-chevron {
  color: var(--amber);
  opacity: .7;
  font-size: 13px;
  flex-shrink: 0;
  width: 14px;
  text-align: center;
}
/* Focus ring — `.lo-card-chevron` isn't a `.cell` (that would also import a
   border + min-height that clashes with its tiny footprint), so it gets the
   same bespoke `.ui-focused` treatment as `.lo-card-apply` below. */
.lo-card-chevron.ui-focused {
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
  border-radius: 2px;
}
.lo-card-num {
  width: 36px; height: 36px;
  border: 1px solid var(--amber-dim);
  color: var(--amber);
  font-size: 16px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.lo-card-name-wrap {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.lo-card-name {
  color: var(--green);
  font-size: 14px;
  letter-spacing: 2px;
}
.lo-card-template-chip,
.lo-card-active-chip {
  font-size: 9px;
  letter-spacing: 1.5px;
  padding: 2px 6px;
  border: 1px solid;
}
.lo-card-template-chip { color: var(--amber); border-color: var(--amber); }
.lo-card-active-chip   { color: var(--green); border-color: var(--green); }
.lo-card-apply {
  flex-shrink: 0;
  font-size: 11px;
  letter-spacing: 2px;
  padding: 8px 14px;
}
.lo-card-apply-locked { color: var(--amber); border-color: var(--amber); opacity: 0.7; cursor: default; }

/* ── loadouts-screen-redesign (2026-07-21) — compact row list ──────────────
   Each slot is one tappable full-width row: header line (num · name · chips ·
   open-chevron · APPLY), then the glance strip (class glyph · weapon badges ·
   ability icons · weapon perk chips), armor-total pills, and the notes
   (clamped by screen height). Tapping anywhere but a button opens the
   full-screen build guide. */
/* DENSITY PASS (loadouts-filters, 2026-07-26) — every vertical metric below
   is ~60% of what the 2026-07-21 "30% bigger" pass left behind: "make the rows
   about 60% of their size vertically. So we can see more on one screen."
   Horizontal type stays legible; what shrinks is row padding, inter-block gaps,
   icon box heights, and the notes line-clamp — the four things that actually
   set row height. Measured against live rects: desktop 321px → ~195px. */
.lo-lrow { padding: 8px 16px; gap: 6px; cursor: pointer; }
.lo-lrow:hover { background: rgba(51, 255, 102, 0.05); }
.lo-card-empty.lo-lrow { cursor: default; }
.lo-card-empty.lo-lrow:hover { background: rgba(51, 255, 102, 0.025); }
.lo-lrow-strip {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.lo-lrow-class {
  width: 28px; height: 28px;
  border: 1px solid var(--amber-dim);
  color: var(--amber);
  font-size: 17px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.lo-lrow-classcell { display: flex; align-items: center; gap: 5px; flex-shrink: 0; }
.lo-lrow-classname { font-size: 9px; letter-spacing: 1px; color: var(--amber); }
.lo-lrow-icon { display: flex; flex-shrink: 0; }
.lo-lrow-weapon svg { width: 30px; height: 30px; display: block; }
.lo-lrow-ab {
  width: 28px; height: 28px;
  border: 1px solid var(--green-dim);
  background: rgba(51, 255, 102, 0.04);
  align-items: center; justify-content: center;
}
.lo-lrow-ab svg { width: 21px; height: 21px; display: block; }
/* A gun + its perk chips wrap as ONE unit so the two guns' perks never
   interleave (follow-up 2026-07-21). */
.lo-lrow-wgroup { display: flex; align-items: center; gap: 6px; }
.lo-lrow-wgroup .bl-perk-chips { margin-top: 0; }
/* Ability cell: icon + stacked ROLE / VERB labels — the compact loop read.
   Density pass: role + verb sit SIDE BY SIDE (was stacked), so the ab strip's
   height is the icon box alone instead of two stacked 14px glyph lines. */
.lo-lrow-abcell { display: flex; align-items: center; gap: 5px; flex-shrink: 0; }
.lo-lrow-abmeta { display: flex; flex-direction: row; align-items: center; gap: 4px; line-height: 1; }
/* Loop-step glyphs instead of the words PRIME/DETONATE/FATE (2026-07-21) —
   color classes tint the currentColor SVGs. */
.lo-lrow-abrole { display: flex; gap: 2px; }
.lo-lrow-abrole .loop-icon-svg { width: 12px; height: 12px; display: block; }
.lo-lrow .bl-perk-chip-step { display: inline-flex; }
.lo-lrow .bl-perk-chip-step .loop-icon-svg { width: 12px; height: 12px; display: block; }
.lo-lrow-abrole.role-prime    { color: var(--rarity-rare); }  /* cyan — set up the loop */
.lo-lrow-abrole.role-detonate { color: var(--amber); }        /* amber — pop the loop */
.lo-lrow-abrole.role-hybrid   { color: var(--green); }
/* Verb sigil (behavior-icon.js), not the word — tinted by the cream color. */
.lo-lrow-abverb { display: flex; color: var(--cream); opacity: 0.85; }
.lo-lrow-abverb .behavior-icon-svg { width: 12px; height: 12px; display: block; }
.lo-lrow-stats { display: flex; flex-wrap: wrap; gap: 3px 6px; }
/* Shared-class overrides at row scale. */
.lo-lrow .lo-card-num { width: 28px; height: 28px; font-size: 14px; }
.lo-lrow .lo-card-name { font-size: 15px; }
.lo-lrow .lo-card-template-chip,
.lo-lrow .lo-card-active-chip { font-size: 10px; padding: 1px 6px; }
.lo-lrow .lo-card-apply { font-size: 12px; padding: 5px 12px; }
.lo-lrow .lo-card-chevron { font-size: 14px; width: 16px; }
.lo-lrow .lo-card-hdr { gap: 9px; }
.lo-lrow .bl-perk-chip { font-size: 11.5px; padding: 1px 6px; }
.lo-lrow .bl-perk-chip-role { font-size: 9px; }
.lo-lrow .lo-card-gear-stat-pill { font-size: 11px; padding: 1px 6px; }
/* Desktop keeps the larger TYPE (playtest 2026-07-21: "make desktop 30% larger
   again") but not the larger BOXES — the density pass caps every height-setting
   metric so a 900px-wide screen still shows 4+ rows at once. */
@media (min-width: 900px) {
  .lo-lrow { padding: 9px 20px; gap: 6px; }
  .lo-lrow-strip { gap: 10px; }
  .lo-lrow-class { width: 34px; height: 34px; font-size: 20px; }
  .lo-lrow-weapon svg { width: 38px; height: 38px; }
  .lo-lrow-ab { width: 34px; height: 34px; }
  .lo-lrow-ab svg { width: 25px; height: 25px; }
  .lo-lrow-wgroup { gap: 7px; }
  .lo-lrow-classcell { gap: 6px; }
  .lo-lrow-classname { font-size: 11px; }
  .lo-lrow-abcell { gap: 6px; }
  .lo-lrow-abmeta { gap: 5px; }
  .lo-lrow-abrole .loop-icon-svg,
  .lo-lrow-abverb .behavior-icon-svg,
  .lo-lrow .bl-perk-chip-step .loop-icon-svg { width: 14px; height: 14px; }
  .lo-lrow-stats { gap: 4px 8px; }
  .lo-lrow .lo-card-num { width: 34px; height: 34px; font-size: 17px; }
  .lo-lrow .lo-card-name { font-size: 18px; }
  .lo-lrow .lo-card-template-chip,
  .lo-lrow .lo-card-active-chip { font-size: 12px; padding: 2px 7px; }
  .lo-lrow .lo-card-apply { font-size: 14px; padding: 6px 16px; }
  .lo-lrow .lo-card-chevron { font-size: 17px; width: 20px; }
  .lo-lrow .bl-perk-chip { font-size: 13.5px; padding: 2px 8px; }
  .lo-lrow .bl-perk-chip-role { font-size: 11px; }
  .lo-lrow .lo-card-gear-stat-pill { font-size: 13px; padding: 2px 8px; }
}
.lo-lrow-notes {
  font-size: 12px;
  line-height: 1.35;
  color: var(--cream);
  opacity: 0.85;
  text-transform: none;
  letter-spacing: 0.4px;
  /* "Grow with prose, sensible screen-size limit" — line-clamp by height tier.
     Density pass: 1 line at rest (the full text is one tap away in the build
     guide); tall screens get a second. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  overflow: hidden;
}
@media (min-height: 1000px) { .lo-lrow-notes { -webkit-line-clamp: 2; } }
@media (min-width: 900px)   { .lo-lrow-notes { font-size: 14px; } }

/* ── loadouts-screen-redesign — the full-screen build guide ────────────────
   Single column on every surface. Reuses the section / gear-row / totals
   grammar from the old card; header carries chips · sentence · loop warning ·
   actions · notes · BUILD STATS. `.lo-det-same` dims pieces the player is
   already wearing (non-active loadouts only) so the diff pops. */
.loadouts-panel-detail .lo-cards-list { max-width: 860px; }
.lo-det { display: flex; flex-direction: column; gap: 14px; }
.lo-det-head { display: flex; flex-direction: column; gap: 10px; }
.lo-det-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lo-det-slot-chip {
  font-size: 9px;
  letter-spacing: 1.5px;
  padding: 2px 6px;
  border: 1px solid var(--green-dim);
  color: var(--green);
  opacity: 0.8;
}
.lo-det-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.lo-det-actions .touch-btn { font-size: 11px; letter-spacing: 1.5px; padding: 10px 16px; }
.lo-det-actions .lo-card-apply { font-size: 12px; letter-spacing: 2px; padding: 10px 22px; }
.lo-det-notes { width: 100%; resize: vertical; overflow: hidden; }
.lo-det-diff-hint {
  font-size: 9px;
  letter-spacing: 2px;
  color: var(--amber);
  opacity: 0.7;
}
/* Playtest 2026-07-21: 0.4 read as the whole guide being washed out when most
   of a build matched the worn one — keep the diff visible but subtle. */
.lo-det-same { opacity: 0.7; }
.lo-det-gear-list { display: flex; flex-direction: column; gap: 8px; }
.lo-det-ab-wrap { display: flex; flex-direction: column; gap: 4px; }
.lo-det-sections .lo-card-section-body { padding: 4px 2px 14px; }

/* (loadouts-screen-redesign — the 2-column `.lo-card-body`/`.lo-card-col` card
   layout is gone: the build guide is single-column on every surface.) */
.lo-card-col-head {
  font-size: 11px;
  letter-spacing: 2px;
  color: var(--amber);
  opacity: 0.8;
  margin-bottom: 2px;
}
.lo-card-class {
  font-size: 13px;
  letter-spacing: 2px;
  color: var(--amber);
  margin-bottom: 4px;
}
/* R2.1.1 — Class chassis details under the class line (JUMP / PASSIVE / ULT). */
.lo-card-class-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--green-dim);
}
.lo-card-class-meta-row {
  display: flex;
  gap: 8px;
  font-size: 12px;
  letter-spacing: 1px;
}
.lo-card-class-meta-k {
  color: var(--amber);
  opacity: 0.7;
  width: 60px;
  flex-shrink: 0;
}
.lo-card-class-meta-v {
  color: var(--green);
}
/* Ability prose description, indented under the slot label so it reads as a
 * continuation of the ability above. */
.lo-card-ab-desc {
  margin-left: 104px;
  margin-top: 2px;
  font-size: 11px;
  line-height: 1.5;
  color: var(--cream);
  opacity: 0.85;
  text-transform: none;
  letter-spacing: 0.4px;
}
/* SYNERGIES bullet list on the card. */
.lo-card-synergies {
  list-style: none;
  padding: 0;
  margin: 0 0 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.lo-card-synergies li {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--cream);
  text-transform: none;
  letter-spacing: 0.4px;
  padding-left: 10px;
  position: relative;
}
.lo-card-synergies li::before {
  content: '•';
  color: var(--green);
  position: absolute;
  left: 0;
}
/* R2.1.1 — Roomier rows. The gear / ability lists were cramped (32px slot
 * labels overlapping item names like "PRIMARY COBALT DOCTRINE"). Slot labels
 * now reserve their own width; each ability gets a sub-line with archetype
 * + stats summary so the player can read what the ability *does* without
 * opening the picker. */
.lo-card-ab-list, .lo-card-gear-list { display: flex; flex-direction: column; gap: 8px; }
/* R2.1.1 — Each gear piece is a 2-tier block: [slot · name] + inline stat
 * pills below. Below the gear list, the BUILD TOTALS section sums every
 * stat across the 5 pieces and renders them as horizontal bars. */
.lo-card-gear-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 0;
  border-top: 1px solid var(--green-dim);
}
.lo-card-gear-row:first-child { border-top: none; padding-top: 0; }
.lo-card-gear-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 12px;
}
.lo-card-gear-stats {
  margin-left: 88px;            /* align with the name (skip slot-lbl column) */
  display: flex;
  flex-wrap: wrap;
  gap: 4px 6px;
}
.lo-card-gear-stat-pill {
  font-size: 10px;
  letter-spacing: 0.5px;
  color: var(--green);
  padding: 1px 6px;
  border: 1px solid var(--green-dim);
  background: rgba(51, 255, 102, 0.04);
  white-space: nowrap;
}

/* R2.1.2 — Stat tables (ARMOR + WEAPONS) on the LOADOUTS card. */
.lo-card-col-head-spaced { margin-top: 14px; }
.lo-card-stat-table {
  width: 100%;
  min-width: 0;          /* B3 — shrinkable inside .lo-card-col (flex column) */
  table-layout: fixed;   /* B3 — column widths follow the container, not the
                             nowrap content below, so the table can never push
                             past .lo-card-col into SYNERGIES (this was the
                             pre-existing ~46px overlap at scale 1.0 too, not
                             just a UI-SCALE regression). */
  border-collapse: collapse;
  font-size: 11.5px;
  letter-spacing: 0.5px;
  margin-top: 4px;
}
.lo-card-stat-th, .lo-card-stat-td {
  padding: 4px 4px;
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-bottom: 1px solid var(--green-dim);
}
.lo-card-stat-th {
  color: var(--amber);
  opacity: 0.75;
  font-weight: normal;
  /* B3 — trimmed from 1.5px: the armor table has 6 stat columns squeezed into
     a fixed-layout width now (no more blowing past .lo-card-col), and headers
     like SHIELD/S.RATE need every spare px to avoid ellipsis at narrow tiers. */
  letter-spacing: 0.5px;
}
/* NAME gets a fixed share of the fixed-layout table; the remaining stat
   columns (up to 6 on the armor table, 3 on the weapons table) split what's
   left evenly — replaces the old content-sized min-width:110px, which is what
   table-layout:auto used to blow the column past .lo-card-col's 1.4fr track.
   30% (not a rounder 1/3) leaves a touch more room for the 6-wide armor stats. */
.lo-card-stat-th-name { text-align: left; padding-left: 0; width: 30%; }
.lo-card-stat-td { color: var(--green); }
.lo-card-stat-td-name {
  text-align: left;
  padding-left: 0;
  font-size: 11px;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;   /* B3 — flex children (.lo-card-stat-name) can ellipsis instead of forcing the fixed column wider */
}
.lo-card-stat-slot {
  font-size: 10.5px;
  letter-spacing: 1.5px;
  color: var(--amber);
  opacity: 0.7;
  width: 64px;
  flex-shrink: 0;
}
.lo-card-stat-slot-total { color: var(--amber); opacity: 1; font-weight: bold; }
.lo-card-stat-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.lo-card-stat-name-empty { color: var(--green-dim); }
.lo-card-stat-td-empty { color: var(--green-dim); }
.lo-card-stat-row-total .lo-card-stat-td {
  color: var(--amber);
  font-weight: bold;
  border-top: 1px solid var(--amber-dim);
  border-bottom: none;
}
.lo-card-stat-row-active .lo-card-stat-td-name::after {
  content: 'IN HAND';
  font-size: 8px;
  letter-spacing: 1.5px;
  color: var(--green);
  background: rgba(51, 255, 102, 0.10);
  border: 1px solid var(--green-dim);
  padding: 1px 4px;
  margin-left: 6px;
}

/* Weapon perk row — the two rolled perks under each gun in the EQUIPPED
   WEAPONS table. Full-width cell, chip per perk, no bottom border so it reads
   as attached to the stat row above it. */
.lo-card-perk-row .lo-card-perk-cell {
  padding: 3px 6px 8px 6px;
  border-bottom: 1px solid var(--fx-green-line-dim, rgba(51,255,102,.12));
}
.lo-card-perk-chip {
  display: inline-block;
  margin: 2px 6px 0 0;
  padding: 2px 7px;
  border: 1px solid var(--green-dim);
  border-radius: 2px;
  background: rgba(51, 255, 102, 0.06);
}
.lo-card-perk-name {
  font-size: 9px;
  letter-spacing: 1.5px;
  color: var(--green);
}
.lo-card-perk-row.lo-card-stat-row-active .lo-card-perk-chip {
  border-color: var(--amber-dim);
}
.lo-card-perk-row.lo-card-stat-row-active .lo-card-perk-name {
  color: var(--amber);
}

/* BUILD TOTALS — armor-only, realistic per-stat cap + tick. */
.lo-card-totals {
  margin-top: 14px;
  padding-top: 10px;
  border-top: 1px solid var(--amber-dim);
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.lo-card-totals-hint {
  font-size: 9px;
  color: var(--green);
  opacity: 0.6;
  letter-spacing: 0.5px;
  margin-bottom: 4px;
  text-transform: none;
}
.lo-card-total-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10px;
  letter-spacing: 1px;
}
.lo-card-total-lbl {
  width: 60px;          /* tighter — shield labels are now S.DLY / S.RATE */
  flex-shrink: 0;
  color: var(--green);
  opacity: 0.85;
  text-transform: uppercase;
}
.lo-card-total-track {
  flex: 1;
  height: 8px;
  border: 1px solid var(--green-dim);
  background: rgba(51, 255, 102, 0.04);
  overflow: hidden;
  position: relative;
}
.lo-card-total-fill {
  height: 100%;
  width: 0%;
  background: var(--green);
  transition: width 0.2s ease;
}
/* Vertical tick at the "full-legendary target" point on the bar. */
.lo-card-total-tick {
  position: absolute;
  top: -1px;
  bottom: -1px;
  width: 2px;
  background: var(--amber);
  opacity: 0.9;
  pointer-events: none;
}
.lo-card-total-val {
  width: 56px;
  text-align: right;
  flex-shrink: 0;
  color: var(--cream);
  letter-spacing: 0;
}
.lo-card-total-val-above {
  color: var(--amber);
  font-weight: bold;
}
.lo-card-ab-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 6px 0;
  border-top: 1px solid var(--green-dim);
}
.lo-card-ab-row:first-child { border-top: none; padding-top: 0; }
.lo-card-ab-line {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--green);
}
.lo-card-ab-slot-lbl, .lo-card-gear-slot-lbl {
  font-size: 10px;
  letter-spacing: 1.2px;  /* tightened when the label grew its bind suffix */
  color: var(--amber);
  opacity: 0.75;
  width: 104px;           /* fits ABILITY 1 · L2 / CLASS · HOLD R3 */
  flex-shrink: 0;
  text-align: left;
}
.lo-card-ab-name { color: var(--green); font-size: 14px; }
.lo-card-ab-empty, .lo-card-gear-empty { color: var(--green-dim); }
.lo-card-gear-name {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12px;
}
/* Sub-line under each ability: archetype, element, then numeric summary. */
.lo-card-ab-meta {
  margin-left: 104px;    /* align with the name above (skip slot-label column) */
  font-size: 11px;
  letter-spacing: 0.5px;
  color: var(--green);
  opacity: 0.75;
}
.lo-card-ab-arch {
  color: var(--amber);
  opacity: 0.85;
  margin-right: 6px;
  letter-spacing: 1.5px;
}

.lo-card-desc {
  font-size: 11px;
  line-height: 1.45;
  color: var(--cream);
  text-transform: none;
  letter-spacing: 0.5px;
}
.lo-card-loop {
  margin: 4px 0 8px;
  white-space: pre-wrap;
  font-family: inherit;
  font-size: 11px;
  line-height: 1.45;
  color: var(--cream);
  text-transform: none;
  letter-spacing: 0.5px;
  background: rgba(51, 255, 102, 0.04);
  border-left: 2px solid var(--green-dim);
  padding: 6px 10px;
}
.lo-card-notes {
  width: 100%;
  resize: vertical;
  background: rgba(10, 14, 42, 0.85);
  border: 1px solid var(--green-dim);
  color: var(--cream);
  font-family: inherit;
  font-size: 11px;
  text-transform: none;
  letter-spacing: 0.5px;
  padding: 6px 10px;
  min-height: 56px;
}
.lo-card-notes:focus { outline: 1px solid var(--amber); }

/* (loadouts-screen-redesign — the expanded-card `.lo-card-foot` is gone; the
   slot-management verbs live in the build guide's `.lo-det-actions` row.) */
.lo-card-delete { color: var(--red); border-color: var(--red); }

/* C (menus-refit-spec.md) — the Deck-class short-landscape `:root.eff-h-le-860`
   compaction rules that used to live here (shedding ability prose + BUILD
   TOTALS + shield sub-columns so one fully-expanded card fit the screen) are
   gone: collapse-by-default means only ONE card is ever expanded at a time
   now, so the height pressure they existed to relieve no longer applies. */

/* ── SAVED LOADOUT BAR (single slim row: label sits inline with the slots) ── */
.lo-loadout-bar {
  flex-shrink: 0;
  border-top: 1px solid var(--green-dim);
  padding: 6px 16px;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 12px;
}
.lo-loadout-bar-label {
  font-size: 9px;
  color: var(--amber);
  letter-spacing: 3px;
  opacity: .8;
  flex-shrink: 0;
}
.lo-slots-row {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  flex: 1;
}
.lo-slot-btn {
  min-width: 52px;
  padding: 4px 8px;
  border-radius: 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-height: 44px;
  cursor: pointer;
  flex-shrink: 0;
}
.lo-slot-num {
  font-size: 14px;
  color: var(--amber);
  letter-spacing: 1px;
}
.lo-slot-name {
  font-size: 8px;
  color: var(--green);
  letter-spacing: 1px;
  text-align: center;
  opacity: .7;
  max-width: 58px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lo-slot-filled .lo-slot-num {
  color: var(--green);
}

/* Slot menu popup */
.lo-slot-menu {
  position: absolute;
  bottom: 80px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--panel-bg);
  border: 1px solid var(--green-dim);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 40;
  min-width: 200px;
}

/* R2.1 — Loadout INFO modal (build guide / how-to-play). Centered card with the
 * preset's description + a preformatted loop block. Z-index above slot menu. */
.lo-info-modal {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--panel-bg);
  border: 1px solid var(--green);
  padding: 18px 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 50;
  min-width: 320px;
  max-width: 560px;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 0 18px rgba(51, 255, 102, 0.18);
}
.lo-info-head {
  border-bottom: 1px solid var(--green-dim);
  padding-bottom: 8px;
}
.lo-info-title {
  font-size: 18px;
  letter-spacing: 3px;
  color: var(--amber);
  text-transform: uppercase;
}
.lo-info-sub {
  font-size: 10px;
  letter-spacing: 2px;
  color: var(--green);
  opacity: 0.7;
  margin-top: 2px;
}
.lo-info-desc {
  font-size: 13px;
  line-height: 1.5;
  color: var(--cream);
}
.lo-info-loop-head {
  margin-top: 4px;
  font-size: 11px;
  letter-spacing: 2px;
  color: var(--green);
  text-transform: uppercase;
}
.lo-info-loop {
  margin: 0;
  white-space: pre-wrap;
  font-family: inherit;
  font-size: 12px;
  line-height: 1.5;
  color: var(--cream);
  background: rgba(51, 255, 102, 0.05);
  border-left: 2px solid var(--green-dim);
  padding: 8px 12px;
}
.lo-info-close {
  align-self: flex-end;
  margin-top: 6px;
}
.lo-info-req-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0 0 10px;
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(255, 180, 60, 0.25);
  font-size: 12px;
  letter-spacing: 0.5px;
}
.lo-info-req-row {
  color: var(--amber, #ffb43c);
}
.lo-info-req-detail {
  opacity: 0.75;
  font-size: 11px;
}
.lo-info-tapestry {
  align-self: stretch;
  margin-bottom: 8px;
}

/* ── Header actions row (RESUME + QUIT) ─────────────────────────────────── */
.lo-header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

/* MAIN MENU — secondary action that returns to the start screen. Always shown
 * (R3); mid-run it acts as the abandon path (main.js's ui:mainMenu handler tears
 * the run down before re-opening the start screen). Green-dim styling so it
 * reads as navigation, not a destructive action — the abandon-confirmation
 * affordance lives in the start screen flow, not on this button itself. */
.lo-main-menu-btn {
  flex-shrink: 0;
  font-size: 11px;
  letter-spacing: 1.5px;
  padding: 6px 12px;
  min-height: 36px;
  text-align: center;
  background: rgba(51,255,102,.06);
  border: 1px solid var(--green-dim, rgba(51,255,102,.4));
  color: var(--green, #33ff66);
  cursor: pointer;
  font-family: inherit;
  transition: background .12s, box-shadow .12s;
}
.lo-main-menu-btn:hover, .lo-main-menu-btn:active {
  background: rgba(51,255,102,.18);
  box-shadow: 0 0 12px rgba(51,255,102,.30);
}

/* ── COMMENCE button (compact primary action, lives in the header) ────────── */
/* Primary action — angular key, consistent with the start screen + DEPLOY.
   Brighten-don't-invert: hover/focus lights up (warm wash + accent bar + glow),
   label stays light (amber→cream). */
.lo-commence-btn {
  position: relative; overflow: hidden;
  flex-shrink: 0; font-size: 12px; letter-spacing: 2px; font-weight: 700;
  padding: 8px 16px 8px 18px; min-height: 38px; text-align: center;
  background: linear-gradient(0deg, rgba(255,176,0,.12), rgba(255,176,0,.04));
  border: 1px solid var(--amber); color: var(--amber); cursor: pointer; font-family: inherit;
  clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px);
  box-shadow: var(--fx-glow-amber); z-index: 1;
  transition: color .14s, background .16s, box-shadow .16s;
}
.lo-commence-btn::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--amber); box-shadow: 0 0 10px var(--amber);
  transform: scaleY(0); transform-origin: bottom; transition: transform .18s ease;
}
.lo-commence-btn:hover, .lo-commence-btn:active, .lo-commence-btn.ui-focused {
  color: var(--cream, #f0e6c8); outline: none;
  background: linear-gradient(0deg, rgba(255,176,0,.22), rgba(255,176,0,.09));
  box-shadow: 0 0 26px rgba(255,176,0,.30), 0 0 7px rgba(255,176,0,.45);
}
.lo-commence-btn:hover::before, .lo-commence-btn:active::before, .lo-commence-btn.ui-focused::before { transform: scaleY(1); }
/* Mid-run RESUME: the rest-state glow + bright amber is the same hue as the
   d-pad focus ring, so next to the flat MAIN MENU/SETTINGS buttons it read as
   already-selected. Rest quiet (no glow, dim border/label); hover/active/
   ui-focused above still light it up fully, so real focus stays unmistakable. */
.lo-commence-btn.lo-commence-midrun:not(:hover):not(:active):not(.ui-focused) {
  background: rgba(255,176,0,.05);
  border-color: var(--amber-dim);
  color: rgba(255,196,64,.75);
  box-shadow: none;
}

/* ── Toast ───────────────────────────────────────────────────────────────── */
.lo-toast {
  position: absolute;
  top: 60px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(10,14,42,.95);
  border: 1px solid var(--amber);
  color: var(--amber);
  padding: 10px 24px;
  font-size: 13px;
  letter-spacing: 2px;
  z-index: 50;
  pointer-events: none;
  animation: lo-toast-in .12s ease;
}
@keyframes lo-toast-in {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to   { opacity: 1; transform: translateX(-50%); }
}

/* ── Hint footer ─────────────────────────────────────────────────────────── */
/* Mid-run RUN PERKS strip (combat-hud-review R4 / P3): one line per active
   roguelite perk, seated above the hint footer. Only visible on mid-run opens
   (loadout.js hides it pre-run / with no perks taken). */
.lo-run-perks {
  flex-shrink: 0;
  display: flex; flex-direction: row; flex-wrap: wrap;
  gap: 4px 18px; align-items: baseline;
  padding: 5px 16px;
  border-top: 1px solid var(--green-dim);
  background: rgba(10,14,42,.6);
  z-index: 1;
}
.lo-run-perks .lo-run-perks-title {
  font-size: 9px; letter-spacing: 2px; color: var(--green); opacity: .8;
}
.lo-run-perks .perk-line {
  font-size: 10px; letter-spacing: 1px; color: var(--amber); white-space: nowrap;
}
.lo-run-perks .perk-line::first-letter { color: var(--green); }

.lo-hint-footer {
  flex-shrink: 0;
  display: none;          /* shown only when gamepad is active driver */
  padding: 4px 16px;
  font-size: 9px;
  color: var(--green);
  letter-spacing: 1.5px;
  opacity: .7;
  border-top: 1px solid var(--green-dim);
  background: rgba(10,14,42,.6);
  z-index: 1;
  gap: 16px;
  align-items: center;
  flex-wrap: wrap;
}
.hint-footer {
  display: none;
}

/* ── ROGUELITE PICKER ────────────────────────────────────────────────────── */
.roguelite-overlay {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: none;      /* toggled by JS */
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* R2.1.2 — Fully opaque (was 0.88) so the 3D scene doesn't bleed through. */
  background: var(--void);
  color: var(--green);
  font-family: 'Courier New', Courier, monospace;
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: env(safe-area-inset-top,0) env(safe-area-inset-right,0)
           env(safe-area-inset-bottom,0) env(safe-area-inset-left,0);
}
.rp-header {
  text-align: center;
  margin-bottom: 20px;
}
.rp-title {
  font-size: 22px;
  color: var(--amber);
  letter-spacing: 6px;
  margin-bottom: 4px;
  text-shadow: 0 0 12px var(--amber-dim);
}
.rp-sub {
  font-size: 11px;
  color: var(--green);
  letter-spacing: 3px;
  opacity: .6;
}
.rp-cards {
  display: flex;
  gap: 16px;
  padding: 0 24px;
  flex-wrap: wrap;
  justify-content: center;
  max-width: 900px;
  width: 100%;
}
.rp-card {
  flex: 1;
  min-width: 220px;
  max-width: 280px;
  padding: 18px 16px;
  background: rgba(10,14,42,.96);
  border-radius: 2px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  cursor: pointer;
  transition: border-color .12s, box-shadow .12s;
}
.rp-card:hover, .rp-card.ui-focused {
  box-shadow: 0 0 14px 2px var(--amber-dim);
}
.rp-rarity {
  font-size: 9px;
  letter-spacing: 3px;
  opacity: .8;
}
.rp-name {
  font-size: 15px;
  color: var(--amber);
  letter-spacing: 2px;
}
.rp-desc {
  font-size: 10px;
  color: var(--green);
  line-height: 1.5;
  letter-spacing: 1px;
  opacity: .8;
  text-transform: none;
}
.rp-mods {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: 4px;
}
.rp-mod-row {
  display: flex;
  justify-content: space-between;
  font-size: 9px;
  letter-spacing: 1px;
}
.rp-mod-key { color: var(--green); opacity: .7; }
.rp-mod-val { font-weight: bold; }
.rp-mod-val.pos { color: var(--green); }
.rp-mod-val.neg { color: var(--red); }
.rp-synergy {
  color: var(--amber);
  opacity: .7;
  font-size: 8px;
  justify-content: flex-start;
  gap: 4px;
}
.rp-select-btn {
  margin-top: auto;
  width: 100%;
  min-height: 44px;
  font-size: 11px;
  letter-spacing: 2px;
}
.rp-hint {
  margin-top: 16px;
  font-size: 9px;
  letter-spacing: 2px;
  color: var(--green);
  opacity: .5;
}

/* ── Loom Boons veiled card (WF-2 — ui/strike/boon-picker.js reuses the rp-* rules above) ── */
.rp-card.veiled {
  border-color: #c08cff;
  border-style: dashed;
  background: rgba(30, 12, 46, .96);
}
.rp-mystery-glyph {
  font-size: 30px;
  text-align: center;
  letter-spacing: 6px;
  color: #c08cff;
  text-shadow: 0 0 14px rgba(192, 140, 255, .6);
  margin: 4px 0;
}

/* ── Procedural slot icons (icons.js / item 37) ──────────────────────────── */
.slot-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  display: inline-block;
  vertical-align: middle;
}
.cell-icon { width: 14px; height: 14px; }
.gear-slot-glyph { width: 18px; height: 18px; }
.gear-slot-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 2px;
}
.gear-item-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 2px;
  min-width: 0;
}
.gear-item-head .cell-name { margin-bottom: 0; flex: 1; min-width: 0; }

/* ── Vault inline stat readout (item 11 / vault-organizer §1) ─────────────── */
.cell-stats {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 4px 0 2px;
}
.cell-stat-row {
  display: flex;
  align-items: center;
  gap: 4px;
}
.cell-stat-key {
  font-size: 7px;
  letter-spacing: .5px;
  color: var(--amber);
  opacity: .8;
  width: 24px;
  flex-shrink: 0;
}
.cell-stat-bar {
  flex: 1;
  height: 5px;
  border: 1px solid var(--green-dim);
  background: rgba(51,255,102,.04);
  overflow: hidden;
}
.cell-stat-fill {
  height: 100%;
  width: 0%;
  background: var(--green);
}
.cell-stat-val {
  font-size: 7px;
  color: var(--green);
  width: 30px;
  text-align: right;
  flex-shrink: 0;
  white-space: nowrap;
}

/* ── Vault sort selector (organizer v1) ──────────────────────────────────── */
.vault-sort {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
}
.vault-sort-label {
  font-size: 9px;
  color: var(--amber);
  letter-spacing: 2px;
  opacity: .7;
}
.vault-sort-select {
  background: rgba(10,14,42,.9);
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 9px;
  letter-spacing: 1px;
  padding: 5px 6px;
  min-height: 32px;
  cursor: pointer;
}
.vault-sort-select:focus { outline: 1px solid var(--amber); }

/* ── Locked-item component (item 35 / progression §3b) ───────────────────── */
/* Shared affordance: 40% opacity + lock glyph + resolved requirement string.
   Applied to abilities, aspect chips, and gear cells alike. */
.locked-item,
.ab-locked {
  opacity: .4;
  cursor: default;
}
.locked-req {
  display: flex;
  align-items: flex-start;
  gap: 4px;
  margin-top: 5px;
  font-size: 8px;
  letter-spacing: .5px;
}
.lock-glyph {
  font-size: 9px;
  line-height: 1.2;
  flex-shrink: 0;
  filter: grayscale(1);
}
.lock-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.lock-text strong {
  color: var(--amber);
  letter-spacing: 1px;
}
.lock-detail {
  color: var(--green);
  opacity: .7;
  text-transform: none;
  line-height: 1.3;
}

/* ── MANAGE LOADOUT control on the roguelite picker (item 34) ─────────────── */
.rp-manage-btn {
  margin-top: 18px;
  font-size: 11px;
  letter-spacing: 2px;
  padding: 10px 20px;
  min-height: 44px;
  background: rgba(51,255,102,.06);
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.rp-manage-btn:hover, .rp-manage-btn:active {
  background: var(--amber-dim);
  border-color: var(--amber);
  color: var(--amber);
}

/* ── Responsive overrides ────────────────────────────────────────────────── */
@media (max-width: 600px) {
  .gear-slot-list  { width: 140px; min-width: 120px; }
  .gear-diag       { width: 140px; min-width: 120px; }
  .ab-picker-card  { width: 100%; min-width: 0; }
  .rp-cards        { gap: 10px; padding: 0 10px; }
  .rp-card         { min-width: 160px; padding: 12px 10px; }
  .lo-tab          { padding: 10px 12px; font-size: 11px; }
  .lo-title        { font-size: 14px; }

  /* Header overflow fix: at ~393px wide the title + MAIN MENU + COMMENCE add up
     to ~449px and don't wrap, so the overlay grew wider than the viewport and
     the focused COMMENCE button auto-scrolled it — shifting the ENTIRE overlay
     (header, tabs, table) sideways. Let the header wrap and shrink the actions
     so everything fits within the viewport width. */
  .lo-header         { flex-wrap: wrap; gap: 8px 10px; padding: 8px 12px; }
  /* Title takes its own row so it can't get squeezed to ~40px and overflow on
     top of the MAIN MENU / COMMENCE buttons (which wrap to the row below). */
  .lo-title-group    { flex-basis: 100%; }
  .lo-title          { letter-spacing: 2px; }
  .lo-subtitle       { font-size: 9px; letter-spacing: 1px; }
  .lo-main-menu-btn  { font-size: 11px; letter-spacing: 1px; padding: 8px 12px; }
  .lo-commence-btn   { font-size: 12px; letter-spacing: 2px; padding: 10px 16px; }

  /* The 9-cell loadout strip (9×36 + gaps + padding ≈ 404px) also nudged past
     393px. Shrink the cells + gutters so the single glyph row fits without
     pushing the overlay wide. */
  .lo-strip          { padding: 8px 10px; gap: 4px; }
  .lo-strip-cell     { min-width: 30px; padding: 5px; }
  .lo-strip-icon     { width: 20px; height: 20px; }
}

/* B4 (ui-scale-responsive) — effective-width twin of the header-wrap rules
   above (C1 class from main.js: eff-w-le-720). Raw max-width:600 never fires
   under UI SCALE zoom — e.g. 844×390 @1.45 is effW≈582, real width 844 — so
   the header never wrapped and .lo-title-group collapsed under the 3 header
   buttons (MAIN MENU + SETTINGS + COMMENCE BULWARK; one more than when the
   raw rule above was written for 2). Re-derived here rather than widening the
   raw query so scale-1.0 desktop behavior at real widths 601–720 is untouched. */
:root.eff-w-le-720 .lo-header        { flex-wrap: wrap; gap: 8px 10px; padding: 8px 12px; }
:root.eff-w-le-720 .lo-title-group   { flex-basis: 100%; }
:root.eff-w-le-720 .lo-title         { font-size: 14px; letter-spacing: 2px; }
:root.eff-w-le-720 .lo-subtitle      { font-size: 9px; letter-spacing: 1px; }
:root.eff-w-le-720 .lo-main-menu-btn { font-size: 11px; letter-spacing: 1px; padding: 8px 12px; }
:root.eff-w-le-720 .lo-commence-btn  { font-size: 12px; letter-spacing: 2px; padding: 10px 16px; }

/* ── Short-height landscape (iPhone 15 landscape ≈ 852×393) ──────────────────
   The Mission Control header + strip + tab bar eat the whole 393px budget,
   leaving no room for the active panel. Compress all three chrome rows so the
   panel host keeps usable, scrollable height. */
@media (max-height: 480px) {
  .lo-header { padding: 6px 16px; gap: 12px; }
  .lo-title { font-size: 14px; letter-spacing: 3px; }
  .lo-subtitle { font-size: 9px; letter-spacing: 2px; }
  .lo-strip { padding: 4px 12px; gap: 5px; }
  .lo-strip-cell { min-height: 34px; padding: 4px 8px; }
  /* Tabs compact on a landscape phone to leave room for the lifted control bar
     (drill pills + sort + search) on the right of this same row. */
  .lo-tab { padding: 8px 9px; min-height: 40px; font-size: 11px; letter-spacing: 1px; }
  /* Panel host fills the remaining space and scrolls rather than clipping. */
  .lo-panel { overflow-y: auto; }
  /* NOTE: the VAULT diag-strip + filter compaction lives in a LATER
     @media (max-height:480px) block (after those classes are defined) — putting
     it here would lose to the base rules, which are defined further down the
     file (media queries add no specificity; source order decides ties). */
}

/* Short-height landscape — roguelite between-wave picker. The 3 cards must fit
   without scrolling: shrink the header, tighten card padding, cap card height
   and let the desc scroll inside if a roll is verbose. */
@media (max-height: 480px) {
  .roguelite-overlay { justify-content: flex-start; padding-top: max(env(safe-area-inset-top,0), 10px); }
  .rp-header { margin-bottom: 10px; }
  .rp-title { font-size: 16px; letter-spacing: 4px; }
  .rp-sub { font-size: 9px; letter-spacing: 2px; }
  .rp-cards { gap: 12px; padding: 0 16px; }
  .rp-card { min-width: 180px; padding: 10px 12px; gap: 5px; max-height: 78vh; overflow-y: auto; }
  .rp-name { font-size: 13px; }
  .rp-desc { font-size: 9px; line-height: 1.35; }
  .rp-select-btn { min-height: 44px; font-size: 11px; }
  .rp-manage-btn { margin-top: 10px; min-height: 44px; }
  .rp-hint { margin-top: 8px; }
}

/* Narrow portrait: don't hide the slots + diagnostics (that left an empty void).
   Stack the gear panel vertically — slots become a horizontal scroll strip, the
   diagnostics read out below them, and the item grid fills the rest. */
@media (max-width: 400px) {
  .gear-panel { flex-direction: column; }
  .gear-slot-list {
    flex-direction: row;
    width: 100%;
    min-width: 0;
    border-right: none;
    border-bottom: 1px solid var(--green-dim);
    overflow-x: auto;
    overflow-y: hidden;
    padding: 8px;
    gap: 6px;
  }
  .gear-slot-cell { min-width: 130px; flex-shrink: 0; }
  .gear-diag {
    width: 100%;
    min-width: 0;
    border-right: none;
    border-bottom: 1px solid var(--green-dim);
    max-height: 130px;
  }
  .gear-item-grid { padding: 8px; }
}

/* ── Reduced motion ──────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .cell, .lo-tab, .lo-commence-btn, .diag-fill, .vault-filter-btn,
  .rp-card, .lo-toast {
    transition: none;
    animation: none;
  }
}

/* ============================================================================
   ARSENAL ORGANIZER (R2.1) — sortable / filterable / searchable gear table.
   Used by both the GEAR tab and the VAULT tab. All rules below live under the
   .organizer-* and .diag-strip-* prefixes; no existing rules are modified.
   See docs/arsenal-organizer.md.
   ========================================================================== */

/* Organizer-hosting panel: column flex, the diag strip stickies inside it. */
.organizer-panel {
  flex-direction: column;
  display: flex;
  overflow: hidden;
  height: 100%;
  padding: 0;
}

/* Container for the whole organizer (chips → table → action bar). */
.organizer {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
}

/* ── Filter chips + search ───────────────────────────────────────────────── */
.organizer-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--green-dim);
  flex-shrink: 0;
  align-items: center;
}
.organizer-chip {
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 6px 12px;
  cursor: pointer;
  min-height: 36px;
  min-width: 44px;
  text-transform: uppercase;
  transition: background .1s, color .1s, border-color .1s;
}
.organizer-chip:hover,
.organizer-chip.active {
  background: var(--amber-dim);
  color: var(--amber);
  border-color: var(--amber);
}

.organizer-search {
  margin-left: auto;
  flex: 1;
  min-width: 140px;
  max-width: 280px;
}
.organizer-search-input {
  width: 100%;
  background: rgba(10, 14, 42, .9);
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 1px;
  padding: 8px 10px;
  min-height: 36px;
  outline: none;
  box-sizing: border-box;
}
.organizer-search-input:focus { border-color: var(--amber); }
.organizer-search-input::placeholder { color: var(--green); opacity: .5; }

/* ── Table ───────────────────────────────────────────────────────────────── */
.organizer-table-wrap {
  flex: 1;
  overflow: auto;
  min-height: 0;
}
.organizer-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: auto;
}
.organizer-th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: rgba(10, 14, 42, .96);
  color: var(--amber);
  font-size: 9px;
  letter-spacing: 2px;
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--green-dim);
  white-space: nowrap;
}
.organizer-th-sortable { cursor: pointer; user-select: none; }
.organizer-th-sortable:hover { color: var(--cream); }
.organizer-th-active .organizer-th-label,
.organizer-th-active .organizer-th-arrow { color: var(--cream); }
.organizer-th-check { width: 36px; }
.organizer-th-arrow { font-size: 8px; opacity: .8; }

.organizer-row {
  border-bottom: 1px solid rgba(51, 255, 102, .08);
  min-height: 44px;
  transition: background .1s;
}
.organizer-row:hover { background: rgba(255, 176, 0, .04); }
.organizer-row-equipped { background: rgba(51, 255, 102, .06); }
.organizer-row-selected { background: rgba(255, 176, 0, .12); }
.organizer-row-equipped.organizer-row-selected { background: rgba(255, 176, 0, .14); }

.organizer-td {
  padding: 8px 10px;
  font-size: 10px;
  color: var(--green);
  vertical-align: middle;
  letter-spacing: .8px;
}
.organizer-td-check { width: 36px; }
.organizer-td-icon { width: 28px; }
.organizer-td-rarity,
.organizer-td-slot,
.organizer-td-element { white-space: nowrap; }
/* The portrait "card" cell is hidden in the default table view; portrait phones
   flip it on and hide the rest (see the portrait card block below). */
.organizer-th[data-col-key="card"],
.organizer-td-card { display: none; }

/* menus-refit-spec.md §F — the WEAPONS/ARMOR split (vault.js `category` param)
   means each tab's `_columns()` only ever BUILDS the columns relevant to it —
   the always-empty-column CSS trim that used to live here (`[data-cat]`
   header/cell hiding) is gone; there is nothing left to hide. */

/* ── WEAPONS/ARMOR drill-down control bar (playtest R; §F) ─────────────────
   "Controls the table below": PRIMARY/SECONDARY/ELEMENT/STATUS (weapons) or
   HELMET/CHEST/LEGS/STATUS (armor) → ‹BACK + children.
   On wide screens it + the search lift into the tab bar's right side (the flat
   chip row disappears); on portrait they sit in a control row atop the panel. */
.vault-controls { display: flex; align-items: center; gap: 8px; min-width: 0; }
.vault-drill {
  display: flex; align-items: center; gap: 4px; flex-wrap: nowrap; min-width: 0;
  /* The root now carries every filter axis (…RARITY · MODE · STATS ≥ · STATUS),
     which can outrun the bar on the wide-but-not-compact tier. nowrap stays —
     pills must not stack into a second row — so the overflow scrolls instead of
     clipping. Scrollbar hidden: the pills themselves are the affordance. */
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.vault-drill::-webkit-scrollbar { display: none; }
.vault-pill {
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 7px 12px;
  min-height: 36px;
  white-space: nowrap;
  cursor: pointer;
  transition: background .1s, color .1s, border-color .1s;
}
.vault-pill:hover { border-color: var(--amber); color: var(--amber); }
.vault-pill-cat  { border-color: var(--amber-dim); color: var(--amber); letter-spacing: 2px; }
.vault-pill-back { color: var(--green); opacity: .85; }
.vault-pill-leaf.active {
  background: var(--amber-dim);
  border-color: var(--amber);
  color: var(--amber);
}
/* Inline STATS sort pills (third drill tier under a weapon slot). Neutral green
   at rest to read as a sort control (not a filter); active axis fills amber. */
.vault-pill-stat { border-style: dashed; }
.vault-pill-stat.active {
  background: var(--amber-dim);
  border-style: solid;
  border-color: var(--amber);
  color: var(--amber);
}

/* ── Collapsed FILTER unit (wide-compact tier, ui-scale-responsive B1/B2) ───
   Same look as a .vault-pill (it stands in for the whole drill row when the
   tab bar can't fit the flat drill-pill row — PRIMARY·SECONDARY·ELEMENT·STATUS
   on WEAPONS, HELMET·CHEST·LEGS·STATUS on ARMOR); the popover below mirrors
   the SORT popover's shape exactly. */
.vault-filter { position: relative; flex: 0 0 auto; min-width: 0; }
.vault-filter-btn {
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 7px 12px;
  min-height: 36px;
  white-space: nowrap;
  cursor: pointer;
  transition: background .1s, color .1s, border-color .1s;
}
.vault-filter-btn:hover { border-color: var(--amber); color: var(--amber); }
.vault-filter-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 140px;
  max-width: min(220px, calc(100vw - 24px));
  padding: 6px;
  background: rgba(10, 14, 42, .98);
  border: 1px solid var(--green-dim);
  box-shadow: 0 6px 24px rgba(0, 0, 0, .5);
}
.vault-filter-opt {
  background: none; border: 1px solid transparent;
  color: var(--green); font-family: inherit; font-size: 11px; letter-spacing: 1px;
  text-align: left; padding: 7px 10px; min-height: 36px; cursor: pointer;
}
.vault-filter-opt:hover { background: rgba(51, 255, 102, .08); }
.vault-filter-opt.active {
  background: var(--amber-dim);
  border-color: var(--amber);
  color: var(--amber);
}
.vault-filter-back { color: var(--green); opacity: .85; }

/* SORT control + popover. */
/* SORT is a different KIND of control from the (green) filter pills — give it a
   distinct cyan identity (≠ green filters, ≠ amber active-filter) so it never
   reads as a filter. */
.vault-sort { position: relative; flex: 0 0 auto; }
.vault-sort-btn {
  background: rgba(79, 214, 255, .06);
  border: 1px solid var(--sort-accent-dim);
  color: var(--sort-accent);
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 7px 12px;
  min-height: 36px;
  white-space: nowrap;
  cursor: pointer;
}
.vault-sort-btn:hover { border-color: var(--sort-accent); background: rgba(79, 214, 255, .12); }
.vault-sort-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 140px;
  padding: 6px;
  background: rgba(10, 14, 42, .98);
  border: 1px solid var(--sort-accent-dim);
  box-shadow: 0 6px 24px rgba(0, 0, 0, .5);
  /* SORT now offers every sortable column (perks + element + archetype + …),
     so the menu can outgrow a phone screen — cap it and scroll instead of
     running off the viewport. */
  max-height: min(60vh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.vault-sort-dir {
  background: rgba(79, 214, 255, .08);
  border: 1px solid var(--sort-accent-dim);
  color: var(--sort-accent);
  font-family: inherit; font-size: 10px; letter-spacing: 1.5px;
  padding: 7px 8px; min-height: 36px; cursor: pointer; margin-bottom: 4px;
}
.vault-sort-opt {
  background: none; border: 1px solid transparent;
  color: var(--green); font-family: inherit; font-size: 11px; letter-spacing: 1px;
  text-align: left; padding: 7px 10px; min-height: 36px; cursor: pointer;
}
.vault-sort-opt:hover { background: rgba(79, 214, 255, .08); }
.vault-sort-opt.active { color: var(--sort-accent); border-color: var(--sort-accent-dim); background: rgba(79, 214, 255, .08); }

/* Placement — wide: in the tab bar's right side. */
.lo-tabbar {
  align-items: center;
  /* B1 belt-and-braces — if tabs + controls + search ever add up to more than
     the tab bar's real width (any tier, any device), scroll rather than
     overlap. Costs nothing when everything fits (no overflow, no scrollbar). */
  overflow-x: auto;
  scrollbar-width: none;
}
.lo-tabbar::-webkit-scrollbar { display: none; }
.lo-tabbar .vault-controls { margin-left: auto; gap: 5px; }
.lo-tabbar .vault-drill { gap: 3px; }
/* VIEW + SEARCH cluster — sit together after FILTER+SORT. */
.lo-tabbar .vault-view-toggle { flex: 0 0 auto; margin-left: 4px; }
.lo-tabbar .organizer-search { flex: 0 1 150px; max-width: 150px; min-width: 96px; margin-left: 2px; }
/* Compact the lifted controls hard so tabs + pills + sort + search fit one row
   on a landscape phone (≈851px). */
.lo-tabbar .vault-pill,
.lo-tabbar .vault-sort-btn,
.lo-tabbar .vault-filter-btn,
.lo-tabbar .vault-view-btn { font-size: 9px; letter-spacing: .5px; padding: 5px 7px; min-height: 32px; }
/* Nothing in the lifted row shrinks below its own content — belt-and-braces
   overflow-x above kicks in instead of squeezing pills/search illegible. */
.lo-tab, .lo-tabbar .vault-controls, .lo-tabbar .vault-view-toggle, .lo-tabbar .organizer-search { flex-shrink: 0; }

/* wide-compact tier (B1/B2) — vault.js toggles this class via setControlsCompact()
   on both controlBar and viewToggleEl. Icon-only CARD/LIST. */
.vault-controls-compact.vault-view-toggle .vault-view-label,
.vault-controls-compact .vault-view-label { display: none; }
.vault-controls-compact.vault-view-toggle .vault-view-btn,
.vault-controls-compact .vault-view-btn { padding: 6px 8px; min-width: 32px; text-align: center; }

/* Placement — portrait: FILTER+SORT on one row; VIEW+SEARCH on the next. */
.vault-controls-host {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 8px 12px; border-bottom: 1px solid var(--green-dim); flex-shrink: 0;
}
.vault-controls-host:empty { display: none; }
.vault-controls-host .vault-controls { flex: 1 1 100%; flex-wrap: nowrap; gap: 6px; align-items: stretch; min-width: 0; }
.vault-controls-host .vault-drill { flex: 1 1 auto; min-width: 0; overflow-x: auto; }
.vault-controls-host .vault-filter,
.vault-controls-host .vault-sort { flex: 0 0 auto; }
.vault-controls-host .vault-pill,
.vault-controls-host .vault-sort-btn,
.vault-controls-host .vault-filter-btn { font-size: 10px; letter-spacing: .5px; padding: 6px 8px; min-height: 34px; }
.vault-controls-host .vault-view-toggle { flex: 0 0 auto; }
.vault-controls-host .organizer-search { flex: 1 1 auto; min-width: 120px; max-width: none; }

.organizer-empty {
  text-align: center;
  color: var(--green-dim);
  font-size: 11px;
  letter-spacing: 2px;
  padding: 24px;
}

/* ── Cell content ────────────────────────────────────────────────────────── */
.organizer-icon { display: inline-flex; align-items: center; }
.organizer-icon-svg { width: 18px; height: 18px; }

.organizer-name {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}
.organizer-name-text {
  font-size: 11px;
  letter-spacing: 1.2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}
.organizer-name-fav { color: var(--amber); font-size: 10px; }

.organizer-rarity {
  font-size: 10px;
  font-weight: bold;
  letter-spacing: 1.5px;
}
.organizer-elem {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.organizer-elem-text {
  font-size: 9px;
  color: var(--green);
  opacity: .8;
  letter-spacing: 1px;
}

.organizer-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 3px 4px;
  max-width: 320px;
}
.organizer-stat-pill {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  border: 1px solid var(--green-dim);
  padding: 2px 5px;
  font-size: 8px;
  letter-spacing: .5px;
  background: rgba(51, 255, 102, .04);
}
.organizer-stat-key { color: var(--amber); opacity: .85; }
.organizer-stat-val { color: var(--green); font-weight: bold; }
/* R2.1 — per-stat columns: missing values render as a muted dash. */
.organizer-stat-val.organizer-stat-empty { color: var(--green-dim); font-weight: normal; }

/* LEFT / RIGHT perk columns (weapon-perks-spec §1). Each cell is one rolled
   perk; list view shows the name only (sep+desc hidden below). */
.organizer-td-perkLeft,
.organizer-td-perkRight { min-width: 110px; max-width: 200px; }
.organizer-archetype {
  font-size: 9px;
  letter-spacing: 1px;
  color: var(--green);
  white-space: nowrap;
  text-transform: uppercase;
}
.organizer-perk {
  display: flex;
  flex-direction: column;
  gap: 4px;
  line-height: 1.3;
  white-space: normal;
}
.organizer-perk-row + .organizer-perk-row { margin-top: 2px; }
.organizer-perk-name {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--amber);
  text-transform: uppercase;
}
.organizer-perk-desc {
  font-size: 9px;
  font-weight: 400;
  color: var(--green);
  opacity: .8;
}
.organizer-perk-placeholder {
  font-size: 9px;
  letter-spacing: 1px;
  color: var(--green-dim);
  font-style: italic;
}
/* B4 — amber-bordered chip on weapons that actually carry a perk. The border
   + tinted background lifts the row above an unperked weapon at thumbnail
   scale (phone vault scan). */
.organizer-perk.organizer-perk-chip {
  border: 1px solid var(--amber);
  border-radius: 2px;
  padding: 4px 6px;
  background: rgba(255, 184, 77, .06);
}

.organizer-equip-btn {
  background: rgba(51, 255, 102, .08);
  border: 1px solid var(--green);
  color: var(--green);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 6px 14px;
  min-height: 36px;
  cursor: pointer;
  transition: background .1s, color .1s;
}
.organizer-equip-btn:hover {
  background: var(--green);
  color: var(--void);
}
.organizer-equipped-tag {
  font-size: 9px;
  letter-spacing: 1.5px;
  color: var(--green);
  border: 1px solid var(--green);
  padding: 4px 8px;
  white-space: nowrap;
}

.organizer-more-btn {
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--amber);
  font-family: inherit;
  font-size: 14px;
  padding: 4px 8px;
  min-height: 36px;
  min-width: 36px;
  cursor: pointer;
  transition: background .1s;
}
.organizer-more-btn:hover {
  background: var(--amber-dim);
  border-color: var(--amber);
}

/* ── Bulk action bar ─────────────────────────────────────────────────────── */
.organizer-action-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-top: 1px solid var(--amber);
  background: rgba(255, 176, 0, .08);
  flex-shrink: 0;
}
.organizer-action-count {
  font-size: 11px;
  letter-spacing: 2px;
  color: var(--amber);
  font-weight: bold;
  flex: 1;
}
.organizer-action-btn {
  background: none;
  border: 1px solid var(--green);
  color: var(--green);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 8px 14px;
  min-height: 44px;
  cursor: pointer;
  transition: background .1s, color .1s;
}
.organizer-action-btn:hover {
  background: var(--green);
  color: var(--void);
}
.organizer-action-dismantle {
  border-color: rgba(255, 90, 77, .6);
  color: var(--red);
}
.organizer-action-dismantle:hover {
  background: var(--red);
  color: var(--void);
}
.organizer-action-clear {
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 6px 12px;
  min-height: 44px;
  cursor: pointer;
  opacity: .7;
}
.organizer-action-clear:hover { opacity: 1; }

/* Row checkboxes — bigger than browser default for touch, but de-emphasised
 * so they don't fight the green/amber palette for attention. Custom box on
 * top of an invisibility-cloaked native input keeps a/11y semantics intact. */
.organizer-check {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  cursor: pointer;
  margin: 0;
  border: 1px solid var(--green-dim);
  background: rgba(51, 255, 102, 0.04);
  border-radius: 2px;
  position: relative;
  flex-shrink: 0;
  opacity: 0.55;
  transition: opacity .12s, border-color .12s, background .12s;
}
.organizer-check:hover { opacity: 0.9; border-color: var(--green); }
.organizer-check:checked {
  background: rgba(255, 176, 0, 0.18);
  border-color: var(--amber);
  opacity: 1;
}
.organizer-check:checked::after {
  content: '✓';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--amber);
  font-size: 12px;
  line-height: 1;
}
.organizer-check:focus-visible { outline: 1px solid var(--amber); outline-offset: 1px; }

/* ── Sticky diagnostic strip (lives at top of GEAR organizer panel) ──────── */
.diag-strip {
  position: sticky;
  top: 0;
  z-index: 3;
  background: rgba(10, 14, 42, .96);
  border-bottom: 1px solid var(--green-dim);
  padding: 8px 14px;
  flex-shrink: 0;
}
.diag-strip-title {
  color: var(--amber);
  font-size: 9px;
  letter-spacing: 3px;
  margin-bottom: 6px;
  opacity: .85;
}
.diag-strip-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 4px 12px;
}
.diag-strip-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.diag-strip-label {
  font-size: 8px;
  letter-spacing: 1.2px;
  color: var(--green);
  width: 62px;
  flex-shrink: 0;
  white-space: nowrap;
}
.diag-strip-track {
  flex: 1;
  height: 8px;
  border: 1px solid var(--green-dim);
  background: rgba(51, 255, 102, .04);
  overflow: hidden;
  min-width: 40px;
}
.diag-strip-fill {
  height: 100%;
  width: 0%;
  background: var(--green);
  transition: width .18s ease;
}
.diag-strip-val {
  font-size: 9px;
  color: var(--amber);
  width: 42px;
  text-align: right;
  flex-shrink: 0;
}

/* ── EQUIPPED tab (playtest R) ─────────────────────────────────────────────
   Default build screen: diag readout (above) + gear/ability/class tiles. Each
   tile is a tap target that deep-links to VAULT (gear) or ABILITIES. Grid auto-
   fits: ~3 wide on landscape, 1–2 on a phone. */
.equipped-panel {
  flex-direction: column;
  overflow-y: auto;
  padding: 0 0 16px;
  gap: 0;
}
.lo-eq-head {
  color: var(--amber);
  font-size: 12px;
  letter-spacing: 4px;
  opacity: .9;
  padding: 10px 16px 5px;
}
/* Header row that carries a trailing secondary action (COPY BUILD LINK) — the
   label stays left, the action sits quietly at the right edge. */
.lo-eq-head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.lo-eq-head-left {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.lo-eq-head-bind {
  /* Compact chip on the CLASS heading — not a full bind column above a card. */
  align-self: center;
  padding: 2px 7px;
  font-size: 9px;
}
/* Relocated share action (was in the header CTA cluster next to COMMENCE). Keep
   it visually subdued so it reads as secondary next to the build. Selector is
   scoped through .lo-eq-head-row to out-specify the runtime-injected
   .share-link-btn base style (share-link.js), which is appended after this
   sheet and would otherwise win at equal specificity. */
.lo-eq-head-row .lo-copy-build-link {
  flex: 0 0 auto;
  font-size: 9px;
  padding: 4px 10px;
  min-height: 26px;
  opacity: .7;
}
.lo-eq-head-row .lo-copy-build-link:hover { opacity: 1; }
/* Active-loadout strip (playtest 2026-07-21) — pinned above the diagnostic
   readout: names the saved loadout the worn build came from; MODIFIED flags
   drift since APPLY; tap opens that loadout's full build guide. */
.lo-eq-active-ld {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 12px 16px 0;
  padding: 8px 12px;
  background: rgba(51, 255, 102, 0.04);
  font: inherit;
  color: var(--green);
  text-align: left;
}
.lo-eq-active-ld-lbl {
  font-size: 9px;
  letter-spacing: 2px;
  opacity: 0.6;
}
.lo-eq-active-ld-name {
  font-size: 13px;
  letter-spacing: 2px;
  color: var(--amber);
}
.lo-eq-active-ld-slot {
  font-size: 9px;
  letter-spacing: 1.5px;
  padding: 2px 6px;
  border: 1px solid var(--green-dim);
  opacity: 0.8;
}
.lo-eq-active-ld-mod {
  font-size: 9px;
  letter-spacing: 1.5px;
  padding: 2px 6px;
  border: 1px solid var(--amber);
  color: var(--amber);
}
.lo-eq-active-ld-none .lo-eq-active-ld-name { color: var(--green); opacity: 0.7; }
/* Column layout (equip-screen-card-layout): the whole build reads at a glance,
   top-down, in paired/tripled columns — CLASS | class-ability, WEAPON 1 | 2,
   ABILITY 1 | 2, ARMOR ×3 (in thirds). The cards are the SAME unified card
   (ui/shared/card.js) shrunk to fit the columns via the .lo-eq-compact scope
   below — the shared card CSS is untouched. Empty slots (the compact tile) ride
   along in the same grid cell. */
.lo-eq-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  padding: 0 16px;
}
/* Landscape / desktop default: paired rows (CLASS | class-ability, WEAPON 1 |
   WEAPON 2, ABILITY 1 | ABILITY 2) two-up, ARMOR in thirds — so a wide screen
   packs the build up to three columns across. minmax(0,1fr) lets cards shrink
   below their content width (ellipsis) instead of forcing a horizontal overflow. */
.lo-eq-weapons,
.lo-eq-abilities { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* CLASS is a triple now — class | class ability | intrinsic (equip-intrinsic-perks). */
.lo-eq-class,
.lo-eq-armor { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* Breakpoints use the zoom-aware effective-width classes main.js stamps on
   <html> (eff-w-le-*, docs/ui-scale-vault-view.md), NOT raw @media — the loadout
   overlay is `zoom`-scaled, so raw widths would be wrong by the UI-scale factor.
   Tablet / phone-landscape narrowing: ARMOR drops to two-up. */
:root.eff-w-le-720 .lo-eq-class,
:root.eff-w-le-720 .lo-eq-armor { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Mobile portrait: every card goes FULL WIDTH (single column) — easiest to read
   on a phone. Phone-landscape (eff width > 600) keeps the paired / thirds columns. */
:root.eff-w-le-600 .lo-eq-weapons,
:root.eff-w-le-600 .lo-eq-abilities,
:root.eff-w-le-600 .lo-eq-class,
:root.eff-w-le-600 .lo-eq-armor { grid-template-columns: minmax(0, 1fr); }
.lo-eq-tile {
  display: flex;
  align-items: center;
  gap: 16px;
  text-align: left;
  padding: 16px 18px;
  min-height: 104px;
  background: rgba(51, 255, 102, .04);
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.lo-eq-tile:hover,
.lo-eq-tile:focus-visible { border-color: var(--amber); background: rgba(255, 176, 0, .08); outline: none; }
.lo-eq-empty { opacity: .55; }

/* A worn EQUIPPED slot IS the full unified card (ui/shared/card.js) promoted
   to a `.lo-eq-tile` nav cell — an <article class="fc"> now, not a <button>.
   `.lo-eq-tile`/`.cell` predate the card and set conflicting flex/border/
   background/padding at equal CSS specificity to `.fc` (card.css loads first
   in index.html, so those single-class rules here would otherwise win the
   cascade and squash the card's own flex-column layout — see card.css's `.fc`
   block, mirrored below). The two-class selector reasserts the card's own
   look so it always wins, then layers the tap/focus affordance on top. Same
   treatment for `.ab-picker-card` (the ABILITIES drawer). */
.lo-eq-tile.fc,
.ab-picker-card.fc {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  text-align: left;
  padding: 0;
  min-height: 0;
  width: 100%;
  background: linear-gradient(180deg, rgba(14, 20, 38, .92), rgba(8, 12, 26, .95));
  border: 1px solid color-mix(in srgb, var(--fc-rc) 55%, #2a3350);
  border-radius: 9px;
  color: inherit;
  font-family: inherit;
  /* cursor NOT set here — `.lo-eq-tile`/`.cell` already supply cursor:pointer
     at single-class specificity, which lets `.ab-locked` (also single-class,
     source-ordered after `.cell`) still win cursor:default on locked picker
     cards. Setting it here would out-specificity that lock treatment. */
}
.lo-eq-tile.fc:hover,
.lo-eq-tile.fc:focus-visible,
.lo-eq-tile.fc.ui-focused,
.ab-picker-card.fc:hover,
.ab-picker-card.fc:focus-visible {
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
}
/* "Tap to change" / 🔒 affordance — the card renders mode:'none' (no footer;
   a fav/junk/equip footer doesn't apply to a slot-summary card), so this row
   reuses `.fc-foot`'s padding/layout as the one dedicated action cue. */
.lo-eq-change-chip {
  font-size: 10.5px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--amber, #ffb000);
  opacity: .8;
}
/* ── Compact unified cards on the EQUIPPED tab (equip-screen-card-layout) ────
   The build now shows in 2/3 columns so the whole loadout is glance-able. The
   cards are the SAME ui/shared/card.js cards, shrunk HERE (scoped to the
   .lo-eq-compact panel) so nowhere else that uses the card is affected. Fonts,
   the icon column, glyphs, stats and perks all step down a notch; perk prose is
   clamped to a few lines so a weapon card in a half-width column stays short
   enough to read alongside its neighbour instead of towering over it. */
.lo-eq-compact .lo-eq-tile.fc { border-radius: 8px; }
.lo-eq-compact .lo-eq-tile.fc .fc-title,
.lo-eq-compact .lo-eq-tile.fc .fc-body,
.lo-eq-compact .lo-eq-tile.fc .fc-perks,
.lo-eq-compact .lo-eq-tile.fc .lo-eq-change-chip {
  padding-left: 13px; padding-right: 11px;
}
.lo-eq-compact .lo-eq-tile.fc .fc-title { padding-top: 11px; }
.lo-eq-compact .lo-eq-tile.fc .fc-eyebrow { font-size: 9px; letter-spacing: 1.6px; }
.lo-eq-compact .lo-eq-tile.fc .fc-name { font-size: clamp(14px, 3.2vw, 16px); letter-spacing: 1.2px; }
.lo-eq-compact .lo-eq-tile.fc .fc-rule { margin-top: 8px; }
.lo-eq-compact .lo-eq-tile.fc .fc-body { gap: 9px; padding-top: 10px; }
/* Weapons / abilities / class-ability cards carry the element+verb glyph column
   → 3-col body (icon | glyphs | stats). The icon column is sized near the class-
   hero clamp (icon-bigger pass) — the old 54px left it dwarfed by the space it
   could fill; the stats column (1fr) just slides over to make room. */
.lo-eq-compact .lo-eq-weapons .lo-eq-tile.fc .fc-body,
.lo-eq-compact .lo-eq-abilities .lo-eq-tile.fc .fc-body,
.lo-eq-compact .lo-eq-class .lo-eq-tile.fc .fc-body { grid-template-columns: clamp(88px, 21vw, 104px) auto 1fr; }
/* Armor cards have no glyph column — card.js sets a 2-col grid INLINE, so beat
   that inline width with a 2-col body (icon | stats) at the same bigger icon. */
.lo-eq-compact .lo-eq-armor .lo-eq-tile.fc .fc-body { grid-template-columns: clamp(88px, 21vw, 104px) 1fr !important; }
.lo-eq-compact .lo-eq-tile.fc .fc-glyphs { gap: 9px; }
.lo-eq-compact .lo-eq-tile.fc .fc-glyph > svg { width: 22px; height: 22px; }
.lo-eq-compact .lo-eq-tile.fc .fc-glyph-val { font-size: 8px; }
/* compact-inspect-cards — EQUIPPED gear/ability tiles are collapsed (names +
   perk chips); full prose lives in the item-sheet. Collapsed icons use the
   hero clamp so the glance band still reads. */
.lo-eq-compact .lo-eq-tile.fc-collapsed .fc-icon { width: clamp(74px, 15vw, 108px); }
.lo-eq-compact .lo-eq-tile.fc-collapsed .fc-glyph > svg { width: 30px; height: 30px; }
.lo-eq-compact .lo-eq-tile.fc .fc-stats { gap: 6px; padding-left: 9px; }
.lo-eq-compact .lo-eq-tile.fc .fc-stat { grid-template-columns: 44px 1fr auto; gap: 7px; }
.lo-eq-compact .lo-eq-tile.fc .fc-stat.fc-stat-chip { grid-template-columns: 44px 1fr; }
/* right-align the value so the numbers form a clean tabular column (units line up) */
.lo-eq-compact .lo-eq-tile.fc .fc-stat.fc-stat-chip .fc-stat-v { justify-self: end; text-align: right; }
.lo-eq-compact .lo-eq-tile.fc .fc-stat-k { font-size: 9.5px; letter-spacing: .8px; }
.lo-eq-compact .lo-eq-tile.fc .fc-stat-v { font-size: 12px; }
.lo-eq-compact .lo-eq-tile.fc .fc-stat.fc-stat-hi .fc-stat-v { font-size: 13px; }
.lo-eq-compact .lo-eq-tile.fc .fc-perks { gap: 6px; padding-top: 10px; }
.lo-eq-compact .lo-eq-tile.fc .fc-perk { padding: 7px 9px; }
.lo-eq-compact .lo-eq-tile.fc .fc-perk-tag { font-size: 8.5px; letter-spacing: 1.2px; }
.lo-eq-compact .lo-eq-tile.fc .fc-perk-name { font-size: 12px; letter-spacing: .8px; }
.lo-eq-compact .lo-eq-tile.fc .fc-perk-desc {
  font-size: 11px; line-height: 1.4;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
.lo-eq-compact .lo-eq-tile.fc .lo-eq-change-chip { font-size: 9px; letter-spacing: 1.4px; padding-top: 9px; padding-bottom: 11px; }

/* Compact empty tiles so they don't tower over the shrunk cards they share a
   row with. (The chassis tile no longer matches `:not(.fc)` padding-wise —
   it's a `.lo-eq-classhero` now, B3 below — but stays reachable by this rule's
   sibling `.lo-eq-classab-tile` empty state.) Glance tiles are excluded — they
   own their tighter sizing via `.lo-eq-glance` (dense card redesign 2026-07-16). */
.lo-eq-compact .lo-eq-tile:not(.fc):not(.lo-eq-glance) { min-height: 76px; padding: 12px 14px; gap: 11px; }
/* Keep the EMPTY glance tile (an `.lo-eq-tile.lo-eq-glance` with no card body,
   used for empty slots) at the dense card height, not the old 76px tower. */
.lo-eq-compact .lo-eq-tile.lo-eq-glance { min-height: 86px; padding: 10px 13px; gap: 10px; }
.lo-eq-compact .lo-eq-icon { width: 38px; height: 38px; }
.lo-eq-compact .lo-eq-name { font-size: 15px; }

.lo-eq-ability-tile { background: rgba(51, 255, 102, .06); }
.lo-eq-classab-tile { background: rgba(255, 176, 0, .06); border-color: var(--amber-dim); }
/* B3 (menus-refit-spec.md) — jump/passive/ult facts sit directly on the hero
   card root (no more `.lo-eq-body` wrapper), so they carry their own
   horizontal padding matching `.lo-eq-classhero-desc`'s (18px/20px) below. */
.lo-eq-class-details { display: flex; flex-direction: column; gap: 5px; padding: 0 18px 14px 20px; }
.lo-eq-class-detail { display: flex; gap: 8px; font-size: 11px; letter-spacing: .6px; }
.lo-eq-class-detail-k { color: var(--amber); opacity: .8; min-width: 58px; }
.lo-eq-class-detail-v { color: var(--green); opacity: .9; }

/* ── Class HERO cards (equip-screen-card-layout; B3 menus-refit-spec.md) ────
   Both the class-ability card AND the chassis tile share this block — the
   chassis was previously a flat dim box beside the ability's glowing hero
   (the screenshot asymmetry); it's now a visual sibling: a GIANT icon (element-
   tinted ability icon, or the planet glyph for chassis), name, and either a
   brief description (ability) or JUMP/PASSIVE/ULT facts (chassis), all under
   one element-keyed accent glow. The `.lo-eq-tile.lo-eq-classhero` compound
   out-specifies the base tile + compact rules so this card owns its own look;
   it keeps `.lo-eq-tile` only so the controller-nav grid (which queries
   `.lo-eq-tile`) still reaches it. */
.lo-eq-compact .lo-eq-tile.lo-eq-classhero {
  --hero-accent: #ffb000;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  text-align: left;
  padding: 0;
  min-height: 0;
  border: 1px solid color-mix(in srgb, var(--hero-accent) 60%, #2a3350);
  border-radius: 10px;
  color: inherit;
  background:
    radial-gradient(130% 90% at 16% 0%, color-mix(in srgb, var(--hero-accent) 24%, transparent), transparent 62%),
    linear-gradient(180deg, rgba(14, 20, 38, .92), rgba(8, 12, 26, .96));
  box-shadow: 0 0 30px -12px var(--hero-accent), 0 2px 0 rgba(0, 0, 0, .4);
  overflow: hidden;
}
.lo-eq-compact .lo-eq-tile.lo-eq-classhero:hover,
.lo-eq-compact .lo-eq-tile.lo-eq-classhero:focus-visible,
.lo-eq-compact .lo-eq-tile.lo-eq-classhero.ui-focused {
  outline: 2.5px solid var(--hero-accent);
  outline-offset: -2.5px;
  border-color: var(--hero-accent);
}
/* accent spine down the left edge (mirrors the unified card's rarity spine) */
.lo-eq-classhero::before {
  content: "";
  position: absolute; inset: 0 auto 0 0; width: 4px;
  background: var(--hero-accent);
}
.lo-eq-classhero-main {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 16px;
  align-items: center;
  padding: 16px 16px 10px 20px;
}
.lo-eq-classhero-icon {
  width: clamp(74px, 15vw, 108px);
  aspect-ratio: 1;
  flex-shrink: 0;
  border: 2px solid var(--hero-accent);
  border-radius: 12px;
  background: radial-gradient(120% 100% at 30% 20%, color-mix(in srgb, var(--hero-accent) 30%, transparent), rgba(5, 9, 22, .95) 78%);
  box-shadow: inset 0 0 0 4px rgba(6, 10, 26, .9), inset 0 0 26px rgba(0, 0, 0, .55);
  display: grid; place-items: center;
}
.lo-eq-classhero-icon > svg {
  width: 66%; height: 66%;
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--hero-accent) 55%, transparent))
          drop-shadow(1.5px 2px 0 rgba(0, 0, 0, .5));
}
/* B3 — the chassis hero's icon box holds a text glyph (the planet symbol,
   `.lo-eq-glyph`) instead of an SVG; re-tint it to the accent and match the
   ability icon's glow treatment so the two hero icons read as one family. */
.lo-eq-classhero-icon .lo-eq-glyph {
  color: var(--hero-accent);
  width: auto;
  font-size: 44px;
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--hero-accent) 55%, transparent))
          drop-shadow(1.5px 2px 0 rgba(0, 0, 0, .5));
}
.lo-eq-classhero-text { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.lo-eq-classhero-eyebrow {
  font-size: 9.5px; letter-spacing: 1.8px; text-transform: uppercase;
  color: var(--hero-accent); opacity: .92;
}
.lo-eq-classhero-name {
  font-size: clamp(19px, 4.4vw, 26px); letter-spacing: 1.5px; font-weight: 700;
  line-height: 1.04; color: var(--hero-accent);
  text-shadow: 0 0 12px color-mix(in srgb, var(--hero-accent) 45%, transparent);
}
.lo-eq-classhero-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.lo-eq-classhero-elem {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 10px; letter-spacing: 1px; color: var(--ink-dim, #a99fc7);
}
.lo-eq-classhero-desc {
  margin: 0;
  padding: 0 18px 12px 20px;
  font-size: 13px; line-height: 1.5; color: #cbd2ec;
}
.lo-eq-classhero .lo-eq-change-chip { padding: 8px 18px 13px 20px; }
.lo-eq-icon { width: 48px; height: 48px; flex-shrink: 0; }
.lo-eq-glyph { font-size: 46px; line-height: 1; color: var(--amber); flex-shrink: 0; width: 52px; text-align: center; }
.lo-eq-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.lo-eq-slot { font-size: 11px; letter-spacing: 2.5px; color: var(--amber); opacity: .8; }
.lo-eq-name {
  font-size: 18px;
  letter-spacing: 1px;
  color: var(--green);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.lo-eq-tag { font-size: 11px; letter-spacing: 1.5px; color: var(--amber); opacity: .85; }
.lo-eq-stats { display: flex; flex-wrap: wrap; gap: 5px 6px; margin-top: 4px; }
.lo-eq-stat {
  display: inline-flex;
  gap: 4px;
  border: 1px solid var(--green-dim);
  padding: 3px 7px;
  font-size: 11px;
  letter-spacing: .5px;
  background: rgba(51, 255, 102, .04);
}
.lo-eq-stat-k { color: var(--amber); opacity: .85; }
.lo-eq-stat-v { color: var(--green); font-weight: bold; }
.lo-eq-chev { color: var(--amber); opacity: .6; font-size: 26px; flex-shrink: 0; align-self: center; }

/* Rich EQUIPPED tiles (weapon perks / ability prose): the icon + chevron pin to
   the top so the growing body reads top-down instead of the icon floating in the
   vertical centre of a tall card. */
.lo-eq-tile-rich { align-items: flex-start; }
.lo-eq-tile-rich .lo-eq-icon,
.lo-eq-tile-rich .lo-eq-glyph { align-self: flex-start; }

/* Weapon perks on the EQUIPPED tile — both rolled perks, name + full desc. */
.lo-eq-perks { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.lo-eq-perk { display: flex; flex-direction: column; gap: 1px; }
.lo-eq-perk-name { font-size: 11px; letter-spacing: 1.5px; color: var(--amber); }
.lo-eq-perk-desc {
  font-size: 12.5px; line-height: 1.35; letter-spacing: .3px;
  color: var(--green); opacity: .85; text-transform: none; white-space: normal;
}
/* Ability signature + prose on the EQUIPPED tile. */
.lo-eq-ab-info { display: flex; flex-direction: column; gap: 3px; margin-top: 6px; }
.lo-eq-ab-sig { font-size: 11px; letter-spacing: 1.5px; color: var(--green); opacity: .8; }
.lo-eq-ab-desc {
  font-size: 12.5px; line-height: 1.35; letter-spacing: .3px;
  color: var(--green); opacity: .85; text-transform: none; white-space: normal;
}

/* ── Phone (narrow portrait OR short landscape): make the organizer table fit ──
   Tighter chips + cells, and drop the lowest-value columns so the core stat
   grid fits the width instead of clipping the rightmost column off-screen. */
@media (max-width: 600px), (max-height: 480px) {
  .organizer-th { padding: 6px 6px; font-size: 8px; letter-spacing: 1px; }
  .organizer-td { padding: 6px 6px; font-size: 9px; }
  .organizer-name-text { max-width: 120px; font-size: 10px; }
  .organizer-stats { max-width: 200px; }
  .organizer-chip { padding: 6px 10px; font-size: 9px; min-height: 36px; }

  /* Drop the three shield sub-stats — niche, and the single biggest reason the
     table ran past the right edge. Hide the header AND body cells; the <th>
     carries no per-key class so target it via [data-col-key] to keep the
     remaining columns aligned. */
  .organizer-th[data-col-key="shieldCapacity"],
  .organizer-td-shieldCapacity,
  .organizer-th[data-col-key="shieldRechargeDelayMult"],
  .organizer-td-shieldRechargeDelayMult,
  .organizer-th[data-col-key="shieldRechargeRateMult"],
  .organizer-td-shieldRechargeRateMult { display: none; }

  /* LEFT/RIGHT perk columns — names only on narrow viewports (matches list mode). */
  .organizer-td-perkLeft,
  .organizer-td-perkRight { min-width: 0; max-width: 120px; }
  .organizer-perk-sep,
  .organizer-perk-desc { display: none; }

  .ability-vault .av-stat-num { font-size: 8px; }
}

/* ── Short landscape (≈851×393): claw back vertical room for the VAULT table ──
   Placed AFTER the base .diag-strip / .organizer-filters / .organizer-chip
   definitions so it actually wins (media queries add no specificity — source
   order breaks ties). The diagnostic readout + chip bar were eating ~165px of
   the 393px budget, leaving the table ~1 row tall. Compress both hard; bars
   stay legible, just tighter. */
@media (max-height: 480px) {
  .diag-strip { padding: 3px 12px; }
  .diag-strip-title { margin-bottom: 1px; font-size: 7px; letter-spacing: 2px; }
  .diag-strip-grid { gap: 1px 10px; }
  .diag-strip-row { gap: 5px; }
  .diag-strip-track { height: 5px; }
  .diag-strip-label, .diag-strip-val { font-size: 8px; }
  .organizer-filters { padding: 4px 10px; gap: 3px; }
  .organizer-chip { min-height: 28px; padding: 3px 8px; font-size: 9px; }
  .organizer-search { min-width: 110px; }
  .organizer-search-input { min-height: 28px; padding: 4px 8px; }
}

/* ── Mobile diagnostic strip: stack the stat bars to two, then one column. ── */
@media (max-width: 600px) {
  .diag-strip-grid { grid-template-columns: repeat(2, 1fr); gap: 4px 8px; }
  .diag-strip-label { width: 56px; font-size: 7px; }
}

/* Hide low-value columns on narrow portrait to keep the row readable. Target
   the <th> via [data-col-key] (the old .organizer-th-element selector matched
   nothing, so the header column was left dangling while its body cells hid). */
@media (max-width: 400px) {
  .organizer-th[data-col-key="element"],
  .organizer-td-element,
  .organizer-th[data-col-key="icon"],
  .organizer-td-icon { display: none; }
  .diag-strip-grid { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .organizer-chip, .organizer-equip-btn, .organizer-action-btn,
  .organizer-more-btn, .diag-strip-fill { transition: none; }
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Starter Hero Screen (playtest R2 menu rework)
 * Comic-panel intro that sits OVER the tabbed Mission Control on a fresh
 * pre-run open. 3 big single-color line-art cards, one per starter build.
 * Each card has an unmistakable COMMENCE; a small TINKER footer dismisses
 * the hero and shows the tabbed UI.
 * ─────────────────────────────────────────────────────────────────────────── */
.lo-hero-screen {
  position: absolute;
  inset: 0;
  z-index: 5;                          /* above tabBar / panelHost / strip */
  display: flex;
  flex-direction: column;
  background: var(--void);
  padding: 24px 28px;
  gap: 18px;
  overflow-y: auto;
  pointer-events: auto;
}
.lo-hero-head {
  text-align: center;
  padding: 8px 0 4px;
  border-bottom: 1px solid var(--green-dim);
}
.lo-hero-headline {
  color: var(--amber);
  font-size: 26px;
  letter-spacing: 8px;
  font-weight: bold;
  line-height: 1.1;
  text-shadow: 0 0 12px rgba(255,176,0,.20);
}
.lo-hero-sub {
  color: var(--green);
  font-size: 11px;
  letter-spacing: 3px;
  opacity: .65;
  padding: 6px 0 10px;
}
.lo-hero-grid {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  min-height: 0;
}
.lo-hero-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 22px 18px;
  background: rgba(10, 14, 42, 0.7);
  border: 2px solid var(--amber);
  /* Comic-panel feel: hard shadow + slight inset highlight, no gradients. */
  box-shadow:
    6px 6px 0 0 var(--green-dim),
    inset 0 0 0 1px rgba(255,176,0,.18);
  transition: transform .12s, border-color .12s, box-shadow .12s;
  cursor: pointer;
}
.lo-hero-card:hover,
.lo-hero-card:focus-within {
  transform: translate(-2px, -2px);
  border-color: var(--green);
  box-shadow:
    8px 8px 0 0 var(--amber),
    inset 0 0 0 1px rgba(51,255,102,.25);
}
.lo-hero-card .lo-hero-title {
  color: var(--amber);
  font-size: 28px;
  letter-spacing: 4px;
  line-height: 1;
  font-weight: bold;
  /* Inked outline so it reads like a comic panel intro. */
  text-shadow:
    -1px 0 0 var(--green-dim),
     1px 0 0 var(--green-dim),
     0 -1px 0 var(--green-dim),
     0  1px 0 var(--green-dim);
}
.lo-hero-card .lo-hero-tagline {
  color: var(--green);
  font-size: 12px;
  letter-spacing: 1.5px;
  text-transform: none;
  opacity: .85;
  line-height: 1.35;
  min-height: 32px;
}
.lo-hero-card .lo-hero-class {
  color: var(--amber);
  font-size: 10px;
  letter-spacing: 2px;
  opacity: .80;
  border-top: 1px solid var(--green-dim);
  border-bottom: 1px solid var(--green-dim);
  padding: 6px 0;
}
.lo-hero-abilities {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
  min-height: 0;
}
.lo-hero-ab-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  background: rgba(51, 255, 102, 0.05);
  border: 1px solid var(--green-dim);
  font-size: 11px;
}
.lo-hero-ab-name {
  color: var(--green);
  letter-spacing: 1px;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lo-hero-ab-name-empty { opacity: .5; }
.lo-hero-chassis {
  color: var(--cream);
  font-size: 9px;
  letter-spacing: 1.5px;
  opacity: .60;
  text-align: center;
}
.lo-hero-commence {
  margin-top: 4px;
  padding: 14px 12px;
  background: var(--amber);
  color: var(--void);
  border: none;
  font-family: inherit;
  font-size: 16px;
  letter-spacing: 4px;
  font-weight: bold;
  text-transform: uppercase;
  cursor: pointer;
  transition: background .12s, transform .08s;
  min-height: 56px;
}
.lo-hero-commence:hover,
.lo-hero-commence:focus-visible {
  background: var(--green);
  color: var(--void);
  outline: none;
  transform: scale(1.02);
}
.lo-hero-footer {
  display: flex;
  justify-content: center;
  padding: 8px 0 4px;
  border-top: 1px solid var(--green-dim);
}
.lo-hero-tinker {
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 12px;
  letter-spacing: 2px;
  padding: 12px 24px;
  cursor: pointer;
  text-transform: uppercase;
  transition: color .12s, border-color .12s;
  min-height: 44px;
}
.lo-hero-tinker:hover,
.lo-hero-tinker:focus-visible {
  color: var(--amber);
  border-color: var(--amber);
  outline: none;
}

/* Mobile (narrow portrait): stack the 3 cards vertically; shrink the inked
   title to fit. Guarded to PORTRAIT so a wide-but-short landscape phone
   (e.g. iPhone 15 at 852×393) keeps the 3-up row — see the short-height rule
   below, which is what actually governs landscape devices. */
@media (max-width: 720px) and (orientation: portrait) {
  .lo-hero-screen { padding: 14px 14px; gap: 12px; }
  .lo-hero-grid { grid-template-columns: 1fr; gap: 12px; }
  .lo-hero-headline { font-size: 20px; letter-spacing: 5px; }
  .lo-hero-card { padding: 16px 14px; gap: 10px; }
  .lo-hero-card .lo-hero-title { font-size: 22px; letter-spacing: 3px; }
  .lo-hero-card .lo-hero-tagline { font-size: 11px; min-height: 0; }
  .lo-hero-commence { font-size: 14px; min-height: 48px; padding: 12px; }
}

/* ── Short-height landscape (iPhone 15 landscape ≈ 852×393) ──────────────────
   The hero is the only pre-run gate, so all three COMMENCE buttons MUST be
   reachable without scrolling at 393px tall (minus safe-area). Keep the cards
   in a 3-up ROW, compress every vertical-budget consumer, and let the
   abilities list scroll WITHIN its card so card height stays bounded and the
   COMMENCE button is always pinned at the bottom of each card. */
@media (max-height: 480px) {
  .lo-hero-screen {
    padding: 8px 12px;
    gap: 8px;
    /* The grid itself owns the height; the screen should not scroll. */
    overflow: hidden;
  }
  .lo-hero-head { padding: 2px 0; }
  .lo-hero-headline { font-size: 16px; letter-spacing: 4px; }
  .lo-hero-sub { font-size: 9px; letter-spacing: 2px; padding: 2px 0 4px; }
  /* Keep the 3-up row (override the portrait-stack rule isn't needed here:
     that rule is portrait-only, but be explicit so wide-short stays 3-up). */
  .lo-hero-grid { grid-template-columns: repeat(3, 1fr); gap: 10px; }
  .lo-hero-card {
    padding: 10px 12px;
    gap: 6px;
    box-shadow: 4px 4px 0 0 var(--green-dim), inset 0 0 0 1px rgba(255,176,0,.18);
    min-height: 0;            /* allow the inner abilities list to scroll */
  }
  .lo-hero-card .lo-hero-title { font-size: 18px; letter-spacing: 2px; }
  .lo-hero-card .lo-hero-tagline {
    font-size: 10px;
    line-height: 1.2;
    min-height: 0;
    /* Bound the tagline so it never pushes COMMENCE off-card. */
    max-height: 2.5em;
    overflow: hidden;
  }
  .lo-hero-card .lo-hero-class { font-size: 9px; padding: 3px 0; letter-spacing: 1.5px; }
  /* The abilities list is the flexible region: it scrolls inside the card so
     the headline/tagline/class above and COMMENCE below stay fixed. */
  .lo-hero-abilities { gap: 4px; overflow-y: auto; min-height: 0; }
  .lo-hero-ab-row { padding: 4px 6px; font-size: 10px; }
  .lo-hero-chassis { font-size: 8px; }
  /* COMMENCE stays a comfortable tap target (>=44px) and never scrolls away. */
  .lo-hero-commence {
    flex-shrink: 0;
    margin-top: 2px;
    padding: 10px;
    font-size: 14px;
    letter-spacing: 3px;
    min-height: 46px;
  }
  /* TINKER footer compresses but stays a >=44px tap target. */
  .lo-hero-footer { padding: 3px 0 1px; }
  .lo-hero-tinker { padding: 10px 18px; font-size: 11px; min-height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .lo-hero-card, .lo-hero-commence, .lo-hero-tinker { transition: none; }
  .lo-hero-card:hover { transform: none; }
  .lo-hero-commence:hover { transform: none; }
}

/* ── TUNING PANEL (god-mode only) ─────────────────────────────────────── */
.tuning-panel {
  flex-direction: column;
  overflow-y: auto;
  padding: 12px 16px 24px;
  gap: 14px;
}
.tuning-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}
.tuning-title {
  color: var(--amber);
  font-size: 14px;
  letter-spacing: 3px;
  flex: 1;
}
.tuning-sub {
  color: var(--green);
  opacity: 0.6;
  font-size: 10px;
  letter-spacing: 1.5px;
  flex: 2;
}
.tuning-reset-all {
  flex-shrink: 0;
  font-size: 11px;
  letter-spacing: 2px;
  padding: 8px 14px;
  color: var(--amber);
  border-color: var(--amber);
}
/* Sub-tab switcher inside the TUNING tab: GAMEPLAY / MUSIC pills. Sits in
   tuning-head; mirrors the visual language of .tuning-btn-choice but a touch
   larger so it reads as a section-level toggle, not a row-level radio. */
.tuning-subtabs {
  display: flex;
  flex-shrink: 0;
  gap: 6px;
}
.tuning-subtab {
  font-size: 11px;
  letter-spacing: 2px;
  padding: 6px 12px;
  color: var(--green);
  border: 1px solid var(--green-dim);
  background: rgba(51, 255, 102, 0.04);
}
.tuning-subtab.active {
  color: var(--amber);
  border-color: var(--amber);
  background: rgba(255, 184, 0, 0.10);
}
/* Collapsible audio drawers (tuning.js _wireDrawer): the big SOUND BOARD / SFX
   TUNING panels fold away by default so the gameplay config list is the first
   thing on the TUNING tab. The header button toggles `.open` on the wrap; the
   wrapped panel (.lo-panel-sfx root) is hidden until then. */
.tuning-drawer { display: flex; flex-direction: column; }
.tuning-drawer-toggle {
  display: flex;
  align-items: baseline;
  gap: 10px;
  width: 100%;
  padding: 11px 14px;
  text-align: left;
  color: var(--amber);
  border: 1px solid var(--green-dim);
  background: rgba(255, 184, 0, 0.05);
  letter-spacing: 2px;
  font-size: 12px;
}
.tuning-drawer.open .tuning-drawer-toggle {
  border-color: var(--amber);
  background: rgba(255, 184, 0, 0.10);
}
.tuning-drawer-caret { color: var(--amber); font-size: 11px; width: 1em; flex-shrink: 0; }
.tuning-drawer-label { flex-shrink: 0; }
.tuning-drawer-hint { color: var(--green); opacity: 0.5; font-size: 10px; letter-spacing: 1px; }
.tuning-drawer:not(.open) > .lo-panel-sfx { display: none !important; }
.tuning-drawer > .lo-panel-sfx { margin-top: 10px; }
/* R3 — multi-column tuning sections on wide screens. Sections flow into a
   responsive grid (auto-fit, ~340px min) so 3–4 cards sit above the fold on a
   desktop monitor instead of one full-width column. Each section keeps its
   own card framing; alignment stays consistent across columns via row gap. */
.tuning-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 12px;
  align-items: start;
}
.tuning-section {
  border: 1px solid var(--green-dim);
  background: rgba(51, 255, 102, 0.025);
  padding: 10px 14px 12px;
  min-width: 0; /* lets the section shrink inside the auto-fit track */
}
.tuning-section-head {
  color: var(--amber);
  font-size: 11px;
  letter-spacing: 2.5px;
  margin-bottom: 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--green-dim);
}
.tuning-row {
  display: grid;
  /* R3 — minmax(0,1fr) so the label can shrink with ellipsis instead of
     pushing the value column to the far right of a wide section. The value
     and controls now sit immediately next to the label. */
  grid-template-columns: minmax(0, 1fr) 72px auto;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  border-bottom: 1px dashed rgba(51, 255, 102, 0.1);
}
.tuning-row:last-child { border-bottom: none; }
.tuning-row-overridden { background: rgba(255, 176, 0, 0.06); }
.tuning-label {
  color: var(--green);
  font-size: 11px;
  letter-spacing: 1.5px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tuning-value {
  color: var(--amber);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  letter-spacing: 1px;
}
.tuning-row-overridden .tuning-value { color: var(--amber); font-weight: bold; }
.tuning-controls {
  display: flex;
  gap: 4px;
}
.tuning-btn {
  min-width: 36px;
  min-height: 36px;
  padding: 0 10px;
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0;
  color: var(--green);
  border: 1px solid var(--green-dim);
  background: rgba(10, 14, 42, 0.6);
}
.tuning-btn:hover,
.tuning-btn.ui-focused {
  color: var(--amber);
  border-color: var(--amber);
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
}
.tuning-btn-reset { font-size: 16px; }
/* Choice rows with too many options to fit on one line (e.g. Waveform
   preset — 8 buttons + reset). Drop to a 2-column header (label | value),
   then move the wrapping controls onto a full-width second row. Keeps the
   row inside the section frame instead of overflowing horizontally. */
.tuning-row-choice-wide {
  grid-template-columns: minmax(0, 1fr) 72px;
  grid-template-rows: auto auto;
}
.tuning-row-choice-wide .tuning-controls {
  grid-column: 1 / -1;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.tuning-row-choice-wide .tuning-btn-choice {
  padding: 0 8px;
  font-size: 12px;
}
@media (max-width: 600px) {
  .tuning-head { flex-direction: column; align-items: stretch; gap: 6px; }
  .tuning-sub { font-size: 9px; }
  .tuning-row { grid-template-columns: 1fr 70px auto; gap: 6px; }
  .tuning-label { font-size: 10px; letter-spacing: 1px; }
  .tuning-btn { min-width: 32px; min-height: 32px; padding: 0 8px; }
}

/* ── SFX TUNING sub-panel ─────────────────────────────────────────────────
   Lives inside the existing TUNING tab (created by sfx-tuning.js). Reuses
   .tuning-row + .tuning-btn so styling stays consistent; only the wrap +
   per-sound block + header actions are SFX-specific. The sound list is
   single-column on purpose — each block has wide hint text + 3 action
   buttons that look cramped in the responsive grid the upper list uses. */
.sfx-tuning-wrap {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 18px;
  border-top: 1px dashed var(--green-dim);
  padding-top: 14px;
}
.sfx-tuning-head { gap: 10px; }
.sfx-head-btns { display: flex; gap: 8px; flex-shrink: 0; }
.sfx-copy-json-btn,
.sfx-reset-all-btn {
  font-size: 11px;
  letter-spacing: 2px;
  padding: 8px 12px;
}
.sfx-tuning-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.sfx-tuning-section { /* inherits .tuning-section visuals */ }
.sfx-tuning-section-head { color: var(--amber); }
.sfx-section-empty {
  color: var(--green);
  opacity: 0.5;
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 4px 0 2px;
}
.sfx-sound-block {
  padding: 8px 0 4px;
  border-top: 1px dashed rgba(51, 255, 102, 0.12);
}
.sfx-sound-block:first-of-type { border-top: none; padding-top: 0; }
.sfx-sound-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  padding: 4px 0 6px;
}
.sfx-sound-name {
  justify-self: start;
  color: var(--amber);
  font-size: 12px;
  letter-spacing: 2px;
  padding: 6px 10px;
  border: 1px solid var(--amber);
  background: rgba(255, 176, 0, 0.06);
}
.sfx-sound-name:hover,
.sfx-sound-name.ui-focused {
  background: rgba(255, 176, 0, 0.14);
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
}
.sfx-sound-hint {
  grid-column: 1 / -1;
  color: var(--green);
  opacity: 0.55;
  font-size: 10px;
  letter-spacing: 1px;
  font-style: italic;
}
.sfx-sound-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-self: end;
}
.sfx-play-btn,
.sfx-default-btn,
.sfx-reset-sound-btn {
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 6px 10px;
  color: var(--green);
  border: 1px solid var(--green-dim);
}
.sfx-play-btn:hover,
.sfx-default-btn:hover,
.sfx-reset-sound-btn:hover,
.sfx-play-btn.ui-focused,
.sfx-default-btn.ui-focused,
.sfx-reset-sound-btn.ui-focused {
  color: var(--amber);
  border-color: var(--amber);
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
}
.sfx-knob-row { /* inherits .tuning-row */ }

/* ── SOUND BOARD (god-mode sample swap; ui/loadout/sound-board.js) ─────────
   Rides the sfx-tuning vocabulary; adds the description line, the NOW file
   readout, and the inline library browser. Unlike the synth-knob panel, the
   36 slots pack into a responsive CARD GRID per section (playtest: "half the
   screen is empty") — 2-3 across on desktop/landscape, 1 on portrait; an
   open library browser promotes its block to the full row. */
.sound-board-wrap { margin-bottom: 14px; }
/* Kill the inherited .tuning-list grid / .sfx-tuning-list flex: with their
   align-items:start the sections shrink-to-fit (~530px) and strand the rest
   of the row. Block → sections span the panel; the grid below packs cards. */
.sound-board-list { display: block; }
.sound-board-list .sfx-tuning-section {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(350px, 100%), 1fr));
  gap: 4px 20px;
  align-items: start;
  margin-bottom: 12px;
}
.sound-board-list .sfx-tuning-section-head { grid-column: 1 / -1; }
.sound-board-list .sb-sound-block { border-top: 1px dashed rgba(51, 255, 102, 0.12); }
/* Block with its library browser open → full row (more room to browse).
   :has() is supported on the target platforms (iOS 16+ / Chrome 105+);
   without it the browser just stays inside the card — still usable. */
.sound-board-list .sb-sound-block:has(.sb-lib-browser) { grid-column: 1 / -1; }
.sb-sound-block { display: block; }
.sb-sound-desc {
  color: var(--green);
  opacity: 0.75;
  font-size: 11px;
  letter-spacing: 0.5px;
  line-height: 1.45;
  padding: 5px 0 2px;
  max-width: 62ch;
}
.sb-sound-now {
  color: var(--green);
  opacity: 0.55;
  font-size: 10px;
  letter-spacing: 1px;
  padding: 2px 0 6px;
  word-break: break-all;
}
.sb-now-custom {
  color: var(--amber);
  opacity: 0.9;
}
.sb-block-custom > .sb-sound-name { border-style: double; }
.sb-import-btn,
.sb-change-btn {
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 6px 10px;
  color: var(--green);
  border: 1px solid var(--green-dim);
}
.sb-import-btn:hover, .sb-import-btn.ui-focused,
.sb-change-btn:hover, .sb-change-btn.ui-focused {
  color: var(--amber);
  border-color: var(--amber);
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
}
.sb-lib-browser {
  margin: 6px 0 8px;
  padding: 6px 8px;
  border: 1px solid rgba(255, 176, 0, 0.35);
  background: rgba(255, 176, 0, 0.04);
  max-height: 340px;
  overflow-y: auto;
  /* Entries flow into columns — the full-row block gives the browser the
     whole panel width, so use it. */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: 2px 16px;
  align-content: start;
}
.sb-lib-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 6px;
  align-items: center;
  padding: 2px 0;
}
.sb-lib-preview {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  text-align: left;
  font-size: 10px;
  letter-spacing: 1px;
  padding: 5px 8px;
  color: var(--green);
  border: 1px solid transparent;
  min-width: 0;
}
.sb-lib-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.sb-lib-hint {
  opacity: 0.5;
  font-size: 9px;
  font-style: italic;
  letter-spacing: 0.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
.sb-lib-preview:hover, .sb-lib-preview.ui-focused {
  color: var(--amber);
  border-color: var(--amber);
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
}
.sb-lib-assign,
.sb-lib-delete {
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 5px 8px;
  color: var(--green);
  border: 1px solid var(--green-dim);
}
.sb-lib-assign:hover, .sb-lib-assign.ui-focused,
.sb-lib-delete:hover, .sb-lib-delete.ui-focused {
  color: var(--amber);
  border-color: var(--amber);
  outline: 2.5px solid var(--amber);
  outline-offset: -2.5px;
}
.sb-lib-row-current .sb-lib-preview { color: var(--amber); }
.sb-lib-row-current .sb-lib-assign {
  color: var(--amber);
  border-color: var(--amber);
}
.sb-lib-row-broken { opacity: 0.35; }

@media (max-width: 600px) {
  .sb-sound-actions { display: flex; }
  .sb-sound-actions .touch-btn { flex: 1; min-width: 0; }
}

@media (max-width: 600px) {
  .sfx-tuning-head { flex-direction: column; align-items: stretch; }
  .sfx-head-btns { justify-content: flex-end; }
  .sfx-sound-head { grid-template-columns: 1fr; gap: 6px; }
  .sfx-sound-name { justify-self: stretch; text-align: left; }
  .sfx-sound-actions { justify-self: stretch; }
  .sfx-play-btn,
  .sfx-default-btn,
  .sfx-reset-sound-btn { flex: 1; min-width: 0; }
}

/* ============================================================================
   DIM PASS — junk triage + Item Inspector affordances + portrait-first
   Mission Control. (docs/vault-organizer.md §junk-and-inspect)
   ========================================================================== */

/* Junk items dim in place — DIM's archive-as-dimming: demoted, not hidden, so
   spatial memory survives triage. Cells dim (not the <tr>) so the controller
   focus outline stays full-strength on a focused junk row. */
.organizer-row-junk > .organizer-td { opacity: .42; }
.organizer-row-junk > .organizer-td-card { opacity: 1; }

/* SHARD JUNK — the bulk-dismantle verb in the vault control bar. Red-tinted so
   it reads as destructive; the confirming state (second tap within 3s) burns
   brighter. */
.vault-junk { display: flex; align-items: stretch; flex: 0 0 auto; }
.vault-junk-btn {
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 1px;
  padding: 6px 10px;
  min-height: 34px;
  cursor: pointer;
  background: rgba(255, 93, 93, .06);
  border: 1px solid rgba(255, 93, 93, .45);
  color: #ff5d5d;
  white-space: nowrap;
  transition: background .1s, border-color .1s;
}
.vault-junk-btn.confirming {
  background: rgba(255, 93, 93, .22);
  border-color: #ff5d5d;
  font-weight: 700;
}
.lo-tabbar .vault-junk-btn { font-size: 9px; letter-spacing: .5px; padding: 5px 7px; min-height: 32px; }

/* ── Portrait-first Mission Control ─────────────────────────────────────────
   The vault already collapses to cards (@media rule above); these bring the
   REST of Mission Control to parity on a portrait phone. */
@media (orientation: portrait) and (max-width: 700px) {
  /* Starter hero: 3 side-by-side comic panels can't fit a portrait phone —
     stack them full-width and let the screen scroll. */
  .lo-hero-screen { padding: 14px 12px; gap: 12px; }
  .lo-hero-grid { grid-template-columns: 1fr; gap: 12px; overflow-y: auto; }
  .lo-hero-headline { font-size: 20px; letter-spacing: 5px; }
  .lo-hero-card .lo-hero-title { font-size: 22px; }
}

@media (orientation: portrait) and (max-width: 600px) {
  /* Tab bar: keep one row, scroll horizontally instead of squeezing. */
  .lo-tabbar { overflow-x: auto; scrollbar-width: none; }
  .lo-tabbar::-webkit-scrollbar { display: none; }
  .lo-tab { flex-shrink: 0; }

  /* Header actions get their own full-width row (title wraps above at ≤600px
     already); COMMENCE stretches to a thumb-sized primary action. */
  .lo-header-actions { flex: 1 1 100%; gap: 8px; }
  .lo-commence-btn { flex: 1; }

  /* ABILITIES: the 3 class-chassis cards stack full-width instead of cramming
     two-abreast at ~180px each. */
  .class-picker { flex-direction: column; }
  .class-card { min-width: 0; width: 100%; }
}

/* ── Gear badge icons (DIM pass v2 — comic badge tile, icons.js) ──────────
   Bare inked silhouettes carry their own hard shadow; the badge tile carries
   its own panel/border/shadow inside the SVG — CSS here only sizes them. */
/* Vault table icon column: weapons are wide (48×24), armor square (24×24). */
.organizer-icon-svg.gear-icon-wide { width: 36px; height: 18px; }
.organizer-icon-svg.gear-icon-sq   { width: 18px; height: 18px; }
/* Equipped-tab tiles: worn item = badge tile; empty slot = bare silhouette.
   Steam-deck readability pass — larger badge so worn gear reads at a glance. */
.lo-eq-badge { width: 68px; height: 68px; flex-shrink: 0; }
.lo-eq-icon.gear-icon-wide { width: 72px; height: 36px; }

/* ════════════════════════════════════════════════════════════════════════════
   Vault Card / List view + UI-scale reflow (docs/ui-scale-vault-view.md)
   -----------------------------------------------------------------------------
   `.vault-panel[data-view="card"|"list"]` is set by vault.js. The card cell
   (shared .fc card from card.css) and the table columns both already render per
   row; these rules just choose which to reveal, at any orientation.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── View toggle control (in the vault control bar) ───────────────────────── */
.vault-view-toggle { display: inline-flex; gap: 0; }
.vault-view-btn {
  background: none;
  border: 1px solid var(--green-dim);
  color: var(--green);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 1.5px;
  padding: 6px 10px;
  min-height: 36px;
  cursor: pointer;
  text-transform: uppercase;
}
.vault-view-btn + .vault-view-btn { border-left: none; }
.vault-view-btn.active {
  background: var(--amber-dim);
  color: var(--amber);
  border-color: var(--amber);
}
/* Single toggle chip (CARD ⇄ LIST merged): it's always the sole button, so the
   "active" amber fill would read as stuck-selected. Present it as a neutral
   green chip instead — it shows the CURRENT view and flips on tap. */
.vault-view-toggle-chip.vault-view-btn.active {
  background: none;
  color: var(--green);
  border-color: var(--green-dim);
}
.vault-view-toggle-chip .vault-view-icon { color: var(--amber); }

/* ── ABILITIES browser (ability-vault.js) ─────────────────────────────────
   The tab is a vault-style organizer, so it reuses .vault-* / .organizer-* /
   .fc-* wholesale; only its ability-specific cells + the two modals need styling. */
.ability-vault .av-name-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.ability-vault .av-name { font-weight: 600; letter-spacing: .5px; }
.ability-vault .av-name-meta {
  font-size: 9px;
  letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--ink-dim, #a99fc7);
  opacity: .85;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ability-vault .av-stat-num {
  font-size: 10px;
  letter-spacing: .5px;
  color: var(--green);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.ability-vault .organizer-td-cd,
.ability-vault .organizer-td-stacks,
.ability-vault .organizer-td-radius { white-space: nowrap; }
/* Grouped description row — full width from TYPE onward; list-only. */
.ability-vault .organizer-row-detail { border-bottom: 1px solid rgba(51, 255, 102, .12); }
.ability-vault .organizer-td-detail-lead { padding: 0; border: none; }
.ability-vault .organizer-td-detail {
  padding: 2px 10px 8px;
  vertical-align: top;
}
.ability-vault .av-detail-desc {
  font-size: 10px;
  line-height: 1.35;
  letter-spacing: .2px;
  color: var(--cream, #e8e2ff);
  opacity: .85;
  white-space: normal;
  max-width: 56em;
}
.vault-panel[data-view="card"] .organizer-row-detail { display: none; }
/* List sticky leads on the detail row match the primary row's sticky offsets. */
.vault-panel[data-view="list"] .organizer-row-detail > .organizer-td-detail-lead:nth-child(1) {
  position: sticky; left: 0; z-index: 2; width: 34px; min-width: 34px; max-width: 34px;
  background: var(--void);
}
.vault-panel[data-view="list"] .organizer-row-detail > .organizer-td-detail-lead:nth-child(2) {
  position: sticky; left: 34px; z-index: 2; width: 44px; min-width: 44px; max-width: 44px;
  background: var(--void);
}
.vault-panel[data-view="list"] .organizer-row-detail > .organizer-td-detail-lead:nth-child(3) {
  position: sticky; left: 78px; z-index: 2; background: var(--void);
  border-right: 1px solid var(--green-dim);
}
.av-badge.av-verb { color: var(--amber); border-color: var(--amber-dim); }
.av-badge {
  display: inline-block; padding: 2px 7px; border-radius: 4px;
  font-size: 10px; letter-spacing: .5px; text-transform: uppercase;
  border: 1px solid var(--line, #34244e); color: var(--ink-dim, #a99fc7);
  white-space: nowrap;
}
/* TYPE — delivery form for free abilities; class rows keep their amber/accent. */
.av-badge.av-type-thrown,
.av-badge.av-type-strike,
.av-badge.av-type-deployed,
.av-badge.av-type-channeled  { color: var(--green); border-color: var(--green-dim); }
.av-badge.av-type-classAbility   { color: var(--amber); border-color: var(--amber); }
.av-badge.av-type-classIntrinsic { color: var(--accent, #c9a6ff); border-color: var(--accent, #c9a6ff); }
.av-badge.av-equipped { color: var(--void); background: var(--green); border-color: var(--green); }
.av-equip-btn {
  padding: 5px 12px; font-family: inherit; font-size: 10px; letter-spacing: 1px;
  text-transform: uppercase; cursor: pointer; border-radius: 4px;
  color: var(--amber); background: var(--amber-dim); border: 1px solid var(--amber);
}
.av-equip-btn:hover, .av-equip-btn.ui-focused { background: var(--amber); color: var(--void); }
/* Filter pill groups — a label + the shared .vault-pill chips per axis. On the
   wide/flat tier the axes sit on one row that scrolls horizontally rather than
   wrapping into a tall block (which used to stretch the sibling CARD toggle).
   Below the flat tier the host collapses them into the .av-filter popover. */
.ability-vault-controls .vault-drill { display: flex; flex-wrap: nowrap; gap: 10px 16px; align-items: center; overflow-x: auto; min-width: 0; }
.av-pill-group { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; flex: 0 0 auto; }
.av-pill-label {
  font-size: 9px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--ink-dim, #a99fc7); opacity: .8; margin-right: 2px;
}
.av-pill.active { background: var(--amber-dim); color: var(--amber); border-color: var(--amber); }
/* Collapsed FILTER popover (compact tier) — the abilities axes stack in one
   scrollable menu, each axis prefixed by its group label. Reuses the shared
   .vault-filter-* chrome; only the multi-axis grouping needs extra rules. */
.av-filter-menu { max-height: min(60vh, 420px); overflow-y: auto; }
.av-filter-menu .vault-filter-grouplabel {
  font-size: 9px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--ink-dim, #a99fc7); opacity: .7; padding: 8px 4px 2px;
}
.av-filter-menu .vault-filter-grouplabel:first-child { padding-top: 2px; }

/* Slot-prompt modal — which free slot (L2 / R2) a plain ability equips into.
   Rides the host's sheet-nav seam, so it looks like a compact action sheet.
   Mounted on document.body (outside .loadout-overlay), so neutralize the
   global HUD .touch-btn position:absolute here — same fix as item-sheet. */
.av-slot-sheet {
  position: fixed; inset: 0; z-index: 34; display: flex;
  align-items: center; justify-content: center; background: rgba(6, 4, 14, .72);
}
.av-slot-sheet .touch-btn { position: static; transform: none; }
.av-slot-box {
  min-width: 280px; max-width: 92vw; padding: 20px;
  background: var(--panel, #140d24); border: 1px solid var(--amber);
  border-radius: 10px; box-shadow: 0 12px 40px rgba(0, 0, 0, .6);
  display: flex; flex-direction: column; gap: 10px;
}
.av-slot-title {
  font-size: 12px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--amber); text-align: center; margin-bottom: 4px;
}
.av-slot-btn {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 10px 14px; cursor: pointer; border-radius: 6px;
  background: rgba(255, 255, 255, .03); border: 1px solid var(--line, #34244e);
  color: var(--ink, #e8e2ff); font-family: inherit;
}
.av-slot-btn:hover, .av-slot-btn.ui-focused { border-color: var(--amber); background: var(--amber-dim); }
.av-slot-bind { font-size: 10px; letter-spacing: 1px; color: var(--amber); text-transform: uppercase; }
.av-slot-occ  { font-size: 12px; color: var(--ink-dim, #a99fc7); }
.av-slot-cancel { text-align: center; color: var(--ink-dim, #a99fc7); }

/* Class picker modal (EQUIPPED) — three classes + descriptions. */
.lo-class-picker {
  position: fixed; inset: 0; z-index: 35; display: flex;
  align-items: center; justify-content: center; background: rgba(6, 4, 14, .78);
}
.lo-class-picker-box {
  width: min(760px, 94vw); padding: 24px;
  background: var(--panel, #140d24); border: 1px solid var(--accent, #c9a6ff);
  border-radius: 12px; box-shadow: 0 16px 50px rgba(0, 0, 0, .65);
}
.lo-class-picker-title {
  font-size: 15px; letter-spacing: 2px; text-transform: uppercase;
  color: var(--accent, #c9a6ff); text-align: center;
}
.lo-class-picker-sub {
  font-size: 11px; color: var(--ink-dim, #a99fc7); text-align: center; margin: 6px 0 16px;
}
.lo-class-picker-row {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px;
}
.lo-class-picker-card {
  display: flex; flex-direction: column; gap: 6px; text-align: left;
  padding: 16px; cursor: pointer; border-radius: 10px; font-family: inherit;
  background: rgba(255, 255, 255, .03); border: 1px solid var(--line, #34244e);
  color: var(--ink, #e8e2ff);
}
.lo-class-picker-card:hover, .lo-class-picker-card.ui-focused {
  border-color: var(--accent, #c9a6ff); background: rgba(201, 166, 255, .08);
}
.lo-class-picker-card.ui-equipped { border-color: var(--green); }
.lo-class-picker-name { font-size: 16px; font-weight: 700; letter-spacing: .5px; }
.lo-class-picker-lean {
  font-size: 9px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--accent, #c9a6ff); opacity: .85;
}
.lo-class-picker-desc { font-size: 11px; line-height: 1.4; color: var(--ink-dim, #a99fc7); }
.lo-class-picker-cancel {
  display: block; margin: 0 auto; padding: 8px 24px; cursor: pointer;
  font-family: inherit; font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--ink-dim, #a99fc7); background: rgba(255, 255, 255, .03);
  border: 1px solid var(--line, #34244e); border-radius: 6px;
}
.lo-class-picker-cancel:hover, .lo-class-picker-cancel.ui-focused { border-color: var(--accent, #c9a6ff); color: var(--ink, #e8e2ff); }
@media (max-width: 640px) { .lo-class-picker-row { grid-template-columns: 1fr; } }

/* ── LIST mode ────────────────────────────────────────────────────────────
   Force the dense table even on portrait phones (overrides the legacy portrait
   card morph by specificity), and pin the identity columns (check + icon + name)
   so a sideways swipe keeps the item — and the already-sticky header — in view. */
.vault-panel[data-view="list"] .organizer-table        { display: table; border-collapse: separate; border-spacing: 0; }
.vault-panel[data-view="list"] .organizer-table thead  { display: table-header-group; }
.vault-panel[data-view="list"] .organizer-tbody        { display: table-row-group; }
.vault-panel[data-view="list"] .organizer-row          { display: table-row; }
.vault-panel[data-view="list"] .organizer-row > .organizer-td       { display: table-cell; }
.vault-panel[data-view="list"] .organizer-row > .organizer-td-card  { display: none; }

.vault-panel[data-view="list"] .organizer-td-check,
.vault-panel[data-view="list"] .organizer-th-check {
  position: sticky; left: 0; z-index: 3;
  width: 34px; min-width: 34px; max-width: 34px;
  background: var(--void);
}
.vault-panel[data-view="list"] .organizer-td-icon,
.vault-panel[data-view="list"] .organizer-th[data-col-key="icon"] {
  position: sticky; left: 34px; z-index: 3;
  width: 44px; min-width: 44px; max-width: 44px;
  background: var(--void); overflow: hidden;
}
.vault-panel[data-view="list"] .organizer-td-name,
.vault-panel[data-view="list"] .organizer-th[data-col-key="name"] {
  position: sticky; left: 78px; z-index: 3;
  background: var(--void);
  border-right: 1px solid var(--green-dim);
}
/* Header corners (both-axis sticky) ride above the body's pinned column. */
.vault-panel[data-view="list"] .organizer-th-check,
.vault-panel[data-view="list"] .organizer-th[data-col-key="icon"],
.vault-panel[data-view="list"] .organizer-th[data-col-key="name"] { z-index: 5; }

/* LIST view trims columns whose value the layout already conveys, cutting the
   horizontal scroll (playtest: "hide columns that aren't necessary"): SLOT is
   implied by the drill context + the ARCHETYPE column; RARITY is encoded in the
   name colour. LEFT/RIGHT perk columns stay — names only (sep+desc hidden). */
.vault-panel[data-view="list"] .organizer-th[data-col-key="slot"],
.vault-panel[data-view="list"] .organizer-th[data-col-key="rarity"] { display: none; }
/* Body cells use the `.organizer-row > .organizer-td-*` child form so they match
   the specificity of the `.organizer-row > .organizer-td { display: table-cell }`
   base rule above and win on source order — a plain `.organizer-td-slot` (one
   fewer class) loses to it and the cell would stay, mis-aligning the row. */
.vault-panel[data-view="list"] .organizer-row > .organizer-td-slot,
.vault-panel[data-view="list"] .organizer-row > .organizer-td-rarity { display: none; }
/* List mode: perk NAMES only — prose lives on the item sheet / card hover. */
.vault-panel[data-view="list"] .organizer-perk-sep,
.vault-panel[data-view="list"] .organizer-perk-desc { display: none; }
.vault-panel[data-view="list"] .organizer-td-perkLeft,
.vault-panel[data-view="list"] .organizer-td-perkRight { min-width: 90px; max-width: 140px; }
.vault-panel[data-view="list"] .organizer-perk.organizer-perk-chip {
  padding: 2px 5px;
}
/* menus-refit-spec.md §F — the data-cat stat trim that used to live here is
   gone: WEAPONS/ARMOR are separate organizer instances now, and each one's
   `_columns()` only ever builds the columns relevant to its category, so
   there are no always-empty cells left to hide/re-assert in list view. */

/* ── CARD mode ────────────────────────────────────────────────────────────
   `.organizer-tbody` becomes a responsive grid; only the card cell shows. Scale
   drives COLUMN COUNT (not zoom): the grid counter-zooms to neutralize the
   overlay's --ui-scale zoom, then sizes its font + track-min by --ui-scale, so a
   larger scale widens the min and yields fewer, bigger columns (reflow). em card
   internals ride that font-size. */
.vault-panel[data-view="card"] .organizer-table       { display: block; }
.vault-panel[data-view="card"] .organizer-table thead { display: none; }
.vault-panel[data-view="card"] .organizer-tbody {
  display: grid;
  /* Fixed 2-up so names/stats have room (glance cards); stacks to 1 on narrow.
     Row gap leaves headroom for the floating EQUIPPED corner tab (top: -8px). */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: 0.9em 0.6em;
  padding: 10px;
  align-content: start;
  font-size: calc(11px * var(--ui-scale, 1));
  zoom: calc(1 / var(--ui-scale, 1));
}
@media (max-width: 640px) {
  .vault-panel[data-view="card"] .organizer-tbody {
    /* minmax(0,1fr) — NOT a bare 1fr: 1fr's implicit `auto` min lets the track
       grow to the card's min-content (nowrap name + perk chips), overflowing a
       narrow phone. min 0 caps the track at the container so the card ellipsizes. */
    grid-template-columns: minmax(0, 1fr);
  }
}
.vault-panel[data-view="card"] .organizer-empty { grid-column: 1 / -1; }
/* Card grid items must shrink to the track — else a wide card forces overflow. */
.vault-panel[data-view="card"] .organizer-row          { display: block; padding: 0; border: none; min-width: 0; }
.vault-panel[data-view="card"] .organizer-row > .organizer-td       { display: none; }
.vault-panel[data-view="card"] .organizer-row > .organizer-td-card  { display: block; padding: 0; border: none; }

/* Browse-grid weapon glance cards: uniform perk chips + no clipped text.
   The perk band is a single fixed width so every card's chips are identical
   (they no longer size to their perk name — that's what made adjacent cards'
   chips different widths). 146px fits the longest perk name in the catalog
   ("PRECISION THREAD", ~106px of 10.5px text) PLUS the right-side loop-verb
   icon on one line, so nothing wraps or clips. The chip font is fixed px (not
   em), so a px band stays exactly fitted across breakpoints. The dim
   ARCHETYPE · RPM meta line WRAPS instead of ellipsizing so it's never cut. */
.vault-panel[data-view="card"] .lo-eq-g-perks {
  flex: 0 0 146px; width: 146px; max-width: 146px;
}
.vault-panel[data-view="card"] .lo-eq-g-meta-txt {
  white-space: normal; overflow: visible; text-overflow: clip;
}

/* ═══════════════════════════════════════════════════════════════════════════
   build-loop.js — "teach the build" widgets (loadout-builds-screen).
   Shared by EQUIPPED / LOADOUTS / ABILITIES. Deliberately larger, higher-
   contrast type than the legacy tables — the screen teaches HOW TO PLAY.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── The build sentence + the loop label ──────────────────────────────────── */
.lo-card-sentence {
  font-size: 15px; line-height: 1.45; color: var(--cream);
  font-style: italic; letter-spacing: .01em; margin-bottom: 12px;
  border-left: 3px solid var(--amber); padding-left: 10px;
}
.lo-card-loop-warn {
  margin-top: 9px; font-size: 12.5px; color: var(--red);
  border: 1px solid var(--red); border-radius: 4px; padding: 6px 9px; line-height: 1.35;
}

/* ── Collapsible sections (loadout-card-collapse) — SYNERGIES / HOW TO PLAY /
   THE LOOP diagram / NOTES. Nested inside col1 (class+abilities), NOT a
   full-width block below both columns — col2 (armor+weapons+perk prose+
   totals) is reliably the taller column, so a full-width block below both
   sat under a few hundred px of blank dead space in col1 instead (playtest:
   "a lot of dead space" / Steam Deck one-screen+scroll complaint). Filling
   col1's own remaining room re-uses space that was already reserved.
   Row rhythm matches `.lo-card-ab-row` right above it (padding 6px 0,
   border-top divider) so the list reads as one continuous column. ────────── */
.lo-card-sections { display: flex; flex-direction: column; gap: 0; }
.lo-card-section { border-top: 1px solid var(--green-dim); }
.lo-card-section-hdr {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 0; cursor: pointer; user-select: none;
}
.lo-card-section-hdr:hover { background: rgba(51, 255, 102, .04); }
.lo-card-section-label {
  font-size: 11px; font-weight: bold; letter-spacing: 2px;
  color: var(--amber-dim); text-transform: uppercase; flex-shrink: 0;
}
.lo-card-section-preview {
  font-size: 11px; color: var(--green-dim); letter-spacing: 0.3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
  flex: 1;
}
/* Pinned to col1's right edge (see the note in `_cardSection`, loadout.js) —
   a small, consistently-placed nav cell keeps nav.js's geometry-first mover
   moving in a straight vertical line down the section list, same reasoning
   as the outer `.lo-card-chevron`/`.lo-card-apply` split. */
.lo-card-section-chevron {
  color: var(--amber-dim); font-size: 11px; width: 10px; flex-shrink: 0;
  margin-left: auto; text-align: right;
}
.lo-card-section-chevron.ui-focused {
  outline: 1px solid var(--amber); outline-offset: 2px;
}
.lo-card-section-body { padding: 2px 2px 12px; }

/* ── LOOP RIBBON ──────────────────────────────────────────────────────────── */
.bl-ribbon { display: flex; flex-wrap: wrap; align-items: stretch; gap: 5px; }
.bl-step {
  flex: 1 1 128px; min-width: 116px;
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 10px; border: 1px solid var(--green-dim); border-radius: 6px;
  background: rgba(10, 14, 42, .5);
}
.bl-step-sigil { width: 22px; height: 22px; flex: 0 0 auto; margin-top: 1px; }
.bl-step-body { min-width: 0; }
.bl-step-role {
  font-size: 10px; font-weight: bold; letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--amber-dim); white-space: nowrap;
}
.bl-step-title {
  display: flex; align-items: center; gap: 5px;
  font-size: 14px; font-weight: bold; color: var(--cream); line-height: 1.15; margin: 2px 0;
}
.bl-step-sub { font-size: 11.5px; color: #8f9ac4; line-height: 1.3; }
.bl-elem-sigil { width: 15px; height: 15px; flex: 0 0 auto; }
.bl-pip { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.bl-arrow { display: flex; align-items: center; color: var(--amber-dim); font-size: 15px; }

/* role tints — mirror .ab-role-badge (prime=cyan · detonate=amber · fate=green) */
.bl-step-prime    { border-color: var(--rarity-rare); }
.bl-step-prime    .bl-step-sigil { color: var(--rarity-rare); }
.bl-step-detonate { border-color: var(--amber); }
.bl-step-detonate .bl-step-sigil { color: var(--amber); }
.bl-step-react    { border-color: var(--bl-react, var(--rarity-legendary)); }
.bl-step-react    .bl-step-title { color: var(--bl-react, var(--cream)); }
.bl-step-fate     { border-color: var(--green); }
.bl-step-fate     .bl-step-sigil { color: var(--green); }
.bl-step-fate     .bl-step-title { color: var(--green); }

/* ── LOOP DIAGRAM (buildLoopDiagram — the EQUIPPED hero + ABILITIES-tab live
   loop). A proper diagram, not a flat ribbon: arrows run ONLY grouped-PRIMERS
   → grouped-DETONATORS (never prime→prime), then the loop branches into the
   two taught outcomes (SAME element → FOCUSED · MIXED elements → AOE
   REACTION) before both converge on FEEDS FATE.
   Mobile-first: `.ld-loop` stacks stages top-to-bottom (portrait phones) —
   every stage is a flex item with no fixed width, and `.ld-nodes`/`.ld-branch`
   wrap their own children, so nothing can force horizontal overflow at
   ~360px. Past 700px it flips to a left-to-right row (desktop) and the
   connector glyph un-rotates to point right instead of down. ────────────── */
.ld-loop {
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
}
.ld-stage { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.ld-stage-label {
  font-size: 10px; font-weight: bold; letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--amber-dim);
}
.ld-nodes { display: flex; flex-wrap: wrap; align-items: stretch; gap: 6px; }

.ld-node {
  flex: 1 1 132px; min-width: 118px; max-width: 100%; box-sizing: border-box;
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 10px; border: 1px solid var(--green-dim); border-radius: 6px;
  background: rgba(10, 14, 42, .5);
}
.ld-node-sigil { width: 22px; height: 22px; flex: 0 0 auto; margin-top: 1px; }
.ld-node-body { min-width: 0; }
.ld-node-kicker {
  font-size: 10px; font-weight: bold; letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--amber-dim); white-space: nowrap;
}
.ld-node-title {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
  font-size: 14px; font-weight: bold; color: var(--cream); line-height: 1.15; margin: 2px 0;
}
.ld-node-sub { font-size: 11.5px; color: #8f9ac4; line-height: 1.3; }

/* The connector: one glyph, CSS-rotated — points down while stages stack
   vertically, un-rotates to point right once `.ld-loop` goes horizontal. */
.ld-arrow {
  display: flex; align-items: center; justify-content: center;
  color: var(--amber-dim); font-size: 16px; line-height: 1;
  transform: rotate(90deg);
}

/* Node role tints — mirrors .bl-step-* (prime=cyan · detonate=amber · fate=green). */
.ld-node-prime    { border-color: var(--rarity-rare); }
.ld-node-prime    .ld-node-sigil { color: var(--rarity-rare); }
.ld-node-detonate { border-color: var(--amber); }
.ld-node-detonate .ld-node-sigil { color: var(--amber); }
.ld-node-fate     { border-color: var(--green); }
.ld-node-fate     .ld-node-sigil { color: var(--green); }
.ld-node-fate     .ld-node-title { color: var(--green); }
.ld-node-empty    { border-color: #4a5280; opacity: .75; }
.ld-node-empty    .ld-node-sigil { color: #6b74a0; }
.ld-node-empty    .ld-node-title { color: #9aa4cc; }

/* The two outcomes: SAME element (FOCUSED) vs MIXED elements (AOE REACTION).
   Both always render AND both light whenever reachable (prime-visual-language.md
   §4 — never an either/or); `.ld-active` = reachable, the default dim = a
   greyed card with its one-line "how to unlock". */
.ld-branch {
  display: flex; flex-wrap: wrap; align-items: stretch; gap: 8px;
}
.ld-branch-or {
  display: flex; align-items: center; justify-content: center; text-align: center;
  flex: 1 1 100%; font-size: 10.5px; font-style: italic; letter-spacing: .04em;
  color: #8f9ac4; padding: 0 2px;
}
.ld-outcome { opacity: .5; filter: saturate(.6); transition: opacity .15s, filter .15s; }
.ld-outcome.ld-active { opacity: 1; filter: none; }
.ld-unlock { font-style: italic; color: #6b74a0; }
.ld-hint   { font-style: italic; color: var(--amber); opacity: .8; }
.ld-node-same { border-color: var(--amber); }
.ld-node-same .ld-node-sigil { color: var(--amber); }
.ld-node-mixed { border-color: var(--rarity-legendary); flex: 1 1 132px; min-width: 118px; }
.ld-node-mixed .ld-node-title { color: var(--rarity-legendary); }

.ld-reaction-chips { display: flex; flex-wrap: wrap; gap: 5px; margin: 3px 0 2px; }
.ld-reaction-chip {
  display: inline-flex; align-items: center; gap: 4px;
  color: var(--bl-react, var(--rarity-legendary)); border: 1px solid currentColor;
  padding: 2px 7px; border-radius: 3px; font-size: 11px; font-weight: bold; letter-spacing: .04em;
}
.ld-reaction-sigil { width: 14px; height: 14px; flex: 0 0 auto; }

/* ── DETONATE CARDS (prime-visual-language.md §4) — one card per pop the kit
   can make (FOCUSED + each reachable reaction). Two element sigils, blurb,
   PUSH/FX property rows, and the single-vs-double-prime payoff ladder. Reuses
   `.ld-outcome`/`.ld-active` for the reachable-vs-greyed treatment. ────────── */
.ld-stage-sublabel {
  font-size: 9.5px; font-weight: bold; letter-spacing: 1.4px; text-transform: uppercase;
  color: #8f9ac4; margin-top: 4px;
}
.ld-det-cards { display: flex; flex-wrap: wrap; align-items: stretch; gap: 8px; }
/* The detonate cards carry more content than the loop nodes (props + prime
   ladder), so they wrap to a SINGLE full-width column on a phone (basis 260 >
   half a ~430px screen → one per row) and only go 2-up once the surface is
   wide enough (tablet/desktop). Keeps the loop from ever forcing horizontal
   overflow at narrow widths. */
.ld-det-card {
  flex: 1 1 260px; min-width: 0; max-width: 100%; box-sizing: border-box;
  display: flex; flex-direction: column; gap: 5px;
  padding: 9px 11px; border: 1px solid var(--bl-react, var(--amber)); border-radius: 6px;
  background: rgba(10, 14, 42, .5);
}
.ld-det-head { display: flex; align-items: center; gap: 8px; }
.ld-det-icons { display: flex; align-items: center; gap: 3px; flex: 0 0 auto; }
.ld-det-sigil { width: 20px; height: 20px; flex: 0 0 auto; }
.ld-det-join { font-size: 12px; font-weight: bold; color: var(--bl-react, var(--amber)); }
.ld-det-titlewrap { min-width: 0; }
.ld-det-kicker {
  font-size: 9px; font-weight: bold; letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--amber-dim);
}
.ld-det-title { font-size: 15px; font-weight: bold; color: var(--bl-react, var(--cream)); line-height: 1.1; }
.ld-det-blurb { font-size: 11.5px; color: var(--cream); line-height: 1.3; }
.ld-det-prop { display: flex; gap: 6px; font-size: 11px; color: #8f9ac4; line-height: 1.3; }
.ld-det-prop-k {
  flex: 0 0 auto; font-size: 8.5px; font-weight: bold; letter-spacing: .8px;
  color: var(--amber-dim); padding-top: 1px; min-width: 20px;
}
.ld-det-tiers { display: flex; flex-direction: column; gap: 3px; margin-top: 2px; }
.ld-det-tier {
  display: flex; flex-direction: column; gap: 1px;
  padding: 4px 6px; border-radius: 4px; background: rgba(255, 255, 255, .03);
  border-left: 2px solid #4a5280;
}
.ld-det-tier-big { border-left-color: var(--bl-react, var(--amber)); background: rgba(255, 176, 0, .06); }
.ld-det-tier-k {
  font-size: 8.5px; font-weight: bold; letter-spacing: .6px; text-transform: uppercase; color: #8f9ac4;
}
.ld-det-tier-big .ld-det-tier-k { color: var(--bl-react, var(--amber)); }
.ld-det-tier-v { font-size: 11px; color: var(--cream); line-height: 1.25; }
.ld-det-unlock { font-size: 10.5px; font-style: italic; color: #6b74a0; }
.ld-det-hint   { font-size: 10.5px; font-style: italic; color: var(--amber); opacity: .85; }

/* ── FATE GROUP — what Fate is + the equipped engines that feed it. ────────── */
.ld-stage-fate .ld-stage-label { color: var(--green); }
.ld-fate-card {
  display: flex; flex-direction: column; gap: 6px;
  padding: 9px 11px; border: 1px solid var(--green); border-radius: 6px;
  background: rgba(10, 30, 20, .35);
}
.ld-fate-head { display: flex; align-items: center; gap: 8px; }
.ld-fate-sigil { width: 20px; height: 20px; flex: 0 0 auto; color: var(--green); }
.ld-fate-title { font-size: 15px; font-weight: bold; color: var(--green); letter-spacing: .04em; }
.ld-fate-blurb { font-size: 11.5px; color: var(--cream); line-height: 1.3; }
.ld-fate-feeds { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ld-fate-feed-k {
  font-size: 9px; font-weight: bold; letter-spacing: 1.2px; color: var(--amber-dim); flex: 0 0 auto;
}
.ld-fate-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.ld-fate-chip {
  display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 3px;
  font-size: 10.5px; font-weight: bold; letter-spacing: .03em;
  color: #8f9ac4; border: 1px solid #4a5280;
}
.ld-fate-chip-engine { color: var(--green); border-color: var(--green); }
.ld-fate-hint { font-size: 10.5px; font-style: italic; color: #7f8ab4; }

/* Desktop / wide: the diagram runs left-to-right instead of stacking. */
@media (min-width: 700px) {
  .ld-loop { flex-direction: row; align-items: stretch; flex-wrap: wrap; }
  .ld-stage { flex: 1 1 200px; justify-content: center; }
  .ld-branch { flex: 1 1 280px; }
  /* DETONATE is the widest group — let it take the row so its cards spread. */
  .ld-stage-detonate { flex: 1 1 100%; }
  .ld-arrow { transform: rotate(0deg); flex: 0 0 auto; }
  /* FATE is the payoff — a full-width footer bar under the horizontal flow, so
     the arrow that would otherwise dangle pointing at the wrapped stage is hidden
     (portrait keeps its downward arrow — this only applies once the loop is a row). */
  .ld-stage-fate { flex: 1 1 100%; }
  .ld-loop .ld-arrow:has(+ .ld-stage-fate) { display: none; }
}

.lo-eq-hero .ld-loop { margin-top: 6px; }

/* ── WEAPON PERKS ─────────────────────────────────────────────────────────── */
.lo-card-perk-head {
  display: flex; align-items: center; gap: 7px;
  margin: 12px 0 6px; font-size: 13px;
}
.lo-card-perk-gun { font-weight: bold; letter-spacing: .04em; }
.bl-perks { display: flex; flex-direction: column; gap: 6px; }
.bl-perk {
  border-left: 3px solid var(--amber-dim); border-radius: 0 4px 4px 0;
  padding: 6px 9px; background: rgba(10, 14, 42, .45);
}
.bl-perk-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.bl-perk-name { font-size: 13.5px; font-weight: bold; color: var(--cream); }
.bl-perk-role {
  font-size: 9.5px; font-weight: bold; letter-spacing: 1px;
  padding: 1px 5px; border: 1px solid currentColor; border-radius: 2px; text-transform: uppercase;
}
.bl-perk-desc { font-size: 12px; color: #9aa4cc; line-height: 1.35; margin-top: 3px; }
.bl-perk-empty { font-size: 12px; color: #7a83a8; font-style: italic; padding: 4px 0; }
/* role → color: primer=cyan · trigger/finisher=amber · engine=green · amplifier=burn · feel=gray */
.bl-perk-primer    { border-left-color: var(--rarity-rare); }
.bl-perk-primer    .bl-perk-role { color: var(--rarity-rare); }
.bl-perk-trigger   { border-left-color: var(--amber); }
.bl-perk-trigger   .bl-perk-role { color: var(--amber); }
.bl-perk-finisher  { border-left-color: var(--amber); }
.bl-perk-finisher  .bl-perk-role { color: var(--amber); }
.bl-perk-engine    { border-left-color: var(--green); }
.bl-perk-engine    .bl-perk-role { color: var(--green); }
.bl-perk-amplifier { border-left-color: var(--elem-burn); }
.bl-perk-amplifier .bl-perk-role { color: var(--elem-burn); }
.bl-perk-feel      { border-left-color: #6b74a0; }
.bl-perk-feel      .bl-perk-role { color: #9aa4cc; }

/* ── REACTION BADGES ──────────────────────────────────────────────────────── */
.bl-react-badges { display: flex; flex-wrap: wrap; gap: 6px; }
.bl-react-badge {
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--bl-react, var(--cream)); border: 1px solid currentColor;
  padding: 3px 9px; border-radius: 3px; font-size: 12px; font-weight: bold; letter-spacing: .06em;
}
/* FOCUSED — a first-class pop chip beside the reactions (amber = the SAME card). */
.bl-react-badge-focused { color: var(--amber); }
/* Loop not closed: no pops at all — dashed muted placeholder. */
.bl-react-badge-none { color: #6b74a0; border-style: dashed; }
.bl-react-sigil { width: 16px; height: 16px; flex: 0 0 auto; }

/* ── HOW TO PLAY (numbered loop) ──────────────────────────────────────────── */
.bl-howto-list { list-style: none; counter-reset: bl-step; margin: 0; padding: 0; }
.bl-howto-step {
  counter-increment: bl-step; position: relative;
  padding: 5px 0 5px 30px; font-size: 13px; line-height: 1.5; color: var(--cream);
}
.bl-howto-step::before {
  content: counter(bl-step); position: absolute; left: 0; top: 4px;
  width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--amber);
  color: var(--amber); font-size: 11px; font-weight: bold;
  display: flex; align-items: center; justify-content: center;
}
.bl-howto-step:not(:last-child)::after {
  content: ''; position: absolute; left: 10px; top: 25px; bottom: -1px;
  width: 1px; background: var(--green-dim);
}

/* ── EQUIPPED-tab hero (loop ribbon at the top of the build overview) ──────── */
/* B5 (menus-refit-spec.md) — `.equipped-panel` is 0-horizontal-padded and this
   widget had none of its own, so the loop diagram ran flush to the viewport
   edge. 16px matches `.lo-eq-grid`'s gutter above it. The diagram's own nodes
   (`.ld-node`) only pad their individual boxes, not the `.ld-loop` container,
   so this doesn't double up on portrait. */
.lo-eq-hero { margin: 2px 0 14px; padding: 0 16px; }
.lo-eq-hero .bl-ribbon { margin-top: 6px; }
.lo-eq-hero-react { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.lo-eq-hero-react-lbl {
  font-size: 11px; font-weight: bold; letter-spacing: 1.5px; color: var(--amber-dim); text-transform: uppercase;
}

/* ── Phase B gear-first layout (cosmetics-spec.md §6) ──────────────────────
   YOUR FATEFORGED — the live avatar viewport under the gear cells, and
   HOW YOUR BUILD PLAYS — the standing loop + intrinsics + stat-totals panel
   (replaces the collapsed VIEW BUILD LOOP drawer). Clean dark backdrop, a rim
   line, nothing else — the diegetic stage is the starship, not this menu. */
.lo-eq-fateforged { padding: 0 16px; }
/* The cell is sized off its HEIGHT, not its width (playtest 2026-08-04): at
   4/5 of a 340px width the body stood 425px tall — taller than the EQUIPPED
   panel's scroll viewport on a phone in landscape, so scrolling it into view
   could only ever show one end of it, and the panel below it was hidden behind
   a body that didn't fit. Height leads, width follows the 4:5 ratio, and 52vh
   keeps the whole Fateforged inside the port on every screen. Close-up detail
   is the full-screen inspector's job, not this cell's. */
.lo-eq-avatar-viewport {
  --lo-av-h: min(425px, 52vh, 97.5vw);   /* 97.5vw = the old 78vw at 4:5 */
  position: relative; height: var(--lo-av-h); width: calc(var(--lo-av-h) * 0.8);
  margin: 4px auto 10px; touch-action: pan-y;
  border: 1px solid var(--green-dim);
  background:
    radial-gradient(ellipse at 50% 28%, rgba(140, 160, 220, 0.10), transparent 62%),
    linear-gradient(180deg, #0a0c14 0%, #060810 100%);
}
.lo-eq-avatar-canvas, .lo-eq-avatar-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; object-fit: contain;
}
.lo-eq-avatar-missing { cursor: default; }
/* The cell is a button (tap / Cross → the inspector), so it points; only the
   full-screen stage, where dragging actually turns the body, grabs. */
.lo-eq-avatar-viewport { cursor: pointer; }
.lo-eq-avatar-hint {
  position: absolute; right: 6px; bottom: 6px; z-index: 2; pointer-events: none;
  font-size: 10px; font-weight: 700; letter-spacing: 1.4px;
  color: var(--amber-dim); background: rgba(4, 6, 12, .72);
  border: 1px solid var(--green-dim); padding: 3px 7px;
}
.lo-eq-avatar-viewport.ui-focused .lo-eq-avatar-hint { color: var(--amber); }

/* ── Full-screen FATEFORGED inspector (ui/loadout/avatar-fullscreen.js) ─────
   The EQUIPPED viewport element re-parents into .lo-avfs-stage and fills it —
   same renderer, no aspect box, no border. */
.lo-eq-avatar-viewport.lo-eq-avatar-fs {
  width: 100%; height: 100%; max-width: none; aspect-ratio: auto;
  margin: 0; border: 0; background: none; cursor: grab; touch-action: none;
}
.lo-eq-avatar-viewport.lo-eq-avatar-fs:active { cursor: grabbing; }
.lo-eq-avatar-fs .lo-eq-avatar-hint { display: none; }
/* The cell keeps its nav focus while the inspector borrows it (so closing
   returns the cursor to it) — but the ring belongs on a menu cell, not framing
   a full-screen body. */
.lo-eq-avatar-viewport.lo-eq-avatar-fs.ui-focused {
  outline: none; box-shadow: none; animation: none;
}

.lo-avfs {
  position: fixed; inset: 0; z-index: 60;
  display: flex; flex-direction: column; align-items: stretch;
  padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px));
  /* Fully opaque: the EQUIPPED screen bleeding through the backdrop read as a
     rendering fault, not depth. */
  background:
    radial-gradient(ellipse at 50% 34%, rgba(140, 160, 220, .13), transparent 64%),
    linear-gradient(180deg, #05070d 0%, #020306 100%);
}
.lo-avfs-head { text-align: center; flex: 0 0 auto; }
.lo-avfs-title {
  font-size: 15px; font-weight: 700; letter-spacing: 3px; color: var(--amber);
}
.lo-avfs-sub {
  margin-top: 4px; font-size: 11px; letter-spacing: 1.4px; color: var(--amber-dim);
}
/* The body owns every pixel the chrome doesn't — min-height:0 so the flex child
   can actually shrink instead of pushing the control bar off-screen. */
.lo-avfs-stage { flex: 1 1 auto; min-height: 0; position: relative; margin: 10px 0; }
.lo-avfs-bar {
  flex: 0 0 auto; display: flex; flex-wrap: wrap; justify-content: center; gap: 8px;
}
.lo-avfs-btn {
  min-height: 44px; padding: 0 14px;
  font-family: inherit; font-size: 12px; font-weight: 700; letter-spacing: 1.6px;
  color: var(--amber); background: rgba(10, 12, 20, .9);
  border: 1px solid var(--green-dim); cursor: pointer;
  touch-action: manipulation; user-select: none;
}
.lo-avfs-btn.active { color: var(--void); background: var(--amber); border-color: var(--amber); }
.lo-avfs-btn:active { border-color: var(--amber); }
.lo-avfs-hint {
  flex: 0 0 auto; margin-top: 8px; text-align: center;
  font-size: 10px; letter-spacing: 1.6px; color: var(--amber-dim);
}
/* Static-portrait fallback (narrow phones / no WebGL): nothing to turn, so the
   turn controls don't pretend otherwise. */
.lo-avfs-static .lo-avfs-turn,
.lo-avfs-static .lo-avfs-spin,
.lo-avfs-static .lo-avfs-front { display: none; }

.lo-eq-play { padding: 0 0 10px; }
.lo-eq-play-hero { margin-top: 4px; }
.lo-eq-play-exotics { display: flex; flex-direction: column; gap: 4px; margin: 2px 16px 10px; }
.lo-eq-play-exotics-empty { display: none; }
.lo-eq-play-exotic { font-size: 11px; line-height: 1.45; letter-spacing: 0.4px; }
.lo-eq-play-exotic-name { font-weight: 700; letter-spacing: 1.2px; margin-right: 7px; }
.lo-eq-play-exotic-desc { color: var(--amber-dim); }
/* The strip now sits standalone between ARMOR and YOUR FATEFORGED (playtest
   2026-08-04) rather than nested at the tail of HOW YOUR BUILD PLAYS — it no
   longer wants the base rule's sticky-header behavior (there's no scroll
   region it should pin to mid-panel) or the tight VAULT padding. */
.equipped-panel > .diag-strip {
  position: static;
  margin: 4px 16px 14px;
  padding: 8px 14px;
  border: 1px solid var(--green-dim);
}

/* Dense EQUIPPED / vault glance tiles — taller cards so the full-width NAME row
   sits above the meta | element | perks row (weapon-card feedback 2026-07-18). */
.lo-eq-glance {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 86px; padding: 10px 13px; text-align: left;
  cursor: pointer; font-family: inherit; text-transform: uppercase;
  color: var(--cream, #f0e6c8);
  background: rgba(255, 255, 255, .03);
  border: 1px solid color-mix(in srgb, var(--eq-rc, var(--green-dim)) 55%, transparent);
  border-left: 3px solid var(--eq-rc, var(--amber));
  border-radius: 6px;
}
.lo-eq-glance:hover, .lo-eq-glance.ui-focused {
  border-color: var(--eq-rc, var(--amber));
  background: rgba(255, 176, 0, .06);
}
.lo-eq-g-icon {
  flex: 0 0 auto; width: 58px; height: 58px; align-self: center;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.lo-eq-g-icon svg { width: 100%; height: 100%; display: block; }
.lo-eq-g-glyph {
  font-size: 44px; line-height: 1; color: var(--eq-rc, var(--amber));
}
/* Body: NAME + meta grow on the left; the hero band (perks / chips / stats)
   sits on the right, top-aligned so it reads as one column. */
.lo-eq-g-body {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 10px;
}
.lo-eq-g-main {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: 3px; justify-content: center;
}
.lo-eq-g-eyebrow {
  font-size: 8.5px; letter-spacing: 1.6px; font-weight: 700;
  color: var(--amber); opacity: .75;
}
.lo-eq-g-name {
  font-size: 15px; font-weight: 700; letter-spacing: .4px; line-height: 1.15;
  color: var(--cream, #f0e6c8);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lo-eq-glance-class .lo-eq-g-name { white-space: normal; }

/* Stacked glance body (weapon/ability/armor): row 1 = full-width NAME spanning
   over the element badge + perk chips, row 2 = meta | element | hero chips.
   Class tiles keep the flat single-row body. */
.lo-eq-g-body.lo-eq-g-stack {
  flex-direction: column; align-items: stretch; gap: 4px;
  align-self: center;
}
.lo-eq-g-stack > .lo-eq-g-name {
  white-space: normal; overflow: visible; text-overflow: clip;
}
.lo-eq-g-row {
  display: flex; align-items: center; gap: 10px; min-width: 0;
}
.lo-eq-g-row .lo-eq-g-main { gap: 2px; }
.lo-eq-g-meta {
  display: flex; align-items: center; gap: 5px; min-width: 0;
  font-size: 10.5px; letter-spacing: .7px; color: var(--ink-dim, #a99fc7);
}
.lo-eq-g-meta-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lo-eq-g-pip {
  flex: 0 0 auto; width: 13px; height: 13px;
  display: inline-flex; align-items: center; justify-content: center;
}
.lo-eq-g-pip svg { width: 100%; height: 100%; display: block; }

/* Middle column — the element badge: big centered sigil over its name. */
.lo-eq-g-elem {
  flex: 0 0 auto; align-self: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; min-width: 52px; padding: 0 6px;
}
.lo-eq-g-elem-icon {
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
}
.lo-eq-g-elem-icon svg { width: 100%; height: 100%; display: block; }
.lo-eq-g-elem-label {
  font-size: 9.5px; font-weight: 700; letter-spacing: 1px; line-height: 1;
  white-space: nowrap;
}
/* Narrow single-column (phone portrait): the middle badge goes ICON-ONLY so the
   card name reclaims that width instead of ellipsizing to a few characters. */
:root.eff-w-le-600 .lo-eq-g-elem { min-width: 0; padding: 0 2px; }
:root.eff-w-le-600 .lo-eq-g-elem-label { display: none; }

/* Hero band — perks (weapon), type chips (ability), stat chips (armor). */
.lo-eq-g-perks {
  flex: 0 0 auto; min-width: 0; max-width: 50%;
  display: flex; flex-direction: column; align-items: stretch; gap: 3px;
}
.lo-eq-g-perkchip {
  display: flex; flex-direction: row; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 4px;
  border: 1px solid color-mix(in srgb, var(--perk-rc, var(--green-dim)) 55%, transparent);
  border-left: 2px solid var(--perk-rc, var(--green-dim));
  background: color-mix(in srgb, var(--perk-rc, #10142a) 12%, rgba(10, 14, 42, .5));
  min-width: 0;
}
.lo-eq-g-perkchip-name {
  flex: 1 1 auto; min-width: 0;
  font-size: 12px; font-weight: 700; letter-spacing: .3px; line-height: 1.3;
  color: var(--cream, #f0e6c8);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Loop-verb triad icon (prime/detonate/fate) — the only role marker; no text.
   Sits to the RIGHT of the perk name; open the weapon to learn what it does. */
.lo-eq-g-perkchip-loopicon {
  flex: 0 0 auto; width: 13px; height: 13px; display: block;
}
.lo-eq-g-perkchip-empty {
  padding: 3px 8px; font-size: 10.5px; color: var(--ink-dim, #a99fc7); opacity: .5;
  border: 1px dashed var(--green-dim); border-radius: 4px; text-align: center;
}
.lo-eq-g-chips {
  flex: 0 0 auto; max-width: 52%;
  display: flex; flex-wrap: wrap; gap: 3px; align-items: center; justify-content: flex-end;
}
.lo-eq-g-chips-stats { justify-content: flex-end; }
.lo-eq-g-infochip {
  display: inline-block; padding: 2px 6px; border-radius: 3px;
  font-size: 8.5px; font-weight: 700; letter-spacing: .6px; line-height: 1.3;
  color: var(--cream, #f0e6c8);
  border: 1px solid color-mix(in srgb, var(--eq-rc, var(--green-dim)) 45%, transparent);
  background: rgba(10, 14, 42, .45);
}
.lo-eq-g-chip-kind { border-color: var(--eq-rc, var(--amber)); color: var(--eq-rc, var(--amber)); }
.lo-eq-g-chip-verb { border-color: var(--amber); color: var(--amber); }
.lo-eq-g-chip-stat { color: var(--green, #33ff66); border-color: var(--green-dim); }
.lo-eq-g-chip-role {
  border-color: var(--perk-rc, var(--amber)); color: var(--perk-rc, var(--amber));
}
/* EQUIPPED corner tab — floats on the card's top border like the class-ability
   "hold R3" bind tag, so it takes no space inside the card. */
.lo-eq-g-eqtab {
  position: absolute; top: -8px; right: 11px; z-index: 2;
  padding: 2px 8px; border-radius: 4px;
  font-size: 9px; font-weight: 700; letter-spacing: 1.3px;
  color: var(--green, #33ff66);
  border: 1px solid var(--green, #33ff66);
  background: color-mix(in srgb, var(--green, #33ff66) 14%, #0a0e2a);
}

/* L2 / R2 / hold R3 sit ABOVE the card so sibling cards stay aligned. */
.lo-eq-ability-wrap {
  display: flex; flex-direction: column; align-items: stretch; gap: 4px; min-width: 0;
}
.lo-eq-ability-wrap > .lo-eq-glance,
.lo-eq-ability-wrap > .lo-eq-tile { flex: 1 1 auto; min-width: 0; width: 100%; }
.lo-eq-bind-tag {
  flex: 0 0 auto; align-self: flex-start;
  min-width: 36px; padding: 3px 8px;
  text-align: center; font-size: 10px; font-weight: 700; letter-spacing: 1.5px;
  color: var(--amber); border: 1px solid var(--amber);
  background: rgba(255, 176, 0, .08); border-radius: 4px;
}
/* CLASS row: only the class-ability card carries a bind tag. Float it as a small
   corner tab (absolute → out of flow) so it steals no vertical space — all three
   class cards then keep equal height and top-aligned edges. */
.lo-eq-class .lo-eq-ability-wrap { position: relative; gap: 0; }
.lo-eq-class .lo-eq-ability-wrap > .lo-eq-bind-tag {
  position: absolute; top: -8px; right: 11px; z-index: 2;
  padding: 2px 8px; font-size: 9px; letter-spacing: 1.3px;
  background: color-mix(in srgb, var(--amber) 14%, #0a0e2a);
}

/* Weapon silhouettes in the build-loop diagram (gun perk nodes). */
.ld-node-sigil.svg-gear-icon,
.ld-node > .ld-node-sigil { width: 36px; height: 36px; flex-shrink: 0; }
.ld-node-sigil svg { width: 100%; height: 100%; display: block; }
.ld-fate-chip-engine { display: inline-flex; align-items: center; gap: 6px; }
.ld-fate-chip-gun { width: 22px; height: 22px; display: inline-block; vertical-align: middle; }
.ld-fate-chip-gun svg { width: 100%; height: 100%; display: block; }

/* ── Compact perk chips (EQUIPPED weapon tiles) ───────────────────────────── */
.bl-perk-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.bl-perk-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10.5px; padding: 1px 6px; border-radius: 3px;
  border: 1px solid var(--green-dim); background: rgba(10, 14, 42, .5); color: var(--cream);
}
.bl-perk-chip-name { font-weight: bold; letter-spacing: .02em; }
.bl-perk-chip-role { font-size: 8.5px; font-weight: bold; letter-spacing: .8px; opacity: .95; }
.bl-perk-chip.bl-perk-primer    { border-color: var(--rarity-rare); }
.bl-perk-chip.bl-perk-primer    .bl-perk-chip-role { color: var(--rarity-rare); }
.bl-perk-chip.bl-perk-trigger,
.bl-perk-chip.bl-perk-finisher  { border-color: var(--amber); }
.bl-perk-chip.bl-perk-trigger   .bl-perk-chip-role,
.bl-perk-chip.bl-perk-finisher  .bl-perk-chip-role { color: var(--amber); }
.bl-perk-chip.bl-perk-engine    { border-color: var(--green); }
.bl-perk-chip.bl-perk-engine    .bl-perk-chip-role { color: var(--green); }
.bl-perk-chip.bl-perk-amplifier { border-color: var(--elem-burn); }
.bl-perk-chip.bl-perk-amplifier .bl-perk-chip-role { color: var(--elem-burn); }

/* E1 (menus-refit-spec.md) — the ABILITIES-tab live loop ribbon (`.lo-ab-loop`)
   is gone; the build loop's one home is EQUIPPED now (B5). */
/* the HOW TO PLAY host was a <pre>; it now carries the numbered <ol>. */
.ab-howto-body { white-space: normal; font-family: inherit; margin: 0; }
.ab-howto-body .bl-howto-list { margin: 0; }

/* ── LOADOUTS-card gear rows (replaces the dense stat tables) ──────────────── */
.lo-card-gear-row {
  display: flex; flex-direction: column; gap: 4px;
  padding: 7px 0; border-bottom: 1px solid rgba(22, 32, 74, .6);
}
.lo-card-gear-head { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.lo-card-gear-slot {
  font-size: 10px; font-weight: bold; letter-spacing: 1px; color: var(--amber-dim);
  text-transform: uppercase; min-width: 52px;
}
.lo-card-gear-name { font-size: 14px; font-weight: bold; letter-spacing: .02em; }
.lo-card-weapon-block { margin-bottom: 10px; }
.lo-card-weapon-block .lo-card-gear-row { border-bottom: none; padding-bottom: 4px; }
.lo-card-weapon-block .bl-perks { margin-top: 2px; }
/* the gear rows reuse the EQUIPPED stat chips; give them a touch more room here */
.lo-card-gear-row .lo-eq-stats { margin-left: 59px; }

/* Vault card legibility on phones: bump the em base so the shared card's
   em-relative internals grow for mobile. Placed AFTER the base card-view rules
   so the same-specificity override wins on source order. */
@media (max-width: 820px) {
  .vault-panel[data-view="card"] .organizer-tbody      { font-size: calc(13.5px * var(--ui-scale, 1)); }
}

/* ── Portrait phones: larger card type ───────────────────────────────────────
   Cards already stack one-per-row at every width (base rule). On a phone in
   portrait we additionally bump the base font 11px→13px so the em card internals
   grow for mobile legibility. It rides the same net-zoom-1 pipeline as the
   default, so it still scales with --ui-scale. */
@media (orientation: portrait) and (max-width: 600px) {
  .vault-panel[data-view="card"] .organizer-tbody {
    font-size: calc(13px * var(--ui-scale, 1));
  }
}
