/* ============================================================
   IDENT // Infinity miniature identification dashboard
   ============================================================ */

/* ───── Self-hosted webfonts ─────
   These were previously loaded from fonts.googleapis.com / fonts.gstatic.com,
   which transmitted every visitor's IP to Google on first paint — before any
   consent banner could be acknowledged. Under EU rules that's a third-party
   transfer that requires prior consent (see LG München, 20 Jan 2022 re:
   Google Fonts). Both families are OFL-licensed, so self-hosting is allowed.
   Files in /wwwroot/fonts/ are static woff2 from Google's CDN with the latin
   subset only (≈54 KB total) — enough for English catalog content.
   font-display: swap mirrors what Google's CSS API requested. */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/space-grotesk-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/jetbrains-mono-latin.woff2') format('woff2');
}

:root {
  --bg-0: oklch(0.16 0.012 240);
  --bg-1: oklch(0.20 0.012 240);
  --bg-2: oklch(0.24 0.014 240);
  --bg-3: oklch(0.28 0.016 240);
  --fg-0: oklch(0.96 0.005 240);
  --fg-1: oklch(0.82 0.008 240);
  --fg-2: oklch(0.62 0.010 240);
  --fg-3: oklch(0.46 0.012 240);
  --line-1: oklch(0.32 0.014 240);
  --line-2: oklch(0.40 0.016 240);
  --accent-hue: 220;
  --accent: oklch(0.78 0.14 var(--accent-hue));
  --accent-fg: oklch(0.85 0.16 var(--accent-hue));
  --accent-dim: oklch(0.78 0.14 var(--accent-hue) / 0.18);
  --accent-line: oklch(0.78 0.14 var(--accent-hue) / 0.45);
  --accent-soft: oklch(0.78 0.14 var(--accent-hue) / 0.55);
  /* Want = wishlist orange. Same hue family as --warn but a separate name because
     they mean different things (warn = OOP / production status; want = wishlist match). */
  --want:      oklch(0.78 0.14 60);
  --want-line: oklch(0.78 0.14 60 / 0.45);
  --want-dim:  oklch(0.78 0.14 60 / 0.14);
  /* Good = active production status (green). */
  --good:      oklch(0.78 0.14 150);
  --good-line: oklch(0.78 0.14 150 / 0.45);
  --good-dim:  oklch(0.78 0.14 150 / 0.14);
  --warn: oklch(0.78 0.14 60);
  --warn-dim: oklch(0.78 0.14 60 / 0.14);
  /* Bad = destructive action red. Used by ConfirmDialog's destructive variant. */
  --bad:      oklch(0.78 0.14 30);
  --bad-line: oklch(0.78 0.14 30 / 0.45);
  --bad-dim:  oklch(0.78 0.14 30 / 0.14);
  --ff-sans: "Space Grotesk", system-ui, sans-serif;
  --ff-mono: "JetBrains Mono", ui-monospace, monospace;
  --r-sm: 2px;
  --r-md: 4px;
  --r-lg: 8px;
  /* ── Responsive scale ──
     --page-gutter is the horizontal padding applied to every top-level
     region that sits flush with the viewport edge (topbar, faction-bar,
     compare-mode-banner, sheet). Using one token keeps the page's left
     edge perfectly aligned across those regions at every viewport width.
     The clamp tightens the gutter continuously below ~1280px down to a
     16px floor that is already mobile-friendly.

     --bp-narrow is the discrete breakpoint at which structural changes
     kick in (today: the topbar title text-collapse from "UNIT
     IDENTIFICATION" to "IDENT"). CSS @media rules can't read custom
     properties, so the literal 1180px is repeated in each media query
     that uses it — keep them aligned with the value below. */
  --page-gutter: clamp(16px, 2.5vw, 32px);
  /* --bp-narrow: 1180px (reference-only — see comment above) */
}

/* ───── Reduced-motion override ─────
   Disables every animation and transition site-wide when the OS / browser
   sets prefers-reduced-motion: reduce. ~0ms duration rather than 0ms so any
   logic relying on transitionend events still fires. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

/* ───── Focus visibility — base rule ─────
   Native interactive elements get the same 2px accent outline at 2px offset
   as the existing .toggle / .cta-primary / .cta-secondary primitives.
   Custom interactive elements (with role="button" or @onclick) and
   component-specific styles should follow the same pattern via the
   utility-class block below. */
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[role="button"]:focus-visible,
[role="checkbox"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ───── Skeleton placeholder ───── */
.skeleton {
  background: var(--bg-2);
  border-radius: var(--r-sm);
  animation: skeletonPulse 1.5s ease-in-out infinite;
}
@keyframes skeletonPulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 0.80; }
}

/* ───── Skeleton card variants ───── */
.skeleton-unit-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 12px;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  width: var(--uc-w, 141px);
  /* Match approximate dimensions of UnitCard (silhouette grid) */
}
.skeleton-unit-card .sk-image  { height: var(--uc-img-h, 208px); aspect-ratio: auto; }
.skeleton-unit-card .sk-name   { height: 12px; width: 70%; }
.skeleton-unit-card .sk-sub    { height: 10px; width: 50%; }
.skeleton-unit-card .sk-tags   { height: 14px; width: 80%; }

.skeleton-product-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  width: 100%;
  min-height: 320px;
}
.skeleton-product-card .sk-head-row {
  display: grid;
  grid-template-columns: 88px 1fr auto;
  gap: 16px;
  align-items: center;
}
.skeleton-product-card .sk-thumb { width: 88px; aspect-ratio: 1 / 1; }
.skeleton-product-card .sk-title { height: 14px; width: 60%; margin-bottom: 6px; }
.skeleton-product-card .sk-meta  { height: 10px; width: 40%; }
.skeleton-product-card .sk-pill  { width: 60px; height: 20px; }
.skeleton-product-card .sk-sculpts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
  gap: 14px 10px;
  margin-top: 8px;
}
.skeleton-product-card .sk-sculpt { height: 92px; }

/* ───── State-swap fade-in ───── */
.fade-in { animation: fadeIn 180ms ease-out; }
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Per-faction accent scope — wraps the catalog UI plus its sibling drawer / modals / rail.
   The wrapper sets --accent-hue inline (style="--accent-hue: <faction>"); we redeclare the
   accent family here so the var(--accent-hue) substitutions inside --accent / --accent-dim /
   --accent-line / --accent-soft / --accent-fg re-resolve against the per-faction hue rather
   than inheriting the resolved cyan values from :root. Same pattern as .products-section
   (~line 2020) and .sculpt (~line 2226). */
.accent-scope {
  --accent:      oklch(0.78 0.14 var(--accent-hue));
  --accent-dim:  oklch(0.78 0.14 var(--accent-hue) / 0.18);
  --accent-line: oklch(0.78 0.14 var(--accent-hue) / 0.45);
  --accent-soft: oklch(0.78 0.14 var(--accent-hue) / 0.55);
  --accent-fg:   oklch(0.85 0.16 var(--accent-hue));
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg-0);
  color: var(--fg-0);
  font-family: var(--ff-sans);
  font-size: 14px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  overflow-x: hidden;
}
button { font-family: inherit; color: inherit; background: none; border: 0; cursor: pointer; padding: 0; }
input { font-family: inherit; }
.mono { font-family: var(--ff-mono); letter-spacing: 0.02em; }

/* ── IDENT app shell ── */
.ident-app {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 240px 1fr;
}

/* ── Sidebar ── */
.sidebar {
  border-right: 1px solid var(--line-1);
  background: var(--bg-1);
  padding: 20px 16px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.brand { display:flex; align-items:center; gap:10px; padding-bottom:14px; border-bottom:1px solid var(--line-1); }
.brand-mark {
  width:28px; height:28px; border:1px solid var(--accent);
  background:var(--accent-dim); display:grid; place-items:center; position:relative;
}
.brand-mark::before { content:""; position:absolute; inset:4px; border:1px solid var(--accent); transform:rotate(45deg); }
.brand-name { font-family:var(--ff-mono); font-weight:700; font-size:13px; letter-spacing:0.16em; }
.brand-sub  { font-family:var(--ff-mono); font-size:9px; letter-spacing:0.14em; color:var(--fg-3); margin-top:2px; }

.section-label {
  font-family:var(--ff-mono); font-size:11px; letter-spacing:0.18em; color:var(--fg-3);
  margin-bottom:8px; display:flex; justify-content:space-between; align-items:baseline;
}
.section-count { color:var(--accent); }

.faction-list, .filter-list { display:flex; flex-direction:column; gap:2px; }
.faction-row, .filter-row {
  display:flex; align-items:center; gap:8px; padding:6px 8px;
  border-radius:var(--r-sm); font-size:12px; color:var(--fg-1);
  cursor:pointer; border:1px solid transparent;
  /* width + text-align defaults are wrong on <button>; reset so a <button class="filter-row">
     fills its column and reads left-aligned like the div version did. */
  width:100%; text-align:left;
  transition:background .12s,border-color .12s,color .12s;
}
.faction-row:hover,.filter-row:hover { background:var(--bg-2); color:var(--fg-0); }
.faction-row.is-active,.filter-row.is-active { background:var(--bg-2); border-color:var(--accent-line); color:var(--fg-0); }
.filter-row.is-active .check { background:var(--accent); border-color:var(--accent); }
.filter-row.is-active .check::after { content:""; position:absolute; inset:2px; background:var(--bg-0); }
.faction-row.is-active .check { background:var(--accent); border-color:var(--accent); }
.faction-row.is-active .check::after { content:""; position:absolute; inset:2px; background:var(--bg-0); }
.check { width:12px; height:12px; border:1px solid var(--line-2); border-radius:1px; position:relative; flex-shrink:0; }
.code-tag { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.1em; color:var(--fg-3); margin-left:auto; }
.faction-row.is-active .code-tag,.filter-row.is-active .code-tag { color:var(--accent); }
.logic-toggle {
  display:flex; border:1px solid var(--line-1); border-radius:var(--r-sm);
  font-family:var(--ff-mono); font-size:11px; letter-spacing:0.14em; margin-bottom:8px; overflow:hidden;
}
.logic-toggle button { flex:1; padding:6px; color:var(--fg-2); background:transparent; border-right:1px solid var(--line-1); }
.logic-toggle button:last-child { border-right:0; }
/* Selection: parent's data-current matches the button's data-value */
.logic-toggle[data-current="OR"]  button[data-value="OR"],
.logic-toggle[data-current="AND"] button[data-value="AND"] {
  background:var(--accent-dim);
  color:var(--accent-fg);
  font-weight:600;
}

.clear-btn { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.06em; color:var(--fg-3); padding:4px 0; text-align:left; }
.clear-btn:hover { color:var(--accent); }

/* ── Main panel ── */
.ident-main { padding:0; min-width:0; display:flex; flex-direction:column; height:100vh; overflow-y:auto; }

.topbar {
  position:sticky; top:0; z-index:10;
  background:oklch(from var(--bg-0) l c h / 0.92);
  backdrop-filter:blur(8px); border-bottom:1px solid var(--line-1);
  padding:10px var(--page-gutter); display:flex; gap:clamp(8px, 1vw, 16px); align-items:center; flex-shrink:0;
}
.topbar-title { display:flex; align-items:baseline; gap:12px; }
.topbar-title h1 { margin:0; font-size:20px; font-weight:600; letter-spacing:0.04em; }
.topbar-title .sub { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.14em; color:var(--fg-3); }
.spacer { flex:1; }

.search {
  display:flex; align-items:center; gap:8px; background:var(--bg-1);
  border:1px solid var(--line-1); border-radius:var(--r-sm); padding:6px 10px; width:clamp(200px, 24vw, 280px);
  transition:border-color .12s;
}
.search:focus-within { border-color:var(--accent-line); }
.search input { flex:1; min-width:0; background:none; border:0; outline:none; color:var(--fg-0); font-size:13px; }
.search input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.search-icon { color:var(--fg-3); display:grid; place-items:center; }

.iconbtn {
  width:32px; height:32px; border:1px solid var(--line-1); border-radius:var(--r-sm);
  display:grid; place-items:center; color:var(--fg-1); background:var(--bg-1);
  flex-shrink: 0;
}
.iconbtn:hover { border-color:var(--accent-line); color:var(--fg-0); }
.iconbtn[data-active="True"], .iconbtn.is-active { background:var(--accent-dim); border-color:var(--accent-line); color:var(--fg-0); }

/* ── Narrow-desktop title collapse ──
   Below the --bp-narrow cliff (1180px — see :root), the catalog topbar
   title shortens from "UNIT IDENTIFICATION" to "IDENT" and drops the
   version suffix. We do this in CSS rather than in Razor so the DOM
   keeps the full string and screen readers still announce it. The
   ::before approach replaces the visual rendering only; assistive tech
   correctly treats generated content as decorative and reads the real
   <h1> text. */
@media (max-width: 1180px) {
  .topbar-title h1 { font-size: 0; line-height: 0; }
  .topbar-title h1::before {
    content: "IDENT";
    font-size: 20px;
    line-height: normal;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--fg-0);
  }
  .topbar-title .sub { display: none; }
}

/* Density segmented control — sits in the catalog topbar between the
   compare button and the PRODUCTS link. Cells share .iconbtn-ish dimensions
   so the topbar height stays steady. */
.density-toggle {
  display:inline-flex; height:32px;
  flex-shrink: 0;
  border:1px solid var(--line-1); border-radius:var(--r-sm);
  background:var(--bg-1); overflow:hidden;
}
.density-toggle .density-cell {
  font-family:var(--ff-mono); font-size:11px; letter-spacing:0.14em;
  color:var(--fg-1); background:transparent; border:0;
  padding:0; width:28px; cursor:pointer;
  border-right:1px solid var(--line-1);
  transition:background .12s,color .12s;
}
.density-toggle .density-cell:last-child { border-right:0; }
.density-toggle .density-cell:hover { color:var(--fg-0); }
.density-toggle .density-cell.is-active {
  background:var(--accent-dim); color:var(--fg-0);
}
.density-toggle .density-cell:focus-visible {
  outline: 2px solid var(--accent); outline-offset: -2px;
}

/* ── Faction bar ── */
.faction-bar {
  position:sticky; top:53px; z-index:9;
  background:oklch(from var(--bg-0) l c h / 0.92);
  backdrop-filter:blur(8px); border-bottom:1px solid var(--line-1);
  padding:8px var(--page-gutter); display:flex; align-items:center; gap:12px; flex-shrink:0;
}
.faction-bar .label { font-family:var(--ff-mono); font-size:10px; letter-spacing:0.18em; color:var(--fg-3); border-right:1px solid var(--line-1); padding-right:12px; }
.faction-switcher { display:flex; gap:2px; flex:1; flex-wrap:wrap; }
.faction-switcher button {
  --fh: 220; display:flex; align-items:baseline; gap:8px; padding:6px 10px;
  border-radius:var(--r-sm); white-space:nowrap; border:1px solid transparent;
  background:var(--bg-1); transition:background .12s,border-color .12s;
}
.faction-switcher button .fcode { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.16em; color:oklch(0.78 0.14 var(--fh)); opacity:.7; }
.faction-switcher button .fname { font-size:12px; letter-spacing:0.04em; color:var(--fg-2); }
.faction-switcher button:hover { background:var(--bg-2); border-color:var(--line-1); }
.faction-switcher button:hover .fname { color:var(--fg-0); }
.faction-switcher button[data-active="True"], .faction-switcher button.is-active { background:oklch(0.78 0.14 var(--fh) / 0.18); border-color:oklch(0.78 0.14 var(--fh) / 0.55); }
.faction-switcher button[data-active="True"] .fcode, .faction-switcher button.is-active .fcode { opacity:1; }
.faction-switcher button[data-active="True"] .fname, .faction-switcher button.is-active .fname { color:var(--fg-0); }

.compare-mode-banner {
  background:var(--accent-dim); border-bottom:1px solid var(--accent-line);
  padding:8px var(--page-gutter); font-family:var(--ff-mono); font-size:11px; letter-spacing:0.16em; color:var(--fg-0);
}

/* ── Sheet ── */
.sheet { padding:clamp(20px, 2.5vw, 32px); display:flex; flex-direction:column; gap:28px; }

.sheet-header { display:flex; align-items:center; gap:20px; border-bottom:1px solid var(--line-1); padding-bottom:24px; }
.sheet-mark {
  width:64px; height:64px; border:1px solid var(--accent); position:relative;
  display:grid; place-items:center; background:var(--accent-dim); flex-shrink:0;
}
.sheet-mark::before { content:""; position:absolute; inset:8px; border:1px solid var(--accent); transform:rotate(45deg); }
.sheet-mark::after { content:""; position:absolute; width:18px; height:18px; border:1px solid var(--accent); border-radius:50%; }
.sheet-title { display:flex; flex-direction:column; gap:4px; }
.sheet-title .crumbs { font-family:var(--ff-mono); font-size:10px; letter-spacing:0.18em; color:var(--fg-3); }
.sheet-title h2 { margin:0; font-size:36px; font-weight:600; letter-spacing:0.04em; line-height:1; }
.sheet-title .desc { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.18em; color:var(--fg-2); margin-top:4px; }
.sheet-meta { margin-left:auto; display:grid; grid-template-columns:auto auto; gap:4px 16px; font-family:var(--ff-mono); font-size:11px; }
.sheet-meta dt { color:var(--fg-3); letter-spacing:0.12em; }
.sheet-meta dd { margin:0; color:var(--fg-1); }

/* ── Silhouette rows — masonry-ish 12-col grid so small rows sit side-by-side ── */
/* Silhouette bands flow horizontally and wrap, each one sized to its own content rather
   than reserving a fixed grid track. A 1-unit silhouette stays narrow and sits next to
   other narrow ones; a many-unit silhouette gets its own line. The .span-N classes set
   from IdentSheet.razor are inert here (they used to size 12-col grid tracks) — left in
   place to avoid touching the markup, but they don't drive layout anymore. */
.silhouette-grid {
  display: flex; flex-wrap: wrap;
  gap: 24px;
  align-items: flex-start;
}
.silhouette-row {
  display: grid; grid-template-columns: 36px 1fr; gap: 14px;
  padding-top: 16px;
  position: relative; min-width: 0;
  flex: 0 0 auto;       /* size to content */
  max-width: 100%;      /* but never overflow the grid — clusters inside wrap if needed */
}

.silhouette-label {
  font-family:var(--ff-mono); font-size:13px; letter-spacing:0.2em; color:var(--fg-2);
  writing-mode:vertical-rl; transform:rotate(180deg);
  display:flex; align-items:flex-start; padding-top:8px; position:relative;
}
.silhouette-label::after { content:""; position:absolute; top:5px; left:50%; width:1px; height: var(--uc-img-h, 208px); background:var(--accent-line); }

/* Each cluster is sized by its own units row, not by an equal grid column — so a 1-unit
   cluster stays narrow and a 4-unit cluster stretches wide, both side-by-side until the
   silhouette-row fills. Eliminates the dead space that grid auto-fit was reserving. */
.role-clusters { display:flex; flex-wrap:wrap; gap:8px 20px; align-content:flex-start; }
.role-cluster { flex:0 0 auto; display:flex; flex-direction:column; gap:12px; padding:6px 0; min-width: var(--uc-min, 124px); max-width:100%; }
.role-cluster .role-label {
  /* Cluster width is constrained by the unit cards underneath (~140px).
     Letter-spacing dropped to 0 to keep longer labels ("Spec. Trained
     Troops 01") within the cluster width. */
  font-family:var(--ff-mono); font-size:10px; letter-spacing:0; color:var(--fg-2);
  border-bottom:1px solid var(--line-1); padding-bottom:8px;
  display:flex; justify-content:space-between;
}
.role-cluster .role-count { color:var(--fg-3); }
.role-cluster .units { display:flex; flex-wrap:wrap; gap:4px; }

/* Card-density steps. Variables consumed by .unit, .unit-img, .role-cluster,
   .silhouette-label::after and .skeleton-unit-card. The default block matches
   today's hardcoded values so a .sheet without [data-density] renders identically
   to pre-refactor markup. */
.sheet                    { --uc-w:140px; --uc-img-h:208px; --uc-min-h:288px; --uc-min:124px; }
.sheet[data-density="xs"] { --uc-w: 96px; --uc-img-h:144px; --uc-min-h:188px; --uc-min: 88px; }
.sheet[data-density="s"]  { --uc-w:116px; --uc-img-h:172px; --uc-min-h:240px; --uc-min:104px; }
.sheet[data-density="l"]  { --uc-w:168px; --uc-img-h:248px; --uc-min-h:336px; --uc-min:148px; }
.sheet[data-density="xs"] .unit-sub,
.sheet[data-density="xs"] .unit-badges { display:none; }
.sheet[data-density="xs"] .unit-name { font-size:11px; }

/* ── Unit card ── */
.unit {
  display:flex; flex-direction:column; align-items:center; gap:5px;
  padding:0px 0px 8px;
  width: var(--uc-w, 140px);
  min-height: var(--uc-min-h, 288px);
  border:1px solid transparent; border-radius:var(--r-sm);
  cursor:pointer; position:relative;
  transition:background .12s,border-color .12s,box-shadow .12s;
}
.unit:hover { background:var(--bg-1); border-color:var(--line-1); }
.unit[data-compare="True"]::before {
  content:""; position:absolute; top:4px; left:4px;
  width:10px; height:10px; background:var(--accent); border:1px solid var(--bg-0);
}
.unit[data-expanded="True"] { background:var(--bg-1); border-color:var(--accent-line); z-index:5; }

/* The figure IS the card. No inner widget framing — no border, no heavy backdrop. State
   indicators (owned / wanted / legacy) light up the whole card via .unit, not an inner box.
   A barely-there ellipse highlight gives the figure a hint of vignette so it doesn't sit
   dead-flat on the card. */
.unit-img {
  width:100%;
  height: var(--uc-img-h, 208px);
  border-radius:var(--r-sm);
  background:radial-gradient(ellipse at 50% 28%, oklch(1 0 0 / 0.04), transparent 65%);
  border:0; position:relative; overflow:hidden;
  display:grid; place-items:center;
}
/* Image children of any of the figure surfaces inherit the portrait fit + parent radius. */
    .unit-img > img,
    .drawer-img > img,
    .foldout-thumb > img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        border-radius: inherit;
    }
.placeholder-glyph { font-family:var(--ff-mono); font-size:9px; letter-spacing:0.16em; color:var(--fg-3); text-align:center; position:relative; z-index:1; padding:0 6px; }
/* Empty state: when a unit has no featured image, fill the box with the #mini silhouette
   (defined in App.razor) plus a horizontal accent scan line — same idiom as .sculpt-img.empty. */
.unit-img.empty svg {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%; height: 100%;
  filter: drop-shadow(0 3px 6px oklch(0.06 0.010 240 / 0.6));
}
.unit-img.empty::after {
  content: "";
  position: absolute;
  top: 50%; left: 0; right: 0;
  height: 1px;
  background: var(--accent-soft);
  opacity: 0.45;
  z-index: 1;
}

.unit-status {
  position:absolute; bottom:4px; right:4px; font-family:var(--ff-mono);
  font-size:11px; letter-spacing:0.12em; color:var(--warn);
  border:1px solid var(--warn); padding:1px 4px; background:var(--bg-0);
  z-index:2;
}

.multi-sculpt-marker {
  position:absolute; top:4px; left:4px; font-size:11px; letter-spacing:0.08em;
  color:var(--accent); border:1px solid var(--accent-line); padding:1px 4px;
  background:var(--bg-0); display:flex; align-items:center; gap:3px; z-index:1; border-radius:1px;
}
.multi-sculpt-marker:hover { background:var(--accent); color:var(--bg-0); }
.unit[data-expanded="True"] .multi-sculpt-marker { background:var(--accent); color:var(--bg-0); }

/* Sculpt foldout — absolute popover anchored to the right (or left) of the card */
.sculpt-foldout {
  position:absolute; top:-1px;
  background:var(--bg-1); border:1px solid var(--accent-line);
  border-radius:var(--r-sm); padding:10px 12px;
  display:flex; flex-direction:column; gap:8px;
  /* Single horizontal row of thumbs — width grows to fit, capped to viewport so a unit
     with many sculpts scrolls inside the panel instead of running off-screen. */
  cursor:default; max-width:min(440px, calc(100vw - 24px));
  z-index:6; box-shadow:0 8px 24px oklch(0 0 0 / 0.5);
}
.unit[data-side="right"] .sculpt-foldout { left:calc(100% + 6px); }
.unit[data-side="left"]  .sculpt-foldout { right:calc(100% + 6px); }
.sculpt-foldout::before {
  content:""; position:absolute; top:14px; width:8px; height:8px;
  background:var(--bg-1); transform:rotate(45deg);
}
.unit[data-side="right"] .sculpt-foldout::before {
  left:-5px; border-left:1px solid var(--accent-line); border-bottom:1px solid var(--accent-line);
}
.unit[data-side="left"] .sculpt-foldout::before {
  right:-5px; border-right:1px solid var(--accent-line); border-top:1px solid var(--accent-line);
}
.foldout-label { font-size:9px; letter-spacing:0.18em; color:var(--accent); }
/* Horizontal row of sculpt thumbs. Each cell holds its natural size (flex-shrink:0) so
   uniformly portrait — many-sculpt units scroll horizontally inside the panel. */
.foldout-list { display:flex; flex-direction:row; gap:10px; overflow-x:auto; padding-bottom:2px; }
.foldout-sculpt { flex:0 0 auto; display:flex; flex-direction:column; align-items:center; gap:4px; background:var(--bg-1); border:1px solid var(--line-1); border-radius:var(--r-sm); width:88px; }
/* Thumb mirrors the new card aesthetic — no inner border, subtle ellipse highlight only,
   portrait ratio matching the main .unit-img (116:208 ≈ 80:144). */
.foldout-thumb { height:112px; border-radius:var(--r-sm); background:radial-gradient(ellipse at 50% 28%, oklch(1 0 0 / 0.04), transparent 65%); border:0; display:grid; place-items:center; overflow:hidden; }
.foldout-name { font-size:11px; letter-spacing:0.04em; color:var(--fg-1); text-align:center; line-height:1.3; }
.foldout-year { font-size:11px; letter-spacing:0.14em; color:var(--fg-3); }

.unit-name { font-size:12px; font-weight:500; text-align:center; letter-spacing:0.02em; color:var(--fg-0); }
.unit-sub  { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.12em; color:var(--fg-3); }

.unit-badges { display:flex; gap:3px; flex-wrap:wrap; justify-content:center; margin-top:auto; }
.sect-badge {
  font-family:var(--ff-mono); font-size:11px; letter-spacing:0.1em;
  padding:1px 4px; border:1px solid var(--line-2); color:var(--fg-2);
  border-radius:1px; background:var(--bg-1); cursor:pointer;
}
.sect-badge:hover { border-color:var(--accent-line); color:var(--fg-0); }
.sect-badge[data-active="True"], .sect-badge.is-active { background:var(--accent); color:var(--bg-0); border-color:var(--accent); }

/* ── Detail drawer ── */
.drawer-scrim { position:fixed; inset:0; background:oklch(0 0 0 / 0.5); opacity:0; pointer-events:none; transition:opacity .2s; z-index:40; }
.drawer-scrim[data-open="True"],.drawer-scrim.is-open { opacity:1; pointer-events:auto; }

.drawer {
  position:fixed; top:0; right:0; bottom:0; width:480px; max-width:92vw;
  background:var(--bg-1); border-left:1px solid var(--line-1); z-index:50;
  transform:translateX(100%); transition:transform .24s cubic-bezier(.2,.7,.2,1);
  display:flex; flex-direction:column;
}
.drawer[data-open="True"],.drawer.is-open { transform:translateX(0); }

.drawer-head { padding:20px 24px; border-bottom:1px solid var(--line-1); display:flex; align-items:flex-start; gap:14px; }
.drawer-close { margin-left:auto; width:28px; height:28px; border:1px solid var(--line-1); display:grid; place-items:center; color:var(--fg-2); }
.drawer-close:hover { color:var(--accent); border-color:var(--accent-line); }

.drawer-img {
  width:104px; height:140px; border-radius:var(--r-sm);
  background:radial-gradient(circle at 50% 30%,var(--bg-3),var(--bg-2));
  border:1px solid var(--accent-line); display:grid; place-items:center; flex-shrink:0;
  overflow:hidden;
  font-family:var(--ff-mono); font-size:9px; letter-spacing:0.14em; color:var(--fg-3);
}
.drawer-id { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.18em; color:var(--accent); }
.drawer h3 { margin:4px 0 2px; font-size:24px; font-weight:600; letter-spacing:0.02em; }
.drawer-sub { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.14em; color:var(--fg-3); }

.drawer-body { padding:20px 24px; overflow-y:auto; flex:1; display:flex; flex-direction:column; gap:24px; }
.drawer-block { display:flex; flex-direction:column; gap:8px; }
.drawer-block-head { display:flex; align-items:baseline; justify-content:space-between; border-bottom:1px solid var(--line-1); padding-bottom:6px; margin-bottom:4px; }
.drawer-block-head .k { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.18em; color:var(--fg-2); }
.drawer-block-head .k-count { font-size:11px; color:var(--accent); letter-spacing:0.14em; }
.drawer-tiny { font-size:11px; letter-spacing:0.14em; color:var(--fg-3); }

.spec-row { display:grid; grid-template-columns:92px 1fr; gap:12px; padding:8px 0; border-top:1px solid var(--line-1); align-items:center; }
.spec-row .k { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.16em; color:var(--fg-3); }
.spec-row .v { font-size:13px; color:var(--fg-0); }

.tag-row { display:flex; flex-wrap:wrap; gap:6px; }
.tag-pill { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.12em; padding:4px 8px; border:1px solid var(--line-2); color:var(--fg-1); background:var(--bg-2); cursor:pointer; }
.tag-pill:hover { border-color:var(--accent); color:var(--fg-0); }
.tag-pill[data-active="True"], .tag-pill.is-active { background:var(--accent); color:var(--bg-0); border-color:var(--accent); }

.status-pill { display:inline-flex; align-items:center; gap:6px; font-family:var(--ff-mono); font-size:11px; letter-spacing:0.16em; padding:3px 8px; border:1px solid var(--line-2); }
.status-pill.active { color:oklch(0.78 0.14 150); border-color:oklch(0.78 0.14 150 / 0.5); }
.status-pill.oop { color:var(--warn); border-color:oklch(0.78 0.14 60 / 0.5); }
.status-pill::before { content:""; width:6px; height:6px; border-radius:50%; background:currentColor; }

.sculpt-list { display:flex; flex-direction:column; gap:6px; }
.sculpt-row {
  display:flex; align-items:center; gap:12px; padding:6px 8px;
  background:var(--bg-2); border:1px solid var(--line-1); border-radius:var(--r-sm);
  cursor:pointer; text-align:left; width:100%; position:relative;
  transition:border-color .12s,background .12s,opacity .12s;
}
.sculpt-row:hover { border-color:var(--accent-line); }
.sculpt-row[data-active="True"], .sculpt-row.is-active { background:var(--accent-dim); border-color:var(--accent-line); }
.sculpt-row[data-dim="True"], .sculpt-row.is-dim { opacity:.45; }
.sculpt-marker { width:6px; height:6px; border-radius:50%; background:var(--line-2); margin-left:auto; transition:background .12s,box-shadow .12s; }
.sculpt-row[data-active="True"] .sculpt-marker, .sculpt-row.is-active .sculpt-marker { background:var(--accent); box-shadow:0 0 8px var(--accent); }

.link-btn { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.06em; color:var(--accent); }
.link-btn:hover { color:var(--fg-0); }
.sculpt-thumb { width:40px; height:52px; border-radius:var(--r-sm); background:radial-gradient(circle at 50% 30%,var(--bg-3),var(--bg-1)); border:1px solid var(--line-1); display:grid; place-items:center; flex-shrink:0; overflow:hidden; }
    .sculpt-thumb > img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        border-radius: inherit;
    }
.sculpt-meta { display:flex; flex-direction:column; gap:2px; min-width:0; }
.sculpt-name { font-size:13px; color:var(--fg-0); }

.product-list { display:flex; flex-direction:column; gap:8px; }
.product-card {
  display:grid; grid-template-columns:64px 1fr auto; gap:12px;
  padding:10px; background:var(--bg-2); border:1px solid var(--line-1);
  border-radius:var(--r-sm); text-decoration:none; color:inherit;
  transition:border-color .12s,background .12s; align-items:center;
}
.product-card:hover { border-color:var(--accent-line); background:var(--bg-3); }
.product-card[data-status="oop"] { opacity:.72; }
.product-card[data-status="oop"]:hover { opacity:1; }
.product-card[data-highlight="true"] { border-color:var(--accent); background:var(--accent-dim); box-shadow:0 0 0 1px var(--accent-line); }
.product-card[data-highlight="dim"] { opacity:.32; }
.product-card[data-highlight="dim"]:hover { opacity:.7; }

.product-thumb { width:64px; height:64px; background:var(--bg-1); border:1px solid var(--line-1); border-radius:var(--r-sm); position:relative; display:grid; place-items:center; overflow:hidden; }
.product-thumb img { width:100%; height:100%; object-fit:cover; }
.product-status-tag { position:absolute; bottom:2px; left:2px; font-family:var(--ff-mono); font-size:11px; letter-spacing:0.12em; padding:1px 4px; background:var(--bg-0); color:var(--warn); border:1px solid var(--warn); }
.product-meta { display:flex; flex-direction:column; gap:4px; min-width:0; }
.product-name { font-size:13px; font-weight:500; color:var(--fg-0); letter-spacing:0.02em; }
.product-contains { display:flex; flex-direction:column; gap:4px; }
.contains-list { display:flex; flex-wrap:wrap; gap:3px; }
.contains-chip { font-size:11px; letter-spacing:0.1em; padding:1px 5px; background:var(--bg-0); border:1px solid var(--line-1); color:var(--fg-2); border-radius:1px; }
.contains-chip[data-active="True"], .contains-chip.is-active { background:var(--accent); border-color:var(--accent); color:var(--bg-0); }
.product-cta { display:flex; align-items:center; gap:6px; font-family:var(--ff-mono); font-size:11px; letter-spacing:0.08em; color:var(--accent); padding:0 4px; }
.product-card:hover .product-cta { color:var(--fg-0); }

/* Split CTA stack on product cards inside the unit drawer */
.product-cta-stack { display:flex; flex-direction:column; gap:4px; align-self:center; }
.product-cta-btn {
  display:grid; place-items:center;
  font-family:var(--ff-mono);
  font-size:11px; letter-spacing:0.08em;
  padding:6px 10px;
  border:1px solid var(--line-1);
  background:var(--bg-1);
  color:var(--fg-2);
  text-decoration:none;
  border-radius:var(--r-sm);
  white-space:nowrap;
  transition:border-color 0.12s, color 0.12s, background 0.12s;
}
.product-cta-btn:hover { border-color:var(--accent-line); color:var(--accent-fg); background:var(--accent-dim); }
.product-cta-btn.content { /* default styling fits */ }
.product-cta-btn.store   { color:var(--accent-fg); }
.affiliate-disclosure { padding-top:8px; font-size:11px; letter-spacing:0.04em; color:var(--fg-3); line-height:1.5; }

/* ── Compare bar ── */
.compare-bar {
  position:fixed; bottom:16px; left:50%; transform:translateX(-50%) translateY(140%);
  /* Above the drawer-scrim (z:40) and drawer panel (z:50) so the bar is visible even when
     the drawer is open — users adding from inside the drawer need to see items land in the
     bar. Below the compare modal (z:60). */
  z-index:55; background:var(--bg-1); border:1px solid var(--accent-line);
  border-radius:var(--r-md); padding:12px 14px; display:flex; align-items:center; gap:12px;
  box-shadow:0 12px 40px oklch(0 0 0 / 0.6); transition:transform .24s cubic-bezier(.2,.7,.2,1);
  max-width:calc(100vw - 64px);
}
.compare-bar[data-open="True"] { transform:translateX(-50%) translateY(0); }
.compare-bar .label { font-family:var(--ff-mono); font-size:10px; letter-spacing:0.18em; color:var(--accent); border-right:1px solid var(--line-1); padding-right:12px; }
.compare-chips { display:flex; gap:6px; flex-wrap:wrap; }
.compare-chip { font-family:var(--ff-mono); font-size:11px; padding:4px 8px; border:1px solid var(--line-1); display:flex; align-items:center; gap:6px; background:var(--bg-2); }
.compare-chip .x { color:var(--fg-3); cursor:pointer; }
.compare-chip .x:hover { color:var(--accent); }

/* ── Compare modal ── */
/* Native <dialog> usage: the dialog itself fills the viewport (acting as the
   scrim host) so backdrop clicks can be detected by clicking the dialog
   element directly. The actual dim layer is provided by ::backdrop. */
.compare-modal { position:fixed; inset:0; background:transparent; z-index:60; padding:40px; overflow-y:auto; max-width:none; max-height:none; width:100%; height:100%; border:none; color:inherit; }
.compare-modal::backdrop { background:oklch(0 0 0 / 0.7); }
.compare-modal-inner { max-width:1200px; margin:0 auto; background:var(--bg-1); border:1px solid var(--line-1); }
.compare-modal-head { padding:18px 24px; display:flex; align-items:center; border-bottom:1px solid var(--line-1); }
.compare-modal-head h3 { margin:0; font-size:18px; letter-spacing:0.04em; }
.compare-modal-head .crumbs { font-family:var(--ff-mono); font-size:10px; letter-spacing:0.16em; color:var(--fg-3); margin-right:12px; }
.compare-grid { display:grid; font-size:13px; }
.compare-grid > div { padding:10px 14px; border-top:1px solid var(--line-1); border-right:1px solid var(--line-1); }
.compare-grid > div:last-child { border-right:0; }
.compare-grid .row-label { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.16em; color:var(--fg-3); background:var(--bg-2); }
.compare-grid .col-head { font-weight:600; font-size:14px; background:var(--bg-2); }
.compare-grid .col-head .sub { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.14em; color:var(--fg-3); margin-top:2px; }

/* ───── Confirm dialog ───── */
dialog.confirm-dialog {
  margin: auto;
  padding: 0;
  background: oklch(from var(--bg-0) l c h / 0.96);
  border: 1px solid var(--line-2);
  color: var(--fg-0);
  min-width: 360px;
  max-width: 480px;
  font-family: var(--ff-sans);
}
dialog.confirm-dialog::backdrop {
  background: oklch(0 0 0 / 0.55);
  backdrop-filter: blur(2px);
}
.confirm-dialog .cd-body {
  padding: 22px 24px 18px;
}
.confirm-dialog .cd-title {
  font-family: var(--ff-mono);
  font-size: 11px;
  font-weight: 600;
  /* Was 0.22em — distinctive headline tracking on a dialog title makes every
     "Are you sure?" prompt feel like a poster. 0.08em keeps mono+caps as an
     "important label" cue without shouting. */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 10px;
}
.confirm-dialog .cd-message {
  font-size: 14px;
  line-height: 1.5;
  color: var(--fg-1);
  margin: 0;
}
.confirm-dialog .cd-actions {
  padding: 14px 24px 18px;
  border-top: 1px solid var(--line-1);
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
.confirm-dialog .cd-btn {
  font-family: var(--ff-mono);
  font-size: 11px;
  font-weight: 600;
  /* Was 0.22em — buttons are interactive surfaces, not headlines. 0.06em keeps
     the mono-caps "uniform" feel without making "DELETE" or "CONFIRM" demand
     to be read in slow motion. */
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 9px 16px;
  cursor: pointer;
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--fg-1);
  transition: background .12s, border-color .12s, color .12s;
}
.confirm-dialog .cd-btn:hover {
  border-color: var(--accent-line);
  color: var(--fg-0);
}
.confirm-dialog .cd-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.confirm-dialog .cd-btn--confirm {
  background: var(--accent);
  border-color: var(--accent);
  color: oklch(0.10 0.012 240);
}
.confirm-dialog .cd-btn--confirm:hover {
  filter: brightness(1.12);
}
.confirm-dialog .cd-btn--destructive {
  background: var(--bad);
  border-color: var(--bad);
  color: oklch(0.10 0.012 30);
}
.confirm-dialog .cd-btn--destructive:hover {
  filter: brightness(1.12);
}

/* ── Empty / stub states ── */
/* ───── Empty-state primitive ───── */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 64px 24px;
  text-align: center;
  min-height: 240px;
}
.empty-state .empty-mark {
  /* The brand-mark glyph at empty-state size */
  width: 56px;
  height: 56px;
  border: 1px solid var(--accent);
  background: var(--accent-dim);
  position: relative;
  opacity: 0.40;
  margin-bottom: 6px;
}
.empty-state .empty-mark::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 1px solid var(--accent);
  transform: rotate(45deg);
}
.empty-state .empty-headline {
  font-size: 16px;
  font-weight: 500;
  color: var(--fg-1);
  letter-spacing: 0.005em;
  margin: 0;
}
.empty-state .empty-subhead {
  font-family: var(--ff-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--fg-3);
  text-transform: none;
  margin: 0;
  max-width: 48ch;
}
.empty-state .empty-cta {
  margin-top: 8px;
}
/* Backwards-compat: existing `.empty-state .big` callsites still work */
.empty-state .big {
  font-size: 16px;
  font-weight: 500;
  color: var(--fg-1);
}

/* ───── Inline error — uses the existing --warn token family (hue 60) ───── */
.inline-error {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: var(--warn-dim);
  border-left: 2px solid var(--warn);
  font-size: 12px;
  color: var(--fg-1);
}
.inline-error .retry-btn {
  margin-left: auto;
  font-family: var(--ff-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--warn);
  border: 1px solid oklch(0.78 0.14 60 / 0.45);
  padding: 4px 10px;
  cursor: pointer;
}
.inline-error .retry-btn:hover { background: oklch(0.78 0.14 60 / 0.20); }

.stub-empty { padding:80px 32px; display:flex; flex-direction:column; align-items:center; text-align:center; gap:14px; color:var(--fg-2); }
.stub-mark { width:96px; height:96px; border:1px solid var(--accent-line); background:var(--accent-dim); display:grid; place-items:center; position:relative; margin-bottom:8px; }
.stub-mark::before { content:""; position:absolute; inset:16px; border:1px solid var(--accent); transform:rotate(45deg); }
.stub-mark::after { content:"?"; font-family:var(--ff-mono); font-size:24px; font-weight:700; color:var(--accent); position:relative; }
.stub-empty h3 { margin:0; font-size:22px; letter-spacing:0.04em; font-weight:600; color:var(--fg-0); }
/* Empty-state body copy — was 0.16em (headline tracking) which made "Nothing here
   yet — this faction's units haven't been added." physically slow to read.
   0.04em keeps the mono+lowercase identity without slowing comprehension. */
.stub-msg { font-family:var(--ff-mono); font-size:11px; letter-spacing:0.04em; color:var(--fg-3); max-width:480px; line-height:1.6; }
.stub-meta { display:flex; gap:24px; margin-top:12px; font-family:var(--ff-mono); font-size:11px; letter-spacing:0.08em; color:var(--fg-3); }
.stub-meta span strong { color:var(--accent); font-weight:500; }

/* ── Blazor error UI ── */
#blazor-error-ui { color-scheme:light only; background:lightyellow; bottom:0; box-shadow:0 -1px 2px rgba(0,0,0,.2); box-sizing:border-box; display:none; left:0; padding:.6rem 1.25rem .7rem 1.25rem; position:fixed; width:100%; z-index:1000; }
#blazor-error-ui .dismiss { cursor:pointer; position:absolute; right:.75rem; top:.5rem; }
.blazor-error-boundary { background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem,#b32121; padding:1rem 1rem 1rem 3.7rem; color:white; }
.blazor-error-boundary::after { content:"An error has occurred." }

/* ============================================================
   IDENT // v2 expansion — Collection, Roster, Search, Recents,
   Skill/Weapon refs, Legacy archive, Mercenary corner accent.
   ============================================================ */

/* ── Collection: card overlays ───────────────────────────────── */
.unit-fav {
  position: absolute;
  top: 4px; right: 4px;
  z-index: 3;
  width: 18px; height: 18px;
  display: grid; place-items: center;
  color: oklch(0.72 0.10 75);            /* muted gold at rest — readable, not loud */
  background: oklch(from var(--bg-0) l c h / 0.6);
  border: 1px solid oklch(0.72 0.10 75 / 0.35);
  border-radius: 1px;
  cursor: pointer;
  transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.unit-fav:hover { color: oklch(0.85 0.16 75); border-color: oklch(0.82 0.13 75 / 0.6); }
.unit-fav.is-on {
  color: oklch(0.85 0.16 75);            /* full gold when favorited */
  border-color: oklch(0.82 0.13 75 / 0.6);
  background: oklch(0.82 0.13 75 / 0.18);
}

/* Owned/wanted ring around the model token */
/* "Owned" / "Wanted" light up the whole card, not an inner image box — emphasizing that
   the card itself is the unit. Hover-bg from .unit:hover stacks naturally on top because
   they touch different properties (border vs. background). */
.unit[data-coll="owned"] {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-line) inset;
}
.unit[data-coll="wanted"] {
  border-color: var(--accent-line);
  border-style: dashed;
}

/* Tiny status pill under the unit name */
.unit-coll {
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.14em;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 5px;
  border: 1px solid var(--line-2);
  background: var(--bg-1);
  border-radius: 1px;
  color: var(--fg-2);
}
.unit-coll::before {
  content: ""; width: 6px; height: 6px;
  border-radius: 50%; background: currentColor;
}
.unit-coll[data-coll="owned"] {
  color: var(--accent);
  border-color: var(--accent-line);
  background: var(--accent-dim);
}
.unit-coll[data-coll="wanted"] {
  color: var(--warn);
  border-color: oklch(0.78 0.14 60 / 0.5);
  background: oklch(0.78 0.14 60 / 0.12);
}
.unit-coll[data-coll="wanted"]::before {
  background: transparent;
  border: 1px solid currentColor;
}

/* ── Drawer collection block ─────────────────────────────────── */
.collection-block { display: flex; flex-direction: column; gap: 10px; }
.collection-summary {
  font-size: 11px; letter-spacing: 0.04em;
  color: var(--fg-3);
  padding-top: 4px;
}
.collection-summary .cs-owned  { color: var(--accent-fg); }
.collection-summary .cs-wanted { color: var(--warn); }
.collection-summary .cs-muted  { color: var(--fg-3); }
.collection-actions { display: grid; grid-template-columns: auto 1fr 1fr; gap: 6px; }
.coll-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--line-2);
  background: var(--bg-2);
  color: var(--fg-1);
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.16em;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.coll-btn:hover { border-color: var(--accent-line); color: var(--fg-0); }
.coll-btn.is-on {
  border-color: var(--accent);
  background: var(--accent-dim);
  color: var(--fg-0);
}
.coll-btn.fav.is-on {
  color: oklch(0.85 0.16 75);
  border-color: oklch(0.82 0.13 75 / 0.6);
  background: oklch(0.82 0.13 75 / 0.18);
}
.coll-btn.wanted.is-on {
  color: var(--warn);
  border-color: oklch(0.78 0.14 60 / 0.6);
  background: oklch(0.78 0.14 60 / 0.14);
}

/* Sculpt row owned check */
.sculpt-own {
  min-width: 16px; height: 16px;
  padding: 0 3px;
  border: 1px solid var(--line-2);
  border-radius: 1px;
  display: grid; place-items: center;
  margin-right: 4px;
  cursor: pointer;
  flex-shrink: 0;
  color: transparent;
  font-family: var(--ff-mono);
  font-size: 11px; font-weight: 700; line-height: 1;
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.sculpt-own:hover { border-color: var(--accent-line); }
.sculpt-own.is-on {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--bg-0);
}

/* Inline +/− stepper next to the ✓ in the drawer's sculpt-rows.
   Fine-grained per-sculpt count adjustment without needing the products page. */
.sculpt-step {
  width: 14px; height: 16px;
  padding: 0;
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--fg-2);
  font-family: var(--ff-mono);
  font-size: 11px; line-height: 1; font-weight: 700;
  cursor: pointer;
  margin-right: 2px;
  border-radius: 1px;
  display: grid; place-items: center;
  flex-shrink: 0;
  transition: border-color 0.12s, color 0.12s;
}
.sculpt-step:hover:not(:disabled) {
  color: var(--accent-fg);
  border-color: var(--accent-line);
}
.sculpt-step:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Sculpt wanted toggle — same shape as .sculpt-own but in the warn/gold colorway */
.sculpt-want {
  width: 16px; height: 16px;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  display: grid; place-items: center;
  margin-right: 4px;
  cursor: pointer;
  flex-shrink: 0;
  color: transparent;
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.sculpt-want:hover { border-color: oklch(0.78 0.14 60 / 0.5); }
.sculpt-want.is-on {
  border-color: var(--warn);
  background: transparent;
  color: var(--warn);
}
.sculpt-want.is-on::after {
  content: "◎";
  font-family: var(--ff-mono);
  font-size: 11px; font-weight: 700;
}

/* ── Topbar collection counts ────────────────────────────────── */
.coll-counts {
  display: flex; gap: 8px;
  flex-shrink: 0;
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.14em;
  color: var(--fg-3);
  padding: 0 12px;
  border-left: 1px solid var(--line-1);
  border-right: 1px solid var(--line-1);
  margin: 0 4px;
  height: 28px;
  align-items: center;
}
.coll-counts span {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-width: 48px;
  line-height: 1;
}
.coll-counts span strong { color: var(--accent); font-weight: 500; }
.coll-counts .fav strong { color: oklch(0.82 0.13 75); }
.coll-counts .wnt strong { color: var(--warn); }

/* ── Global Search ───────────────────────────────────────────── */
.gsearch {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  padding: 6px 10px;
  width: 380px;
  transition: border-color 0.12s;
}
.gsearch:focus-within { border-color: var(--accent-line); }
.gsearch input {
  flex: 1; min-width: 0;
  background: none; border: 0; outline: none;
  color: var(--fg-0);
  font-size: 13px;
}
.gsearch input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gsearch-shortcut {
  font-size: 10px; letter-spacing: 0.12em;
  color: var(--fg-3);
  border: 1px solid var(--line-1);
  border-radius: 3px;
  padding: 1px 5px;
  line-height: 1;
}
.gsearch[data-open="True"] .gsearch-shortcut { display: none; }

.gsearch-pop {
  position: absolute;
  top: calc(100% + 6px); right: 0;
  width: 520px; max-width: 90vw;
  background: var(--bg-0);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-sm);
  box-shadow: 0 12px 40px oklch(0% 0 0 / 0.5);
  z-index: 50;
  display: flex; flex-direction: column;
  max-height: 70vh; overflow: hidden;
}
.gsearch-pop-head {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line-1);
  background: var(--bg-1);
}
.gsearch-scope {
  display: flex; gap: 0;
  border: 1px solid var(--line-1);
  border-radius: 3px;
  overflow: hidden;
}
.gsearch-scope button {
  background: none; border: 0;
  color: var(--fg-3);
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.14em;
  padding: 4px 10px;
  cursor: pointer;
}
.gsearch-scope[data-current="all"]     button[data-value="all"],
.gsearch-scope[data-current="faction"] button[data-value="faction"] {
  background: var(--accent-dim);
  color: var(--accent-fg);
  font-weight: 600;
}
.gsearch-count { margin-left: auto; font-size: 11px; letter-spacing: 0.14em; color: var(--fg-3); }
.gsearch-list { overflow-y: auto; padding: 4px 0; }
.gsearch-item {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  align-items: center;
  gap: 12px;
  width: 100%;
  background: none;
  border: 0;
  border-left: 2px solid transparent;
  padding: 8px 12px;
  text-align: left;
  cursor: pointer;
  color: var(--fg-1);
}
.gsearch-item.is-active {
  background: var(--accent-dim);
  border-left-color: oklch(70% 0.18 var(--accent-hue));
  color: var(--fg-0);
}
.gsearch-faction {
  font-size: 11px; letter-spacing: 0.14em;
  text-align: center;
  border: 1px solid var(--line-1);
  border-radius: 3px;
  padding: 3px 0;
  color: oklch(70% 0.12 var(--fh, var(--accent-hue)));
  background: oklch(20% 0.02 var(--fh, var(--accent-hue)) / 0.4);
}
.gsearch-faction.is-self { border-color: oklch(70% 0.18 var(--fh, var(--accent-hue))); }
.gsearch-name { font-size: 13px; font-weight: 500; display: flex; align-items: center; gap: 6px; }
.gsearch-sub { color: var(--fg-3); font-weight: 400; }
.gsearch-leg {
  font-size: 11px; letter-spacing: 0.14em;
  border: 1px dashed var(--line-2);
  padding: 1px 5px;
  color: var(--fg-3);
  border-radius: 2px;
}
.gsearch-tags {
  display: flex; gap: 6px; margin-top: 3px;
  font-size: 11px; letter-spacing: 0.1em;
  color: var(--fg-3);
  flex-wrap: wrap;
}
.gsearch-mtag {
  text-transform: uppercase;
  border: 1px solid var(--line-1);
  border-radius: 2px;
  padding: 1px 5px;
}
.gsearch-arrow { color: var(--fg-3); font-size: 12px; opacity: 0; }
.gsearch-item.is-active .gsearch-arrow { opacity: 1; }
.gsearch-empty { padding: 32px 16px; text-align: center; }
.gsearch-empty .big { font-size: 12px; letter-spacing: 0.18em; color: var(--fg-2); margin-bottom: 6px; }
.gsearch-empty .hint { font-size: 11px; color: var(--fg-3); letter-spacing: 0.04em; font-family: var(--ff-sans); }
.gsearch-foot {
  display: flex; gap: 16px;
  padding: 8px 12px;
  border-top: 1px solid var(--line-1);
  background: var(--bg-1);
  font-size: 10px; letter-spacing: 0.12em;
  color: var(--fg-3);
}
.gsearch-foot kbd {
  font-family: var(--ff-mono);
  border: 1px solid var(--line-1);
  border-radius: 2px;
  padding: 1px 5px;
  margin-right: 4px;
  background: var(--bg-0);
  color: var(--fg-2);
}

/* ── Skill / weapon chips + popover ──────────────────────────── */
.ref-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.ref-chip {
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.1em;
  border: 1px solid var(--line-1);
  border-radius: 3px;
  padding: 4px 8px;
  background: var(--bg-1);
  color: var(--fg-1);
  cursor: pointer;
  position: relative;
  text-transform: uppercase;
}
.ref-chip:hover { border-color: var(--accent-line); color: var(--fg-0); }
.ref-chip[data-kind="weapon"] {
  border-color: oklch(45% 0.06 var(--accent-hue));
  color: oklch(78% 0.10 var(--accent-hue));
}
.ref-chip.is-active {
  background: var(--accent-dim);
  border-color: oklch(70% 0.18 var(--accent-hue));
  color: var(--fg-0);
}
.ref-pop {
  position: absolute;
  top: calc(100% + 6px); left: 0;
  z-index: 60;
  background: var(--bg-0);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-sm);
  padding: 12px 14px;
  width: 280px;
  box-shadow: 0 8px 28px oklch(0% 0 0 / 0.5);
  font-family: var(--ff-sans);
  text-transform: none;
  letter-spacing: 0;
}
.ref-pop-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.ref-pop-name { font-size: 13px; font-weight: 600; color: var(--fg-0); }
.ref-pop-cat {
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.16em;
  color: var(--fg-3);
  border: 1px solid var(--line-1);
  border-radius: 2px;
  padding: 1px 5px;
  text-transform: uppercase;
}
.ref-pop-range {
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.08em;
  color: oklch(78% 0.10 var(--accent-hue));
  margin-bottom: 6px;
}
.ref-pop-desc { font-size: 12px; line-height: 1.5; color: var(--fg-1); text-wrap: pretty; }

/* ── Drawer prev/next nav + recently viewed ──────────────────── */
.drawer-nav {
  display: flex; align-items: center; gap: 4px;
  margin-left: auto; margin-right: 8px;
}
.drawer-nav button {
  width: 26px; height: 26px;
  background: none;
  border: 1px solid var(--line-1);
  border-radius: 3px;
  color: var(--fg-2);
  cursor: pointer;
  font-family: var(--ff-mono);
  font-size: 12px;
}
.drawer-nav button:hover:not(:disabled) { border-color: var(--accent-line); color: var(--fg-0); }
.drawer-nav button:disabled { opacity: 0.3; cursor: not-allowed; }
.drawer-nav .pos {
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.12em;
  color: var(--fg-3);
  padding: 0 4px;
  min-width: 56px;
  text-align: center;
}

.recent-strip {
  border-top: 1px solid var(--line-1);
  padding: 10px 16px;
  background: var(--bg-1);
}
.recent-strip-head {
  font-family: var(--ff-mono);
  font-size: 9px; letter-spacing: 0.18em;
  color: var(--fg-3);
  margin-bottom: 6px;
}
.recent-list { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: thin; }
.recent-pill {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 6px;
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  border-radius: 3px;
  padding: 5px 9px;
  font-size: 11px;
  color: var(--fg-1);
  cursor: pointer;
  white-space: nowrap;
}
.recent-pill:hover { border-color: var(--accent-line); color: var(--fg-0); }
.recent-pill[data-current="True"] {
  border-color: oklch(70% 0.18 var(--accent-hue));
  background: var(--accent-dim);
  color: var(--fg-0);
}
.recent-pill .fcode { font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.14em; color: var(--fg-3); }

/* ── Legacy badge + demoted card treatment ───────────────────── */
.unit-legacy {
  position: absolute;
  /* Top-center — out of the way of the sculpts toggle (top-left) and favorite star (top-right). */
  top: 4px; left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.14em;
  color: var(--fg-3);
  border: 1px dashed var(--line-2);
  padding: 1px 5px;
  background: oklch(from var(--bg-0) l c h / 0.85);
  backdrop-filter: blur(2px);
  white-space: nowrap;
}
/* Legacy units only show inside the explicitly-revealed archive section, so we keep their
   colors at full strength — visitors who got there asked to see them. The dashed outline
   is enough to differentiate at-a-glance without muting the figure. */
.unit[data-legacy="true"] { border-style: dashed; border-color: var(--line-2); }

/* Legacy status pill (drawer + compare) */
.status-pill.legacy {
  color: var(--fg-2);
  border-color: var(--line-2);
  border-style: dashed;
}

/* Legacy archive section at bottom of sheet */
.legacy-archive {
  margin-top: 12px;
  border: 1px dashed var(--line-2);
  background: oklch(from var(--bg-0) calc(l - 0.01) c h);
  padding: 20px 24px 24px;
  border-radius: var(--r-sm);
}
.legacy-archive-head {
  display: flex; align-items: flex-end; gap: 16px;
  border-bottom: 1px dashed var(--line-1);
  padding-bottom: 14px;
  margin-bottom: 18px;
}
.legacy-archive-title { display: flex; flex-direction: column; gap: 2px; }
.legacy-archive-title .crumbs { font-size: 10px; letter-spacing: 0.18em; color: var(--fg-3); }
.legacy-archive-title h3 {
  margin: 0;
  font-size: 22px; font-weight: 600; letter-spacing: 0.04em;
  color: var(--fg-1);
}
.legacy-archive-desc { font-size: 11px; letter-spacing: 0.16em; color: var(--fg-3); margin-top: 2px; }
.legacy-archive-count {
  margin-left: auto;
  font-size: 11px; letter-spacing: 0.16em; color: var(--fg-3);
  border: 1px solid var(--line-1);
  padding: 4px 10px;
}

/* ── Cross-faction guest corner accent ───────────────────────── */
.unit-guest-corner {
  position: absolute;
  top: 0; left: 0;
  width: 24px; height: 24px;
  z-index: 0;
  background: linear-gradient(
    135deg,
    oklch(60% 0.18 var(--gh, var(--accent-hue))) 0%,
    oklch(60% 0.18 var(--gh, var(--accent-hue))) 50%,
    transparent 50%,
    transparent 100%
  );
  pointer-events: auto;
  cursor: help;
}

/* ── Roster: centered ±  controls revealed on card hover ─────── */
.unit-roster-ctl {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  z-index: 5;
  display: flex;
  gap: 6px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s;
}
.unit:hover .unit-roster-ctl {
  opacity: 1;
  pointer-events: auto;
}
.unit-roster-btn {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: oklch(from var(--bg-0) l c h / 0.88);
  border: 1px solid var(--accent-line);
  color: var(--fg-0);
  font-size: 16px; line-height: 1;
  cursor: pointer;
  display: grid; place-items: center;
  font-family: var(--ff-mono);
  backdrop-filter: blur(2px);
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.unit-roster-btn:hover:not(:disabled) {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent-fg);
}
.unit-roster-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* In-roster card visual: thin left-edge accent rail + count appended to name. */
.unit[data-in-roster="true"] {
  border-left: 3px solid var(--accent-fg);
  padding-left: 5px;   /* offset the 3px rail (default padding is 8px → 8-3 = 5) */
}
.unit-roster-count {
  color: var(--accent-fg);
  font-size: 11px;
  letter-spacing: 0.04em;
  margin-left: 2px;
}

/* Drag cursor */
html[data-unit-dragging="true"] .unit { cursor: grabbing; }

/* ── Roster rail ─────────────────────────────────────────────── */
.roster-rail {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: 320px;
  background: var(--bg-1);
  border-left: 1px solid var(--line-1);
  z-index: 50;
  display: flex; flex-direction: column;
  font-family: var(--ff-sans);
  box-shadow: -8px 0 30px rgba(0,0,0,0.4);
}
.rr-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line-1);
}
.rr-title { font-size: 11px; letter-spacing: 0.18em; color: var(--fg-1); }
.rr-close {
  background: transparent;
  border: 1px solid var(--line-1);
  color: var(--fg-1);
  width: 22px; height: 22px;
  cursor: pointer;
  font-size: 14px; line-height: 1;
}
.rr-close:hover { color: var(--fg-0); border-color: var(--line-2); }
.rr-name {
  padding: 14px 16px 8px;
  font-size: 14px; color: var(--fg-0);
  border-bottom: 1px dashed var(--line-1);
  cursor: pointer;
}
.rr-name:hover { background: var(--bg-0); }
.rr-name-edit-hint {
  font-size: 11px; color: var(--fg-3);
  margin-left: 6px;
  opacity: 0.4;
}
.rr-name:hover .rr-name-edit-hint { opacity: 1; }
.rr-name-input {
  display: block;
  width: calc(100% - 32px);
  margin: 12px 16px 8px;
  padding: 4px 8px;
  background: var(--bg-0);
  border: 1px solid var(--accent-line);
  color: var(--fg-0);
  font-family: inherit;
  font-size: 14px;
}
.rr-picker {
  display: flex; gap: 6px; align-items: center;
  padding: 10px 16px;
  border-bottom: 1px dashed var(--line-1);
}
.rr-picker-select {
  flex: 1; min-width: 0;
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  color: var(--fg-0);
  padding: 5px 6px;
  font-family: inherit;
  font-size: 13px;
}
.re-picker {
  display: flex; gap: 6px; align-items: center;
  margin-left: 12px;
}
.re-picker-select {
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  color: var(--fg-0);
  padding: 5px 8px;
  font-family: inherit;
  font-size: 12px;
  max-width: 220px;
}
.re-toast {
  position: absolute;
  top: 12px; left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  background: var(--accent);
  color: var(--bg-0);
  padding: 6px 14px;
  font-size: 11px;
  letter-spacing: 0.14em;
  border-radius: var(--r-sm);
  box-shadow: 0 4px 12px oklch(0 0 0 / 0.4);
  animation: re-toast-fade 2.4s ease;
}
@keyframes re-toast-fade {
  0%   { opacity: 0; transform: translate(-50%, -8px); }
  10%  { opacity: 1; transform: translate(-50%, 0); }
  85%  { opacity: 1; transform: translate(-50%, 0); }
  100% { opacity: 0; transform: translate(-50%, -8px); }
}
.rr-empty {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  color: var(--fg-2);
  text-align: center;
  padding: 30px;
}
.rr-empty-mark {
  font-size: 36px;
  color: var(--accent-line);
  border: 2px dashed var(--accent-line);
  width: 60px; height: 60px;
  display: grid; place-items: center;
  border-radius: 50%;
}
.rr-empty-msg { font-size: 13px; line-height: 1.5; }
.rr-list { flex: 1; list-style: none; margin: 0; padding: 8px 0; overflow-y: auto; }
.rr-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 16px;
  border-bottom: 1px solid var(--line-1);
  gap: 8px;
}
.rr-item:hover { background: var(--bg-0); }
.rr-item-main { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.rr-count {
  font-size: 11px;
  color: var(--accent-fg);
  background: var(--accent-dim);
  padding: 3px 6px;
  border: 1px solid var(--accent-line);
  flex-shrink: 0;
}
.rr-item-name { min-width: 0; }
.rr-uname { font-size: 13px; color: var(--fg-0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rr-sub { color: var(--fg-2); font-size: 12px; }
.rr-meta { font-size: 11px; letter-spacing: 0.12em; color: var(--fg-2); margin-top: 2px; }
.rr-uname--missing { color: var(--fg-3); font-style: italic; }
.rr-meta--missing  { color: var(--fg-3); }
.rr-item-ctl { display: flex; gap: 4px; }
.rr-mini {
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  color: var(--fg-1);
  width: 22px; height: 22px;
  cursor: pointer;
  font-size: 13px; line-height: 1;
}
.rr-mini:hover { color: var(--fg-0); border-color: var(--accent-line); }
.rr-foot {
  border-top: 1px solid var(--line-1);
  padding: 12px 16px;
  background: var(--bg-0);
}
.rr-totals {
  display: flex; justify-content: space-between;
  font-size: 11px; letter-spacing: 0.14em; color: var(--fg-1);
  margin-bottom: 10px;
}
.rr-totals strong { color: var(--fg-0); font-size: 14px; margin-left: 4px; }
.rr-actions { display: flex; gap: 6px; }
.rr-btn {
  flex: 1;
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--fg-1);
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.16em;
  padding: 8px 0;
  cursor: pointer;
}
.rr-btn:hover:not(:disabled) { color: var(--fg-0); border-color: var(--accent-line); }
.rr-btn:disabled { opacity: 0.4; cursor: not-allowed; }

.roster-rail[data-drag-over="True"] {
  background: var(--accent-dim);
  outline: 2px dashed var(--accent-fg);
  outline-offset: -2px;
}
.roster-rail[data-drag-over="True"] .rr-empty-mark {
  border-color: var(--accent-fg);
  color: var(--accent-fg);
  transform: scale(1.1);
}

/* Topbar ROSTER button */
.roster-toggle {
  display: flex !important;
  align-items: center;
  gap: 6px;
  padding: 0 10px !important;
  width: auto !important;
}
.roster-pip {
  background: var(--accent-dim);
  border: 1px solid var(--accent-line);
  color: var(--accent-fg);
  font-size: 11px;
  padding: 1px 5px;
  min-width: 18px;
  text-align: center;
}

/* When rail open, shift the detail drawer left so they coexist */
.drawer.rail-shifted { right: 320px; }

/* ── Roster editor overlay ───────────────────────────────────── */
.roster-editor {
  position: fixed; inset: 0;
  background: transparent;
  z-index: 60;
  display: grid; place-items: center;
  /* Native <dialog> resets: fill the viewport so .re-shell centers via place-items. */
  width: 100%; height: 100%;
  max-width: none; max-height: none;
  border: none; padding: 0;
  color: inherit;
}
.roster-editor::backdrop {
  background: rgba(0,0,0,0.7);
}
.re-shell {
  width: min(1100px, 95vw);
  height: min(800px, 92vh);
  background: var(--bg-1);
  border: 1px solid var(--line-2);
  display: flex; flex-direction: column;
  position: relative;   /* anchors absolutely-positioned children like .re-toast */
}
.re-head {
  display: flex; align-items: center; gap: 16px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--line-1);
}
.re-crumbs { font-size: 10px; letter-spacing: 0.18em; color: var(--fg-2); }
.re-name { font-size: 22px; margin: 0; cursor: pointer; color: var(--fg-0); }
.re-edit-hint { font-size: 12px; color: var(--fg-2); margin-left: 6px; opacity: 0.5; }
.re-name:hover .re-edit-hint { opacity: 1; }
.re-name-input {
  font-size: 22px;
  background: var(--bg-0);
  border: 1px solid var(--accent-line);
  color: var(--fg-0);
  padding: 4px 8px;
  font-family: inherit;
  flex: 1;
}
.re-close {
  margin-left: auto;
  background: transparent;
  border: 1px solid var(--line-1);
  color: var(--fg-1);
  width: 28px; height: 28px;
  font-size: 16px; cursor: pointer;
}
.re-close:hover { color: var(--fg-0); }
.re-body { display: flex; flex: 1; min-height: 0; }
.re-list-wrap { flex: 1; overflow-y: auto; padding: 16px 20px; }
.re-empty {
  padding: 60px 20px;
  text-align: center;
  font-size: 11px; letter-spacing: 0.16em;
  color: var(--fg-2);
  border: 1px dashed var(--line-1);
}
.re-entries { display: flex; flex-direction: column; gap: 12px; }
.re-entry {
  border: 1px solid var(--line-1);
  background: var(--bg-0);
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 10px;
}
.re-entry-head {
  display: flex; align-items: center; gap: 12px;
}
.re-idx {
  font-size: 11px; letter-spacing: 0.16em;
  color: var(--fg-3);
  min-width: 28px;
}
.re-entry-name { flex: 1; min-width: 0; }
.re-uname { color: var(--fg-0); font-size: 13px; }
.re-usub { color: var(--fg-2); font-size: 11px; }
.re-uname--missing { color: var(--fg-3); font-style: italic; }
.re-fcode { font-size: 11px; letter-spacing: 0.16em; }
.re-count-num { min-width: 24px; text-align: center; font-size: 12px; color: var(--fg-0); }
.re-count-ctl { display: flex; align-items: center; gap: 6px; }
.re-remove-line { color: var(--fg-3); }
.re-remove-line:hover { color: oklch(70% 0.18 25); border-color: oklch(60% 0.18 25); }
.re-instances {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding-top: 8px;
  border-top: 1px dashed var(--line-1);
}
.re-instances-label {
  width: 100%;
  font-size: 11px; letter-spacing: 0.18em;
  color: var(--fg-3);
  padding-bottom: 2px;
}
.re-instance {
  display: flex; align-items: center; gap: 6px;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  padding: 4px 6px;
}
.re-inst-num { color: var(--fg-3); font-size: 11px; min-width: 22px; }
.re-select {
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  color: var(--fg-0);
  padding: 4px 6px;
  font-family: inherit;
  font-size: 12px;
  min-width: 160px;
}
.re-side {
  width: 240px;
  border-left: 1px solid var(--line-1);
  padding: 16px 20px;
  display: flex; flex-direction: column;
  background: var(--bg-0);
}
.re-stat-block { margin-bottom: 16px; }
.re-stat-label { font-size: 11px; letter-spacing: 0.14em; color: var(--fg-2); }
.re-stat-value { font-size: 28px; color: var(--fg-0); margin-top: 2px; }
.re-stat-value-sm { font-size: 11px; color: var(--fg-1); margin-top: 4px; }
.re-spacer { flex: 1; }
.re-action {
  background: var(--accent-dim);
  border: 1px solid var(--accent-line);
  color: var(--accent-fg);
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.06em;
  padding: 10px 0;
  cursor: pointer;
  margin-bottom: 8px;
}
.re-action:hover:not(:disabled) { background: var(--accent-line); color: var(--bg-0); }
.re-action:disabled { opacity: 0.4; cursor: not-allowed; }
.re-action.danger {
  background: transparent;
  border-color: var(--line-2);
  color: var(--fg-2);
}
.re-action.danger:hover:not(:disabled) {
  border-color: oklch(60% 0.18 25);
  color: oklch(70% 0.18 25);
  background: transparent;
}

/* ============================================================
   ADMIN UI
   ============================================================ */
.admin-shell {
  min-height: 100vh;
  display: flex; flex-direction: column;
  background: var(--bg-0);
  color: var(--fg-1);
  font-family: var(--ff-sans);
}
.admin-topbar {
  display: flex; align-items: center; gap: 24px;
  padding: 10px 24px;
  background: var(--bg-1);
  border-bottom: 1px solid var(--line-1);
  position: sticky; top: 0; z-index: 10;
}
.admin-brand { display: flex; gap: 8px; align-items: baseline; }
.admin-nav { display: flex; gap: 4px; flex: 1; }
.admin-nav-link {
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.16em;
  color: var(--fg-2);
  padding: 6px 12px;
  text-decoration: none;
  border-radius: var(--r-sm);
  text-transform: uppercase;
}
.admin-nav-link:hover { background: var(--bg-2); color: var(--fg-0); }
.admin-nav-link.active { background: var(--accent-dim); color: var(--accent-fg); }
.admin-back {
  font-family: var(--ff-mono);
  font-size: 10px; letter-spacing: 0.16em;
  color: var(--fg-3);
  text-decoration: none;
  padding: 6px 10px;
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
}
.admin-back:hover { color: var(--accent); border-color: var(--accent-line); }

.admin-main {
  flex: 1;
  padding: 28px 32px 60px;
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  box-sizing: border-box;
}

.admin-h1 { font-size: 24px; font-weight: 600; letter-spacing: 0.02em; margin: 0 0 4px; color: var(--fg-0); }
.admin-h2 { font-size: 14px; font-weight: 600; letter-spacing: 0.04em; margin: 0 0 12px; color: var(--fg-0); }
.admin-sub { color: var(--fg-2); margin: 0 0 28px; font-size: 13px; }
.admin-crumbs { font-family: var(--ff-mono); font-size: 10px; letter-spacing: 0.18em; color: var(--fg-3); margin-bottom: 6px; }
.admin-crumbs a { color: var(--fg-3); text-decoration: none; }
.admin-crumbs a:hover { color: var(--accent); }

.admin-page-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 24px;
  gap: 16px;
}
.admin-actions { display: flex; gap: 8px; }

.admin-empty { padding: 48px 16px; text-align: center; color: var(--fg-3); font-family: var(--ff-mono); letter-spacing: 0.14em; font-size: 11px; }
.admin-empty.inline { padding: 18px 12px; }

.admin-msg {
  padding: 10px 14px;
  border-radius: var(--r-sm);
  margin-bottom: 16px;
  font-size: 13px;
}
.admin-msg.ok    { background: var(--accent-dim); border: 1px solid var(--accent-line); color: var(--fg-0); }
.admin-msg.error { background: oklch(0.30 0.10 25 / 0.4); border: 1px solid oklch(0.65 0.18 25 / 0.6); color: oklch(0.92 0.06 25); }

.admin-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 24px;
}
.admin-stat {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  padding: 14px 16px;
  text-decoration: none;
  color: var(--fg-1);
  display: block;
  transition: border-color 0.12s, background 0.12s;
}
.admin-stat:hover { border-color: var(--accent-line); background: var(--bg-2); }
.admin-stat-label { font-size: 10px; letter-spacing: 0.16em; color: var(--fg-3); }
.admin-stat-value { font-size: 32px; font-weight: 600; color: var(--fg-0); margin-top: 4px; }
.admin-stat-sub { font-size: 10px; letter-spacing: 0.12em; color: var(--fg-2); margin-top: 4px; }

.admin-recent-units {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  padding: 14px 16px;
  display: inline-block;
  min-width: 220px;
}
.admin-recent-units-label {
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--fg-3);
}
.admin-recent-units-list {
  list-style: none;
  margin: 8px 0 0 0;
  padding-left: 18px;
  color: var(--fg-1);
  font-size: 13px;
}
.admin-recent-units-list li { margin-bottom: 3px; }

.admin-quick { display: flex; gap: 10px; margin-top: 20px; }

.admin-btn {
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--fg-1);
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.16em;
  padding: 8px 14px;
  cursor: pointer;
  text-decoration: none;
  border-radius: var(--r-sm);
}
.admin-btn:hover { border-color: var(--accent-line); color: var(--accent-fg); }
.admin-btn.small { padding: 4px 10px; font-size: 10px; letter-spacing: 0.14em; }
.admin-btn.primary {
  background: var(--accent-dim);
  border-color: var(--accent-line);
  color: var(--accent-fg);
}
.admin-btn.primary:hover { background: var(--accent); color: var(--bg-0); }
.admin-btn.danger { color: oklch(0.7 0.16 25); border-color: oklch(0.55 0.18 25 / 0.5); }
.admin-btn.danger:hover { background: oklch(0.55 0.18 25 / 0.2); border-color: oklch(0.65 0.18 25); color: oklch(0.85 0.16 25); }
.admin-btn.ghost  { color: var(--fg-2); border-color: var(--line-2); }
.admin-btn.ghost:hover { color: var(--fg-1); border-color: var(--line-1); }

.admin-mini {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  color: var(--fg-1);
  width: 24px; height: 24px;
  cursor: pointer;
  font-size: 13px; line-height: 1;
  margin-right: 4px;
}
.admin-mini:hover { color: var(--accent); border-color: var(--accent-line); }
.admin-mini.danger { color: oklch(0.65 0.18 25); }
.admin-mini.danger:hover { color: oklch(0.8 0.18 25); border-color: oklch(0.65 0.18 25); }

/* ── Tables ────────────────────────────────────────────────── */
.admin-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  overflow: hidden;
  font-size: 13px;
}
.admin-table th {
  text-align: left;
  background: var(--bg-2);
  padding: 8px 10px;
  font-family: var(--ff-mono);
  font-size: 10px; letter-spacing: 0.14em;
  color: var(--fg-2);
  text-transform: uppercase;
  border-bottom: 1px solid var(--line-1);
}
.admin-table td { padding: 8px 10px; border-bottom: 1px solid var(--line-1); color: var(--fg-1); vertical-align: middle; }
.admin-table tr:last-child td { border-bottom: 0; }
.admin-table tr:hover td { background: var(--bg-2); }
.admin-table.inner { margin-top: 0; box-shadow: none; }
.admin-link { color: var(--accent-fg); text-decoration: none; }
.admin-link:hover { color: var(--accent); text-decoration: underline; }
.admin-muted { color: var(--fg-3); }

.admin-pill {
  display: inline-block;
  font-family: var(--ff-mono);
  font-size: 9px; letter-spacing: 0.16em;
  padding: 1px 5px;
  border: 1px solid var(--line-2);
  margin-right: 4px;
  border-radius: 1px;
}
.admin-pill.active { color: var(--accent); border-color: var(--accent-line); background: var(--accent-dim); }
.admin-pill.oop    { color: var(--warn); border-color: oklch(0.78 0.14 60 / 0.5); }
.admin-pill.legacy { color: var(--fg-2); border-color: var(--line-2); border-style: dashed; }
.admin-pill.draft  { color: var(--fg-2); border-color: var(--line-2); border-style: dotted; }

/* ── Filter bar ────────────────────────────────────────────── */
.admin-filterbar {
  display: flex; gap: 12px; align-items: flex-end;
  margin-bottom: 16px;
  padding: 12px 16px;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
}

.admin-bulkbar {
  display: flex; gap: 12px; align-items: center;
  margin-bottom: 12px;
  padding: 10px 14px;
  background: var(--accent-dim);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-sm);
  position: sticky;
  top: 0;
  z-index: 10;
}
.admin-bulkbar .mono { color: var(--accent-fg); font-size: 11px; letter-spacing: 0.14em; }

/* ── Forms ─────────────────────────────────────────────────── */
.admin-form-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}
.admin-card {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  padding: 18px 20px;
}
.admin-card--wide { grid-column: span 2; }
.admin-card-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
.admin-card-head .admin-h2 { margin: 0; }

.admin-fields {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
}
.admin-product-fields { grid-template-columns: repeat(4, 1fr); }
.admin-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.admin-field.admin-checkbox { flex-direction: row; align-items: center; gap: 8px; grid-column: span 2; }
.admin-label { font-family: var(--ff-mono); font-size: 10px; letter-spacing: 0.14em; color: var(--fg-3); }
.admin-hint  { font-size: 11px; color: var(--fg-3); margin-top: 2px; }

.admin-field input[type="text"],
.admin-field input[type="number"],
.admin-field select {
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  color: var(--fg-0);
  padding: 6px 8px;
  font-family: inherit;
  font-size: 13px;
  border-radius: var(--r-sm);
  width: 100%;
  box-sizing: border-box;
}
.admin-field input:focus, .admin-field select:focus { outline: none; border-color: var(--accent-line); }

.admin-inline-input {
  background: transparent;
  border: 1px solid transparent;
  color: var(--fg-0);
  padding: 4px 6px;
  font-family: inherit;
  font-size: 13px;
  width: 100%;
  border-radius: var(--r-sm);
}
.admin-inline-input:hover { border-color: var(--line-1); background: var(--bg-0); }
.admin-inline-input:focus { outline: none; border-color: var(--accent-line); background: var(--bg-0); }

.admin-section-group { margin-bottom: 16px; }
.admin-section-title { font-size: 10px; letter-spacing: 0.18em; color: var(--accent); margin-bottom: 6px; }

.admin-checks { display: flex; flex-direction: column; gap: 4px; }
.admin-checks.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 12px; }
.admin-check {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px;
  border-radius: var(--r-sm);
  font-size: 12px; color: var(--fg-1);
  cursor: pointer;
}
.admin-check:hover { background: var(--bg-2); }
.admin-check input[type="checkbox"] { accent-color: var(--accent); }

/* Per-faction membership rows in UnitEdit — checkbox + inline playable + last-edition select. */
.admin-memberships { display: flex; flex-direction: column; gap: 6px; }
.admin-membership {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) auto auto;
  align-items: center;
  gap: 12px;
  padding: 4px 6px;
  border-radius: var(--r-sm);
}
.admin-membership:hover { background: var(--bg-2); }
.admin-membership .admin-check { flex: 0 0 auto; padding: 0; }
.admin-membership-flag {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--fg-2); letter-spacing: .08em;
  cursor: pointer;
}
.admin-membership-flag input[type="checkbox"] { accent-color: var(--accent); }
.admin-membership-edition {
  font: inherit;
  font-size: 12px;
  padding: 3px 6px;
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  color: var(--fg-1);
}

.admin-product-row {
  position: relative;
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  padding: 12px 14px;
  margin-bottom: 12px;
}
.admin-product-sculpts { margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--line-1); }
.admin-product-del { position: absolute; top: 8px; right: 8px; }

/* ADMIN button in catalog topbar */
.admin-link-btn { width: auto !important; padding: 0 10px !important; text-decoration: none; color: var(--fg-1); }
.admin-link-btn:hover { color: var(--accent-fg); border-color: var(--accent-line); }

/* ── Image upload + thumbnail ──────────────────────────────── */
.admin-upload-cell {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
}
.admin-upload-cell input[type="text"] { flex: 1; min-width: 0; }
/* Hide the actual file input, use the wrapping label as the visible button */
.admin-upload-label {
  position: relative;
  cursor: pointer;
  flex-shrink: 0;
  text-decoration: none;
}
.admin-upload-input {
  position: absolute; inset: 0;
  opacity: 0;
  cursor: pointer;
  width: 100%; height: 100%;
}
/* Image preview thumbnail (40x40) used inline in admin tables and forms */
.admin-img-thumb {
  width: 36px; height: 36px;
  object-fit: cover;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-1);
  display: block;
  flex-shrink: 0;
}
.admin-img-thumb--empty {
  display: grid; place-items: center;
  background: var(--bg-2);
  color: var(--fg-3);
  font-family: var(--ff-mono);
  font-size: 14px;
}

/* ============================================================
   /products — public products listing
   ============================================================ */
/* No sidebar on this page — collapse the .ident-app grid to a single column. */
.ident-app.products-page { grid-template-columns: 1fr; }
.products-page .ident-main { padding-bottom: 60px; }

/* Banner shown when a deep-link narrowed the page to one product */
.products-focus-banner {
  background: var(--accent-dim);
  border-bottom: 1px solid var(--accent-line);
  padding: 8px 32px;
  display: flex; align-items: center; gap: 16px;
  font-size: 11px; letter-spacing: 0.16em;
  color: var(--accent-fg);
}
.products-focus-clear {
  margin-left: auto;
  color: var(--fg-2);
  text-decoration: none;
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.14em;
}
.products-focus-clear:hover { color: var(--accent-fg); }

.products-filters {
  position: sticky; top: 53px; z-index: 9;
  display: flex; flex-direction: column; gap: 10px;
  background: oklch(from var(--bg-0) l c h / 0.94);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line-1);
  padding: 14px 32px;
}
.products-filter-row {
  display: flex; align-items: center; gap: 12px;
  font-size: 13px; color: var(--fg-1);
}
.products-faction-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.products-faction-chip {
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.16em;
  padding: 4px 10px;
  border: 1px solid var(--line-1);
  background: var(--bg-1);
  color: var(--fg-2);
  cursor: pointer;
  border-radius: var(--r-sm);
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.products-faction-chip:hover { color: var(--fg-0); border-color: var(--line-2); }
.products-faction-chip.is-active {
  border-color: oklch(70% 0.18 var(--fh, var(--accent-hue)));
  background: oklch(70% 0.18 var(--fh, var(--accent-hue)) / 0.16);
  color: var(--fg-0);
}

.products-section {
  padding: 24px 32px;
  border-top: 1px solid var(--line-1);
}
.products-section:first-of-type { border-top: 0; }
.products-section-head {
  display: flex; align-items: baseline; gap: 12px;
  margin-bottom: 16px;
}
.products-section-code {
  font-size: 11px; letter-spacing: 0.18em;
  padding: 3px 10px;
  border: 1px solid oklch(70% 0.18 var(--fh, var(--accent-hue)));
  background: oklch(70% 0.18 var(--fh, var(--accent-hue)) / 0.18);
  color: oklch(85% 0.16 var(--fh, var(--accent-hue)));
  border-radius: var(--r-sm);
}
.products-section-head h2 { margin: 0; font-size: 20px; font-weight: 600; letter-spacing: 0.02em; color: var(--fg-0); }
.products-section-count { margin-left: auto; font-size: 11px; letter-spacing: 0.14em; color: var(--fg-3); }

.products-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
  gap: 14px;
}


/* ── Crop dialog ──────────────────────────────────────────────
   Modal cropper for the admin upload flow. Built by JS (ident.js → mountCropper),
   styled here. Sits above everything. */
.crop-scrim {
  position: fixed; inset: 0; z-index: 9999;
  background: oklch(0 0 0 / 0.65);
  display: grid; place-items: center;
  padding: 24px;
}
.crop-panel {
  background: var(--bg-1); border: 1px solid var(--accent-line); border-radius: var(--r-sm);
  display: flex; flex-direction: column; gap: 12px;
  padding: 16px 18px 14px;
  max-width: min(960px, 96vw); max-height: 92vh;
  box-shadow: 0 12px 48px oklch(0 0 0 / 0.4);
}
.crop-head h3 {
  margin: 0; font-size: 16px; font-weight: 600;
  font-family: var(--ff-mono); letter-spacing: 0.16em; color: var(--accent);
}
.crop-hint { font-size: 11px; color: var(--fg-3); margin-top: 4px; line-height: 1.4; max-width: 60ch; }

.crop-stage {
  flex: 1; min-height: 0; display: grid; place-items: center;
  background: repeating-conic-gradient(var(--bg-2) 0% 25%, var(--bg-1) 0% 50%) 0 0 / 16px 16px;
  border: 1px solid var(--line-1); border-radius: var(--r-sm);
  overflow: auto;
}
.crop-wrap {
  position: relative; line-height: 0;
  max-width: 100%; max-height: 80vh;
}
.crop-img { display: block; max-width: 100%; max-height: 80vh; user-select: none; }

/* Overlay sits on top of the image; pointer events go through to the rect/handles below it. */
.crop-overlay { position: absolute; inset: 0; pointer-events: none; }

/* The visible rectangle. The "halo" effect — dimming everything outside the rect — is done
   with an oversized box-shadow rather than a separate mask layer, so resizing is one element. */
.crop-rect {
  position: absolute;
  border: 1.5px solid var(--accent);
  box-shadow: 0 0 0 9999px oklch(0 0 0 / 0.55);
  cursor: move;
  pointer-events: auto;
  box-sizing: border-box;
}

.crop-handle {
  position: absolute; width: 12px; height: 12px;
  background: var(--accent); border: 1px solid var(--bg-0);
  border-radius: 2px;
  pointer-events: auto;
}
.crop-handle-nw { top: -6px;  left: -6px;  cursor: nwse-resize; }
.crop-handle-n  { top: -6px;  left: 50%;   transform: translateX(-50%); cursor: ns-resize; }
.crop-handle-ne { top: -6px;  right: -6px; cursor: nesw-resize; }
.crop-handle-e  { top: 50%;   right: -6px; transform: translateY(-50%); cursor: ew-resize; }
.crop-handle-se { bottom: -6px; right: -6px; cursor: nwse-resize; }
.crop-handle-s  { bottom: -6px; left: 50%;  transform: translateX(-50%); cursor: ns-resize; }
.crop-handle-sw { bottom: -6px; left: -6px; cursor: nesw-resize; }
.crop-handle-w  { top: 50%;   left: -6px;  transform: translateY(-50%); cursor: ew-resize; }

.crop-foot {
  display: flex; align-items: center; gap: 8px;
}
.crop-size { color: var(--fg-3); font-size: 11px; letter-spacing: 0.14em; margin-right: auto; }
.crop-btn {
  font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.14em;
  padding: 6px 12px; border-radius: var(--r-sm);
  background: var(--bg-2); color: var(--fg-1);
  border: 1px solid var(--line-1); cursor: pointer;
}
.crop-btn:hover { background: var(--bg-3); border-color: var(--line-2); }
.crop-btn.primary {
  background: var(--accent); color: var(--accent-fg); border-color: var(--accent);
}
.crop-btn.primary:hover { background: var(--accent); filter: brightness(1.08); }

/* ── SculptPicker (used in roster editor) ──────────────────────────────
   Custom Blazor dropdown: each option carries a small thumb, hovering shows a bigger
   preview to the right of the menu. Replaces a native <select> which can't render images. */
.sculpt-picker { position: relative; display: inline-block; min-width: 240px; }
.sculpt-picker-trigger {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 6px 10px;
  background: var(--bg-2);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  color: var(--fg-0);
  font-family: inherit; font-size: 12px;
  cursor: pointer;
  text-align: left;
}
.sculpt-picker-trigger:hover { border-color: var(--line-2); }
.sculpt-picker[aria-expanded="true"] .sculpt-picker-trigger,
.sculpt-picker-trigger[aria-expanded="True"] { border-color: var(--accent-line); }
.sculpt-picker-trigger-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sculpt-picker-caret { font-size: 10px; color: var(--fg-3); }

/* Menu sits below the trigger. Scrolls if a unit has many sculpts. */
.sculpt-picker-menu {
  position: absolute; top: calc(100% + 2px); left: 0;
  min-width: 100%;
  background: var(--bg-1);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-sm);
  box-shadow: 0 8px 24px oklch(0 0 0 / 0.5);
  padding: 4px;
  z-index: 100;
  max-height: 60vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 2px;
}
.sculpt-picker-option {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 4px 6px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 1px;
  color: var(--fg-0);
  font-family: inherit; font-size: 12px;
  text-align: left;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.sculpt-picker-option:hover { background: var(--bg-2); border-color: var(--line-1); }
.sculpt-picker-option.is-current { background: var(--accent-dim); border-color: var(--accent-line); }
.sculpt-picker-option-thumb {
  width: 32px; height: 44px; flex-shrink: 0;
  border-radius: 1px;
  background: radial-gradient(ellipse at 50% 28%, oklch(1 0 0 / 0.04), transparent 65%);
  display: grid; place-items: center;
  overflow: hidden;
}
.sculpt-picker-option-thumb--empty { color: var(--fg-3); font-size: 14px; }
.sculpt-picker-option-thumb img { width: 100%; height: 100%; object-fit: contain; }
.sculpt-picker-option-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sculpt-picker-option-year { font-size: 11px; letter-spacing: 0.14em; color: var(--fg-3); flex-shrink: 0; }

/* Floating preview to the right of the menu — pointer-events:none so it can't steal hover. */
.sculpt-picker-preview {
  position: absolute; top: calc(100% + 2px); left: calc(100% + 8px);
  background: var(--bg-1);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-sm);
  box-shadow: 0 8px 24px oklch(0 0 0 / 0.5);
  padding: 8px;
  z-index: 101;
  pointer-events: none;
  width: 132px;
}
.sculpt-picker-preview img {
  display: block;
  width: 116px; height: 156px;
  object-fit: contain;
  border-radius: var(--r-sm);
  background: radial-gradient(ellipse at 50% 28%, oklch(1 0 0 / 0.04), transparent 65%);
}
.sculpt-picker-preview-name {
  font-size: 11px; letter-spacing: 0.08em; color: var(--fg-1);
  text-align: center;
  margin-top: 6px;
  word-break: break-word;
}

/* ════════════════════════════════════════════════════════════════════════
   Products page redesign — primitives + ProductCard styles.

   Per-faction hue propagation: each <section class="products-section"> sets
   --fh = the faction's accent hue. Re-aliasing --accent-hue here makes every
   --accent-derived color inside the section (CTA fills, owned rails, sculpt
   tags, the corner badge) tint to the active faction automatically — without
   per-faction overrides on every rule below.
   ════════════════════════════════════════════════════════════════════════ */
.products-section {
  /* Re-tie the accent family to the locally-overridden --accent-hue. The :root-level
     --accent / --accent-dim / --accent-line have their var(--accent-hue) substitutions
     resolved at :root and inherit as fixed colors; redefining them here forces them to
     re-resolve against the section's faction hue. Without these lines, the CTA / toggle
     / sculpt-tag colors stay cyan no matter which faction's section the card lives in. */
  --accent-hue:  var(--fh, 220);
  --accent:      oklch(0.78 0.14 var(--accent-hue));
  --accent-dim:  oklch(0.78 0.14 var(--accent-hue) / 0.18);
  --accent-line: oklch(0.78 0.14 var(--accent-hue) / 0.45);
  --accent-soft: oklch(0.78 0.14 var(--accent-hue) / 0.55);
  --accent-fg:   oklch(0.85 0.16 var(--accent-hue));
}

/* ── Page hero strip (above the faction sections) ───────────────────── */
.hero-strip {
  margin: 28px clamp(20px, 3vw, 36px) 0;
  padding: 18px 22px;
  background: linear-gradient(90deg,
    oklch(0.78 0.14 60 / 0.08) 0%,
    oklch(0.78 0.14 60 / 0.02) 50%,
    transparent 100%);
  border-left: 2px solid var(--want);
  display: flex;
  align-items: center;
  gap: 22px;
}
.hero-num {
  font-family: var(--ff-mono);
  font-weight: 600;
  font-size: 36px;
  color: var(--want);
  line-height: 1;
  letter-spacing: -0.02em;
}
.hero-text { font-size: 14px; line-height: 1.5; color: var(--fg-1); }
.hero-text strong { color: var(--fg-0); font-weight: 600; }
.hero-text small {
  display: block;
  margin-top: 4px;
  font-family: var(--ff-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-3);
}

/* ── Card root ──────────────────────────────────────────────────────── */
.product {
  display: flex;
  flex-direction: column;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  position: relative;
}
.product[data-state="oop"] { background: oklch(0.18 0.012 240); }

/* ── Card header (thumb + title block + status pill) ─────────────────── */
.p-head {
  display: grid;
  grid-template-columns: 88px 1fr auto;
  gap: 16px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--line-1);
  align-items: center;
}
.p-thumb {
  width: 88px;
  aspect-ratio: 1 / 1;
  background: var(--bg-2);
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line-1);
}
.p-thumb img { width: 100%; height: 100%; object-fit: cover; }
.p-thumb .product-status-tag {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: grid; place-items: center;
  font-family: var(--ff-mono);
  font-size: 11px; letter-spacing: 0.18em; font-weight: 600;
  color: var(--warn);
  background: oklch(from var(--bg-0) l c h / 0.82);
  border: 0; border-top: 1px solid var(--warn);
  padding: 2px 4px;
}

.p-title { min-width: 0; }
.p-name { font-weight: 600; font-size: 15px; letter-spacing: -0.005em; line-height: 1.25; color: var(--fg-0); }
.p-meta {
  margin-top: 5px;
  font-family: var(--ff-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-2);
}
.p-meta .sep { opacity: 0.4; margin: 0 6px; }
.p-meta .owned-tally { color: var(--accent); }
.p-meta .wanted-tally { color: var(--want); }

/* Empty-state thumbnail: 2x2 silhouette grid + scan line + sculpt-count caption.
   Uses the <symbol id="mini"> defined in App.razor. */
.p-thumb.empty {
  background:
    radial-gradient(ellipse at 50% 30%, oklch(0.30 0.020 240) 0%, oklch(0.18 0.012 240) 70%, transparent 100%),
    var(--bg-2);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: repeat(2, 1fr);
  place-items: center;
  padding: 6px;
  gap: 2px;
}
.p-thumb.empty svg { width: 100%; height: 100%; opacity: 0.42; }
.p-thumb.empty::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px;
  background: var(--accent);
  opacity: 0.45;
}
.p-thumb.empty .lab {
  position: absolute;
  bottom: 4px; left: 4px;
  font-family: var(--ff-mono);
  font-size: 9px;
  letter-spacing: 0.24em;
  color: var(--accent);
  opacity: 0.7;
}

/* ── Value-prop band (between header and sculpts grid) ──────────────── */
/* Two render modes — wishlist-value ("hot") and neutral ("muted") — at the
   same min-height so sculpts grids align across cards in the same row. */
.p-value {
  padding: 14px 18px;
  border-bottom: 1px solid var(--line-1);
  display: flex;
  align-items: center;
  gap: 14px;
  position: relative;
  min-height: 78px;
}
.p-value::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: var(--want);
}
.p-value[data-tone="muted"]::before { background: var(--line-2); }
.p-value[data-tone="muted"] { background: oklch(0.18 0.012 240); }
.p-value[data-tone="hot"] {
  background: linear-gradient(90deg,
    oklch(0.78 0.14 60 / 0.10) 0%,
    oklch(0.78 0.14 60 / 0.02) 70%,
    transparent 100%);
}
.vp-num {
  font-family: var(--ff-mono);
  font-weight: 600;
  font-size: 30px;
  color: var(--want);
  line-height: 1;
  letter-spacing: -0.02em;
}
.vp-stack { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.vp-key {
  font-family: var(--ff-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-1);
  line-height: 1.2;
}
.vp-key.dim { color: var(--fg-3); font-size: 11px; letter-spacing: 0.16em; }

/* ── Sculpts grid ───────────────────────────────────────────────────── */
.p-sculpts {
  padding: 16px 18px;
  flex: 1;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
  gap: 14px 10px;
  align-content: start;
}
.sculpt {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  position: relative;       /* anchors the rail ::before below */
  transition: transform .12s;
  /* Per-sculpt --accent-hue is set inline (style="--accent-hue: <unit's faction>").
     Re-derive the accent family in this scope so the sculpt's own faction colors
     drive the tag chip / rail / count chip — see comment on .products-section above
     for why the :root-level accent vars don't pick up nested --accent-hue overrides. */
  --accent:      oklch(0.78 0.14 var(--accent-hue));
  --accent-dim:  oklch(0.78 0.14 var(--accent-hue) / 0.18);
  --accent-line: oklch(0.78 0.14 var(--accent-hue) / 0.45);
  --accent-soft: oklch(0.78 0.14 var(--accent-hue) / 0.55);
  --accent-fg:   oklch(0.85 0.16 var(--accent-hue));
}
.sculpt:hover { transform: scale(1.02); }
.sculpt-head { display: flex; align-items: center; gap: 5px; height: 14px; }
.sculpt-tag {
  display: inline-grid; place-items: center;
  height: 12px; padding: 0 4px;
  background: var(--accent-dim);
  border: 1px solid var(--accent-line);
  color: var(--accent);
  font-family: var(--ff-mono);
  font-size: 9px; letter-spacing: 0.16em; text-transform: uppercase;
  flex-shrink: 0;
}
.sculpt-name {
  font-family: var(--ff-mono);
  font-size: 11px;
  color: var(--fg-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0; flex: 1;
}
.sculpt-img {
  aspect-ratio: 1 / 1.18;
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(ellipse 70% 55% at 50% 38%, oklch(0.26 0.018 240) 0%, oklch(0.16 0.010 240) 75%, transparent 100%),
    oklch(0.14 0.010 240);
}
.sculpt-img img { width: 100%; height: 100%; object-fit: contain; }
.sculpt-img > .placeholder-glyph {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 9px;
}
/* Empty-state silhouette: shown when the sculpt has no ImageUrl. Uses the #mini symbol
   from App.razor; the SVG fills the whole container with default xMidYMid meet centering. */
.sculpt-img.empty svg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  filter: drop-shadow(0 3px 6px oklch(0.06 0.010 240 / 0.6));
}
.sculpt-img.empty::after {
  content: "";
  position: absolute;
  top: 50%; left: 0; right: 0;
  height: 1px;
  background: var(--accent-soft);
  opacity: 0.45;
  z-index: 1;   /* above the silhouette so the scan line reads */
}
/* Status rail in the gap between the head row and the image — solid accent for owned,
   dashed warn for wanted. Lives on the .sculpt parent (not on .sculpt-img) so it doesn't
   overlay the figure's head. The 14px head row + 2px buffer = top:16px, sitting in the
   6px gap; pointer-events:none so the rail doesn't intercept clicks on the head row. */
.sculpt[data-rail="own"]::before,
.sculpt[data-rail="want"]::before {
  content: "";
  position: absolute;
  left: 8%; right: 8%;
  top: 16px;
  height: 2px;
  z-index: 2;
  pointer-events: none;
}
.sculpt[data-rail="own"]::before { background: var(--accent); }
.sculpt[data-rail="want"]::before {
  background: repeating-linear-gradient(90deg, var(--want) 0 4px, transparent 4px 7px);
}
/* Owned-count chip in the head row: only renders when count > 1. flex:none keeps it at
   its natural width so the .sculpt-name (flex:1, ellipsis) just truncates a character
   earlier. Single-owned and wanted states need no chip — the rail in the gap above the
   image is enough to read each at a glance. */
.sculpt-count {
  flex: none;
  font-family: var(--ff-mono);
  font-size: 11px;
  color: var(--accent);
  letter-spacing: 0.04em;
  padding-left: 6px;
}

/* ── Card footer (toggles + primary/secondary CTA) ───────────────────── */
.p-foot {
  margin-top: auto;
  padding: 14px 18px;
  border-top: 1px solid var(--line-1);
  display: flex;
  align-items: center;
  gap: 10px;
  background: oklch(from var(--bg-0) l c h / 0.4);
  flex-wrap: wrap;
}
.toggles { display: flex; gap: 8px; flex-wrap: wrap; }
.foot-spacer { flex: 1; }

.toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 11px;
  border: 1px solid var(--line-1);
  background: transparent;
  color: var(--fg-2);
  font-family: var(--ff-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.toggle:hover { color: var(--fg-1); border-color: var(--line-2); }
.toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.toggle[data-on="own"] {
  background: var(--accent-dim);
  border-color: var(--accent-line);
  color: var(--accent);
}
.toggle[data-on="want"] {
  background: var(--want-dim);
  border-color: var(--want-line);
  color: var(--want);
}
.toggle .ico { width: 10px; height: 10px; display: inline-grid; place-items: center; line-height: 1; letter-spacing: 0; }

/* Chamfered primary CTA — the affiliate buy link. Filled accent (faction-tinted),
   dark text, 8px clipped corners on TR + BL for the catalog HUD chrome look. */
.cta-primary {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 11px 18px;
  background: var(--accent);
  color: oklch(0.10 0.012 240);
  font-family: var(--ff-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
  position: relative;
  clip-path: polygon(
    8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px
  );
  transition: filter .15s ease, gap .15s ease;
}
.cta-primary:hover { filter: brightness(1.12); gap: 14px; }
.cta-primary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cta-primary .arrow { font-weight: 400; }

/* Same shape as primary, softer fill — used for OOP secondhand links (no affiliate revenue). */
.cta-secondary {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 11px 18px;
  background: var(--accent-dim);
  color: var(--accent);
  font-family: var(--ff-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
  position: relative;
  clip-path: polygon(
    8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px
  );
  transition: background .15s ease, gap .15s ease;
}
.cta-secondary:hover {
  /* Faction-tinted hover (per-section --accent-hue inheritance does the work). */
  background: oklch(0.78 0.14 var(--accent-hue) / 0.28);
  gap: 14px;
}
.cta-secondary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cta-secondary .arrow { font-weight: 400; }

/* ─────────── Admin: data import page ─────────── */

/* -- details/summary baseline -------------------------------------------- */
details > summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
}
details > summary::-webkit-details-marker { display: none; }
details > summary::before {
  content: '\25B6';
  display: inline-block;
  font-size: 9px;
  margin-right: 6px;
  color: var(--fg-3);
  transition: transform 0.15s;
}
details[open] > summary::before { transform: rotate(90deg); }

/* -- import-progress-stack (page wrapper) --------------------------------- */
.import-progress-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 24px;
}

/* -- ImportProgressBar ---------------------------------------------------- */
.import-progress-bar {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  padding: 12px 14px;
}
.import-progress-bar.is-running { border-color: var(--accent-line); background: var(--accent-dim); }
.import-progress-bar.is-complete { border-color: oklch(0.55 0.15 145 / 0.5); background: oklch(0.20 0.04 145 / 0.4); }
.import-progress-bar.is-error { border-color: oklch(0.65 0.18 25 / 0.6); background: oklch(0.30 0.10 25 / 0.3); }

.import-progress-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  gap: 12px;
}
.import-progress-phase {
  font-family: var(--ff-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--fg-0);
  text-transform: uppercase;
}
.import-progress-status {
  font-family: var(--ff-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--fg-2);
}
.is-running  .import-progress-status { color: var(--accent-fg); }
.is-complete .import-progress-status { color: oklch(0.72 0.14 145); }
.is-error    .import-progress-status { color: oklch(0.80 0.12 25); }

.import-progress-track {
  height: 6px;
  background: var(--bg-2);
  border-radius: 3px;
  overflow: hidden;
  margin-bottom: 6px;
}
.import-progress-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 3px;
  transition: width 0.3s ease;
}
.is-running .import-progress-fill {
  background: var(--accent);
  animation: import-pulse 1.4s ease-in-out infinite;
}
.is-complete .import-progress-fill { background: oklch(0.60 0.14 145); }
.is-error    .import-progress-fill { background: oklch(0.65 0.18 25 / 0.7); }

@keyframes import-pulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.6; }
}

.import-progress-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.import-progress-label {
  font-family: var(--ff-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--fg-3);
}

/* -- ImportSummaryPanel --------------------------------------------------- */
.import-summary-panel {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  padding: 16px 18px;
  margin-bottom: 20px;
}
.import-summary-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  gap: 12px;
}
.import-summary-tag {
  display: inline-block;
  font-family: var(--ff-mono);
  font-size: 9px;
  letter-spacing: 0.16em;
  padding: 2px 6px;
  border: 1px solid var(--line-2);
  border-radius: 2px;
  color: var(--fg-2);
  text-transform: uppercase;
  margin-right: 6px;
}
.import-summary-tag.dry-run  { color: var(--warn, oklch(0.82 0.14 60)); border-color: oklch(0.78 0.14 60 / 0.5); background: oklch(0.24 0.06 60 / 0.3); }
.import-summary-tag.committed { color: var(--accent-fg); border-color: var(--accent-line); background: var(--accent-dim); }

.import-summary-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  overflow: hidden;
  font-size: 13px;
  margin-bottom: 12px;
}
.import-summary-table th {
  text-align: left;
  background: var(--bg-2);
  padding: 7px 10px;
  font-family: var(--ff-mono);
  font-size: 10px; letter-spacing: 0.14em;
  color: var(--fg-2);
  text-transform: uppercase;
  border-bottom: 1px solid var(--line-1);
  font-weight: 600;
}
.import-summary-table td {
  padding: 7px 10px;
  border-bottom: 1px solid var(--line-1);
  color: var(--fg-1);
  vertical-align: middle;
}
.import-summary-table tr:last-child td { border-bottom: 0; }
.import-summary-table tr:hover td { background: var(--bg-2); }

.import-summary-section {
  background: var(--bg-0);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  margin-top: 8px;
  font-size: 13px;
}
.import-summary-section.is-error { border-color: oklch(0.65 0.18 25 / 0.5); background: oklch(0.30 0.10 25 / 0.2); }
.import-summary-section > summary {
  font-family: var(--ff-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--fg-2);
  text-transform: uppercase;
  padding: 2px 0;
}
.import-summary-section.is-error > summary { color: oklch(0.80 0.12 25); }

.import-summary-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.import-summary-list li {
  font-size: 12px;
  color: var(--fg-1);
  padding: 3px 0 3px 14px;
  position: relative;
}
.import-summary-list li::before {
  content: '\2013';
  position: absolute; left: 2px;
  color: var(--fg-3);
}
/* Needs-curation items look clickable */
.import-summary-list li a, .import-summary-list li.link {
  color: var(--accent-fg);
  text-decoration: none;
  cursor: pointer;
}
.import-summary-list li a:hover, .import-summary-list li.link:hover {
  color: var(--accent);
  text-decoration: underline;
}

.import-summary-subgroup {
  margin-top: 8px;
}
.import-summary-subgroup-header {
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--fg-2);
  margin-bottom: 4px;
}

/* -- ImportHistoryList ---------------------------------------------------- */
.import-history-list {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.import-history-rows {
  list-style: none;
  margin: 0; padding: 0;
}
.import-history-rows > li {
  border-bottom: 1px solid var(--line-1);
}
.import-history-rows > li:last-child { border-bottom: 0; }
.import-history-rows > li > details > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  font-size: 13px;
  color: var(--fg-1);
  transition: background 0.1s;
}
.import-history-rows > li > details > summary:hover { background: var(--bg-2); }
.import-history-rows > li > details > summary::before { color: var(--fg-3); }

.import-history-tag {
  font-family: var(--ff-mono);
  font-size: 9px; letter-spacing: 0.16em;
  padding: 1px 5px;
  border: 1px solid var(--line-2);
  border-radius: 2px;
  text-transform: uppercase;
  flex-shrink: 0;
}
.import-history-tag.dry  { color: var(--warn, oklch(0.82 0.14 60)); border-color: oklch(0.78 0.14 60 / 0.5); }
.import-history-tag.real { color: var(--accent-fg); border-color: var(--accent-line); background: var(--accent-dim); }

.import-history-status {
  font-family: var(--ff-mono);
  font-size: 10px; letter-spacing: 0.12em;
  margin-left: auto;
  flex-shrink: 0;
}
.import-history-status.ok    { color: oklch(0.72 0.14 145); }
.import-history-status.info  { color: var(--fg-2); }
.import-history-status.error { color: oklch(0.80 0.12 25); }

.import-history-detail {
  padding: 10px 14px 12px 32px;
  border-top: 1px solid var(--line-1);
  background: var(--bg-0);
  font-size: 12px;
  color: var(--fg-2);
}

/* -- DataDumpUpload ------------------------------------------------------- */
.data-dump-upload {
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  padding: 16px 18px;
  margin-bottom: 20px;
}
.data-dump-status {
  margin-bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.data-dump-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 13px;
  color: var(--fg-1);
}
.data-dump-label {
  font-family: var(--ff-mono);
  font-size: 10px; letter-spacing: 0.14em;
  color: var(--fg-3);
  min-width: 110px;
  flex-shrink: 0;
}
.data-dump-value {
  color: var(--fg-0);
  font-size: 13px;
}
.data-dump-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 8px;
}
