/* ============================================================================
   HoloCare.Web — app.css  ·  POKEDEX LIGHT THEME
   Re-skin of the app from the old dark Bootstrap look to the Pokedex design
   system. Layout/geometry is preserved 1:1 from the original; only colors,
   typography, borders, radii and elevation are remapped to design tokens.

   HOW THIS WORKS
   - Imports the design-system token + component layers.
   - Overrides Bootstrap 5.3 CSS variables so every Bootstrap component (.btn,
     .form-control, .form-select, .badge, .modal…) adopts the light palette.
   - Restyles HoloCare's own classes with semantic tokens.

   IMPORTANT companion change (see handoff README):
   - In wwwroot/index.html change  <html lang="en" data-bs-theme="dark">
                              to    <html lang="en" data-bs-theme="light">
   - The old "[data-bs-theme=dark] …" override block is intentionally GONE.
   ============================================================================ */

@import url("ds-tokens.css");
@import url("ds-anatomical.css");
@import url("ds-type.css");
@import url("ds-components.css");
@import url("case.css");
@import url("learn.css");

/* ---------------------------------------------------------------------------
   1 · BOOTSTRAP THEME → POKEDEX (light + violet)
   Map Bootstrap's design variables to our tokens so its components reskin.
--------------------------------------------------------------------------- */
:root,
[data-bs-theme="light"] {
  --bs-primary: var(--violet-600);
  --bs-primary-rgb: 24, 85, 148;
  --bs-link-color: var(--violet-600);
  --bs-link-color-rgb: 24, 85, 148;
  --bs-link-hover-color: var(--violet-700);

  --bs-body-bg: var(--bg-app);
  --bs-body-color: var(--fg-primary);
  --bs-secondary-color: var(--fg-secondary);
  --bs-tertiary-color: var(--fg-muted);
  --bs-border-color: var(--border-default);
  --bs-secondary-bg: var(--bg-sunken);
  --bs-tertiary-bg: var(--bg-sunken);

  --bs-border-radius: var(--radius-sm);
  --bs-border-radius-sm: var(--radius-xs);
  --bs-border-radius-lg: var(--radius-md);

  --bs-font-sans-serif: var(--font-sans);
  --bs-body-font-size: var(--text-base);

  --bs-danger: var(--red-500);  --bs-danger-rgb: 229, 72, 77;
  --bs-success: var(--mint-600);
  --bs-warning: var(--amber-500);
  --bs-info: var(--blue-500);
}

/* Dark theme: same token-driven mapping, with dark-appropriate literal rgb pairs. Our semantic tokens
   (--bg-app, --accent, …) already flip via the [data-bs-theme="dark"] block in ds-tokens.css, so every
   Bootstrap component reskins to the dark palette. Loaded after bootstrap.min.css → wins on its dark block. */
[data-bs-theme="dark"] {
  --bs-primary: var(--accent);
  --bs-primary-rgb: 42, 107, 173;            /* violet-500 (blue) */
  --bs-link-color: var(--fg-link);
  --bs-link-color-rgb: 133, 176, 217;        /* violet-300 (blue) */
  --bs-link-hover-color: var(--accent-hover);

  --bs-body-bg: var(--bg-app);
  --bs-body-color: var(--fg-primary);
  --bs-emphasis-color: var(--fg-primary);
  --bs-secondary-color: var(--fg-secondary);
  --bs-tertiary-color: var(--fg-muted);
  --bs-border-color: var(--border-default);
  --bs-secondary-bg: var(--bg-sunken);
  --bs-tertiary-bg: var(--bg-sunken);

  --bs-danger: var(--danger);  --bs-danger-rgb: 240, 86, 91;
  --bs-success: var(--success);
  --bs-warning: var(--warning);
  --bs-info: var(--info);
}

html, body { font-family: var(--font-sans); background: var(--bg-app); color: var(--fg-primary); }

/* Links */
a, .btn-link { color: var(--fg-link); text-decoration: none; }
a:hover, .btn-link:hover { color: var(--accent-hover); }

/* ---- Buttons: lean on the design system, override Bootstrap class names ---- */
.btn { border-radius: var(--radius-sm); font-weight: var(--weight-medium); font-size: var(--text-sm); transition: var(--transition-colors); }
.btn-primary { color: var(--fg-on-accent); background-color: var(--accent); border-color: var(--accent); }
.btn-primary:hover, .btn-primary:focus { color: var(--fg-on-accent); background-color: var(--accent-hover); border-color: var(--accent-hover); }
.btn-primary:active { background-color: var(--accent-active) !important; border-color: var(--accent-active) !important; }

.btn-secondary { color: var(--accent-fg); background-color: var(--accent-subtle); border-color: transparent; }
.btn-secondary:hover, .btn-secondary:focus { color: var(--accent-fg); background-color: var(--accent-subtle-hover); border-color: transparent; }

.btn-light { color: var(--fg-primary); background-color: var(--bg-surface); border-color: var(--border-default); }
.btn-light:hover { background-color: var(--bg-hover); border-color: var(--border-strong); }
.btn-light:active, .btn-light.btn-primary { background-color: var(--accent-subtle) !important; border-color: var(--border-accent) !important; color: var(--accent-fg) !important; }

.btn-outline-secondary { color: var(--fg-secondary); border-color: var(--border-default); }
.btn-outline-secondary:hover { color: var(--fg-primary); background-color: var(--bg-hover); border-color: var(--border-strong); }

/* red-600 (not --danger/red-500) so white label clears WCAG AA (5.1:1) in both themes. */
.btn-danger { background-color: var(--red-600); border-color: var(--red-600); color: #fff; }
.btn-danger:hover { background-color: var(--red-700); border-color: var(--red-700); }
.btn-outline-danger { color: var(--danger-fg); border-color: var(--red-100); }
.btn-outline-danger:hover { background-color: var(--danger-bg); border-color: var(--red-100); color: var(--danger-fg); }

/* Leading icon inside a text button — token spacing (replaces inline margins). */
.btn__icon-leading { margin-right: var(--space-3); }

/* One consistent focus ring everywhere. */
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus,
.form-control:focus, .form-select:focus, .form-check-input:focus {
  box-shadow: var(--ring-focus);
}

/* Form controls */
.form-control, .form-select { border-color: var(--border-default); border-radius: var(--radius-sm); color: var(--fg-primary); background-color: var(--bg-surface); }
.form-control:focus, .form-select:focus { border-color: var(--accent); }
.form-check-input:checked { background-color: var(--accent); border-color: var(--accent); }

.content { padding-top: 1.1rem; }
.valid.modified:not([type=checkbox]) { outline: 1px solid var(--mint-600); }
.invalid { outline: 1px solid var(--danger); }
.validation-message { color: var(--danger); }
code { color: var(--accent-fg); background: var(--accent-subtle); padding: 0.1em 0.36em; border-radius: var(--radius-xs); }

/* Blazor error UI + loading spinner */
#blazor-error-ui { color-scheme: light only; background: var(--warning-bg); bottom: 0; box-shadow: var(--shadow-md); box-sizing: border-box; display: none; left: 0; padding: 0.6rem 1.25rem 0.7rem; position: fixed; width: 100%; z-index: var(--z-toast); }
#blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: 0.75rem; top: 0.5rem; }
.blazor-error-boundary { background: var(--danger); padding: 1rem 1rem 1rem 3.7rem; color: white; }
.blazor-error-boundary::after { content: "An error has occurred."; }
.loading-progress { position: absolute; display: block; width: 8rem; height: 8rem; inset: 20vh 0 auto 0; margin: 0 auto; }
.loading-progress circle { fill: none; stroke: var(--slate-150); stroke-width: 0.6rem; transform-origin: 50% 50%; transform: rotate(-90deg); }
.loading-progress circle:last-child { stroke: var(--accent); stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%; transition: stroke-dasharray 0.05s ease-in-out; }
.loading-progress-text { position: absolute; text-align: center; font-weight: bold; inset: calc(20vh + 3.25rem) 0 auto 0.2rem; color: var(--fg-secondary); }
.loading-progress-text:after { content: var(--blazor-load-percentage-text, "Loading"); }

/* ===========================================================================
   2 · HOLOSCOPE EDITOR  (layout preserved; colors → tokens)
=========================================================================== */
/* Fill the area below the app header (the logged-in user bar) instead of a hard 100vh — otherwise the
   header pushes the editor down and the bottom of the sidebar (W/L + colour settings) falls below the fold. */
.editor { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.5rem; height: 100%; box-sizing: border-box; overflow: hidden; background: var(--bg-app); }
.editor__toolbar { position: relative; display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; flex: 0 0 auto; }

/* AI assistant entry — a compact top-bar pill (replaces the floating bubble inside the editor). */
.editor-chatbtn { flex-shrink: 0; display: inline-flex; align-items: center; gap: 0.35rem; height: 30px; padding: 0 0.6rem 0 0.55rem;
    border-radius: var(--radius-full); border: 1px solid var(--border-default); background: var(--bg-surface);
    color: var(--fg-secondary); font-size: var(--text-xs); font-weight: var(--weight-semibold); line-height: 1; cursor: pointer;
    transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard); }
.editor-chatbtn:hover:not(:disabled) { background: var(--bg-hover); color: var(--fg-primary); border-color: var(--border-strong); }
.editor-chatbtn:disabled { opacity: .45; cursor: default; }
.editor-chatbtn:disabled .editor-chatbtn__ico { color: currentColor; }
.editor-chatbtn__ico { display: inline-flex; color: var(--accent); }
.editor-chatbtn.is-open { background: var(--accent-subtle); border-color: var(--border-accent); color: var(--accent-fg); }
.editor-chatbtn.is-open .editor-chatbtn__ico { color: var(--accent-fg); }
.editor-chatbtn__label { white-space: nowrap; }
.editor__viewsettings { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.5rem; background: var(--bg-sunken); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); }
/* Shared case note (editor sidebar, below the brush panel) */
.editor__notes { display: flex; flex-direction: column; gap: 0.3rem; padding: 0.5rem; background: var(--bg-sunken); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); flex: 0 0 auto; }
.editor__notes-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; }
.editor__notes-label { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--fg-secondary); }
.editor__notes-hint { font-size: var(--text-2xs); color: var(--fg-muted); }
.editor__notes-input { width: 100%; resize: vertical; box-sizing: border-box; font-size: var(--text-xs); padding: 0.35rem 0.45rem; border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-surface); color: var(--fg-primary); }

.editor__viewtoggles { display: flex; gap: 1rem; font-size: var(--text-sm); }
.editor__viewtoggles label { display: flex; align-items: center; gap: 0.3rem; cursor: pointer; color: var(--fg-secondary); }
.editor__dims { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--fg-muted); }
.editor__empty { color: var(--fg-muted); padding: 2rem; }
/* Unified loading panel (spinner + title + phase) — shared look with the import "Building case" screen. */
.hs-loading { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 0.75rem; padding: 4rem 1.5rem; color: var(--fg-muted); }
/* Boot-overlap: cover the (still-empty) booting canvas with the loading spinner until HasVolume. */
.hs-loading--overlay { position: absolute; inset: 0; background: var(--bg-app); z-index: 5; padding: 0; }
.hs-loading__spinner { width: 40px; height: 40px; border: 3px solid var(--slate-150); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; }
.hs-loading__title { font-size: var(--text-h3); font-weight: var(--weight-semibold); color: var(--fg-primary); }
.hs-loading__sub { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--fg-muted); min-height: 1.2em; }

/* Centered error state (case failed to open / not found) — card-like, matches the loading panel. */
.hs-error { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 0.6rem; padding: 4rem 1.5rem; max-width: 30rem; margin: 0 auto; }
.hs-error__icon { display: flex; align-items: center; justify-content: center; width: 56px; height: 56px; border-radius: 50%; background: var(--danger-bg); color: var(--danger); margin-bottom: 0.25rem; }
.hs-error__icon--muted { background: var(--slate-150); color: var(--fg-muted); }
.hs-error__title { font-size: var(--text-h3); font-weight: var(--weight-semibold); color: var(--fg-primary); }
.hs-error__msg { font-size: var(--text-sm); color: var(--fg-muted); line-height: 1.5; }
.hs-error__actions { display: flex; gap: 0.5rem; justify-content: center; margin-top: 0.75rem; }

/* The imaging panes stay DARK by design (radiology convention + contrast). */
.slice-view { display: flex; flex-direction: column; background: var(--bg-canvas); border-radius: var(--radius-sm); padding: 0.25rem; min-height: 0; min-width: 0; }
.slice-view__header { display: flex; justify-content: space-between; color: var(--fg-on-canvas); font-size: var(--text-xs); padding: 0.15rem 0.35rem; flex: 0 0 auto; }
.slice-view__canvas { flex: 1 1 auto; width: 100%; min-height: 0; image-rendering: pixelated; background: #000; object-fit: contain; }
/* Slice slider only reveals while the cursor is over that pane (opacity, not display → no reflow).
   The cell is pointer-events:none (brush strokes pass through to the canvas) so CSS :hover can't drive
   this — viewport.input.js reports the hovered pane and toggles .is-hover. */
/* Compact slice slider, inline in the header to the left of the slice index. Revealed only while the
   cursor is over the pane (JS toggles .is-hover) OR while the slider itself is hovered/focused/dragged
   (moving onto it fires the canvas pointerleave that clears .is-hover — :hover/:active bridge that). */
.slice-view__slider { width: 18rem; min-width: 3rem; height: 1rem; margin: 0; flex: 0 1 auto; accent-color: var(--violet-400); opacity: 0; transition: opacity 0.12s ease; }
/* Revealed while: the cursor is over the pane (JS .is-hover); OR any interactive header control is hovered
   (moving onto the slider/fs button fires the canvas pointerleave that clears .is-hover — the header gets
   :hover from its interactive descendants even though it's pointer-events:none, bridging the handoff); OR
   the slider is being dragged/keyboard-focused. :focus-visible NOT :focus so a mouse click doesn't pin it. */
.slice-view__slider.is-hover, .slice-view__header:hover .slice-view__slider, .slice-view__slider:focus-visible, .slice-view__slider:active { opacity: 1; }

.editor-viewport { position: relative; width: 100%; height: 100%; min-width: 0; min-height: 0; background: var(--bg-canvas); border-radius: var(--radius-sm); }
.editor-viewport__canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.editor-viewport__overlay { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(2, 1fr); pointer-events: none; }
.ev-cell { position: relative; display: flex; flex-direction: column; justify-content: space-between; min-width: 0; min-height: 0; padding: 0.25rem; }
/* The header is an overlay strip across the TOP of the canvas. Don't give the whole bar pointer-events
   (it would swallow a brush press in that strip — you couldn't START a stroke near the top, only drag in).
   Only the interactive children opt back in (.ev-fs button + .slice-view__toggle, below); the title/index
   text + empty space stay transparent so a press there falls through to the canvas. */
.ev-cell .slice-view__slider, .ev-cell .slice-view__toggle { pointer-events: auto; }
.editor-viewport__overlay--full { grid-template-columns: 1fr; grid-template-rows: 1fr; }
.slice-view__hdr-right { display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
/* Per-pane fullscreen toggle — same square-icon look as .ev-vtool, sized like the mini clip buttons so it
   sits flush in the header row. */
.ev-fs { pointer-events: auto; width: 1.95rem; height: 1.95rem; display: inline-flex; align-items: center; justify-content: center; padding: 0; border-radius: var(--radius-sm); border: 1px solid rgba(255,255,255,0.16); background: rgba(18,20,26,0.5); color: var(--fg-on-canvas); cursor: pointer; transition: var(--transition-colors); line-height: 1; -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
.ev-fs:hover { background: rgba(40,44,54,0.72); border-color: rgba(255,255,255,0.38); }
.ev-fs__icon { width: 16px; height: 16px; }
/* Square icon toggles stacked on the right edge of the 3D pane (volume / seg / hide-table / cinematic +
   clip plane, and the clip orientation sub-row). The overlay is pointer-events:none; each button opts
   back in so empty gaps still fall through to the canvas (orbit). */
.ev-vstack { position: absolute; top: 0.4rem; right: 0.4rem; display: flex; flex-direction: column; align-items: flex-end; gap: 0.3rem; z-index: 2; }
/* Clip-plane toggle bar, bottom-right corner of the 3D pane; right-anchored so the orientation/flip
   sub-row (DOM order before the toggle) fans out to the LEFT while the toggle stays put in the corner. */
.ev-clipbar { position: absolute; right: 0.4rem; bottom: 0.4rem; display: flex; flex-direction: column; align-items: flex-end; gap: 0.3rem; z-index: 2; }
/* Clip toggle + its orientation sub-row stay on one horizontal row (sub-row fans LEFT) even though the
   outer bar is now a vertical column matching the top stack. */
.ev-clipgroup { display: flex; flex-direction: row; align-items: center; gap: 0.3rem; }
.ev-vtool { pointer-events: auto; width: 1.95rem; height: 1.95rem; display: inline-flex; align-items: center; justify-content: center; padding: 0; border-radius: var(--radius-sm); border: 1px solid rgba(255,255,255,0.16); background: rgba(18,20,26,0.5); color: var(--fg-on-canvas); cursor: pointer; transition: var(--transition-colors); font-size: var(--text-2xs); font-weight: var(--weight-bold, 700); line-height: 1; -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
.ev-vtool:hover:not(:disabled) { background: rgba(40,44,54,0.72); border-color: rgba(255,255,255,0.38); }

/* Split overlay mirrors the renderer's split cells() (SPLIT_LARGE_FRAC = 0.75): left half = large slice
   (top 75%) over a 3-plane mini strip (bottom 25%); right half = 3D. Keep 75/25 + thirds in sync with cells(). */
/* Reuse the base grid's repeat(2,1fr) COLUMNS (single row) so the 50% divider rounds pixel-identically to
   the quad layout — a flex split rounds the boundary slightly differently, shifting the 3D title / 2D
   padding by ~1px between layouts. Children auto-place into col 1 (2D) and col 2 (3D). */
/* Columns follow the draggable divider (--hs-split, default 0.5); the renderer's cells() splits at the same
   fraction so the 2D/3D canvas panes and these HTML overlays stay aligned. */
.editor-viewport__overlay--split { grid-template-columns: calc(var(--hs-split, 0.5) * 100%) 1fr; grid-template-rows: 1fr; }
.ev-split__left { min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.ev-split__right { min-width: 0; min-height: 0; }
.ev-split__large { flex: 0 0 75%; min-height: 0; }
/* Strip fills the bottom 25% with no padding/gap so its buttons tile EXACTLY over the canvas mini-slices
   (which have no inset) — any gap here lets the slice peek out past the frame. Borders draw INSIDE
   (box-sizing) so a frame never grows the button past its canvas cell. */
.ev-split__strip { flex: 0 0 25%; min-height: 0; display: flex; flex-direction: row; }
.ev-mini { pointer-events: auto; position: relative; flex: 1 1 0; min-width: 0; box-sizing: border-box; border: 1px solid rgba(255,255,255,0.22); border-radius: var(--radius-sm); background: transparent; cursor: pointer; transition: border-color 0.12s ease, box-shadow 0.12s ease; padding: 0; }
.ev-mini:hover { border-color: rgba(255,255,255,0.55); }
.ev-mini.is-active { border-color: var(--violet-400, #9a82ff); box-shadow: 0 0 0 2px var(--violet-400, #9a82ff) inset; z-index: 1; }
.ev-mini__tag { position: absolute; left: 3px; bottom: 2px; font-size: var(--text-2xs); font-weight: var(--weight-bold, 700); color: var(--fg-on-canvas); text-shadow: 0 1px 2px rgba(0,0,0,0.85); pointer-events: none; }
.ev-mini.is-active .ev-mini__tag { color: #fff; }

/* Draggable split divider — a thin grab strip centred on the 2D|3D boundary (--hs-split). Drag handled in
   viewport.input.js; this is just the affordance. Sits above the pane overlays so it's always grabbable. */
.ev-divider { position: absolute; top: 0; bottom: 0; left: calc(var(--hs-split, 0.5) * 100%); transform: translateX(-50%);
  width: 14px; z-index: 6; cursor: col-resize; pointer-events: auto; display: flex; align-items: center; justify-content: center;
  touch-action: none; }
.ev-divider::before { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; transform: translateX(-50%);
  width: 2px; background: rgba(255,255,255,0.16); transition: background 0.12s ease, width 0.12s ease; }
.ev-divider:hover::before, .ev-divider:active::before { background: var(--accent, #7aa2ff); width: 3px; }
.ev-divider__grip { position: relative; width: 4px; height: 36px; border-radius: 3px; background: rgba(255,255,255,0.3);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.45); transition: background 0.12s ease; }
.ev-divider:hover .ev-divider__grip, .ev-divider:active .ev-divider__grip { background: #fff; }

/* Focus layout: 4fr:1fr COLUMNS (large 80% + rail 20%) — matches FOCUS_RAIL_FRAC (0.2) and rounds like the
   quad/split grids. The rail is a vertical 4-stack of thumbnail buttons over the (inset) canvas thumbnails;
   tiles reuse the .ev-mini look. Click promotes; the active one is bordered. */
.editor-viewport__overlay--focus { grid-template-columns: 4fr 1fr; grid-template-rows: 1fr; }
.ev-focus__main { min-width: 0; min-height: 0; }
.ev-focus__rail { min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.ev-focustile { pointer-events: auto; position: relative; flex: 1 1 0; min-height: 0; box-sizing: border-box; border: 1px solid rgba(255,255,255,0.22); border-radius: var(--radius-sm); background: transparent; cursor: pointer; transition: border-color 0.12s ease, box-shadow 0.12s ease; padding: 0; }
.ev-focustile:hover { border-color: rgba(255,255,255,0.55); }
.ev-focustile.is-active { border-color: var(--violet-400, #9a82ff); box-shadow: 0 0 0 2px var(--violet-400, #9a82ff) inset; z-index: 1; }

.ev-vtool:disabled { opacity: 0.4; cursor: default; }
.ev-vtool.is-on { background: rgba(54,214,198,0.22); border-color: #36d6c6; color: #cffaf3; }
.ev-vtool__icon { width: 16px; height: 16px; }
/* Clip orientation + flip: smaller squares in a row under the clip toggle (two-letter / icon labels). */
.ev-vsub { display: flex; flex-direction: row; gap: 0.25rem; }
/* 3D scene-background picker: the landscape button (ev-vtool) in the tool stack fans a labelled preset row
   to its LEFT (DOM order: sub-row before the button). Dark translucent to match the over-canvas tools. */
.ev-envgroup { display: flex; flex-direction: row; align-items: center; gap: 0.3rem; }
.ev-envsub { display: flex; flex-direction: row; gap: 0.2rem; }
.ev-envtile { pointer-events: auto; padding: 0 0.4rem; height: 1.95rem; display: inline-flex; align-items: center; border-radius: var(--radius-sm); border: 1px solid rgba(255,255,255,0.16); background: rgba(18,20,26,0.5); color: var(--fg-on-canvas); cursor: pointer; font-size: var(--text-2xs); font-weight: var(--weight-bold, 700); line-height: 1; white-space: nowrap; transition: var(--transition-colors); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
.ev-envtile:hover { background: rgba(40,44,54,0.72); border-color: rgba(255,255,255,0.38); }
.ev-envtile.is-on { background: var(--violet-500, #7c5cff); border-color: var(--violet-400, #9a82ff); color: #fff; }
.ev-vtool--mini { width: 1.55rem; height: 1.55rem; font-size: 9px; letter-spacing: 0.02em; }
.ev-vtool--mini .ev-vtool__icon { width: 13px; height: 13px; }
/* Clip-plane position slider: stacked OVER the orientation buttons (column), spanning their width. Dragging
   it glides the cut plane through the stack (off01 ∈ [-1,1], the same unit the 3D move-handle reports). */
.ev-clipcontrols { display: flex; flex-direction: column; align-items: stretch; gap: 0.3rem; }
.ev-clipslider { pointer-events: auto; -webkit-appearance: none; appearance: none; width: 100%; height: 14px; margin: 0; background: transparent; cursor: pointer; }
.ev-clipslider:focus { outline: none; }
.ev-clipslider::-webkit-slider-runnable-track { height: 5px; border-radius: 3px; background: rgba(255,255,255,0.25); }
.ev-clipslider::-moz-range-track { height: 5px; border-radius: 3px; background: rgba(255,255,255,0.25); }
.ev-clipslider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 13px; height: 13px; margin-top: -4px; border-radius: 50%; background: #36d6c6; border: 1px solid rgba(255,255,255,0.6); box-shadow: 0 0 3px rgba(0,0,0,0.65); }
.ev-clipslider::-moz-range-thumb { width: 13px; height: 13px; border-radius: 50%; background: #36d6c6; border: 1px solid rgba(255,255,255,0.6); box-shadow: 0 0 3px rgba(0,0,0,0.65); }
/* Walk-mode block tools (issue #187): a small control hint next to the walk switch (left-click adds,
   right-click removes — the two "tools" are the two mouse buttons). */
.ev-walkhint { color: var(--fg-on-canvas); font-size: var(--text-2xs); opacity: 0.8; white-space: nowrap; }
/* Centre crosshair for aiming the walk block tools — dim while navigating, bright when a tool is armed. */
.ev-crosshair { position: absolute; left: 50%; top: 50%; width: 16px; height: 16px; transform: translate(-50%, -50%); pointer-events: none; opacity: 0.5; }
.ev-crosshair.is-armed { opacity: 0.95; }
.ev-crosshair::before, .ev-crosshair::after { content: ""; position: absolute; background: #fff; box-shadow: 0 0 2px rgba(0,0,0,0.9); }
.ev-crosshair::before { left: 50%; top: 0; width: 2px; height: 100%; transform: translateX(-50%); }
.ev-crosshair::after { top: 50%; left: 0; height: 2px; width: 100%; transform: translateY(-50%); }

/* sidebar / panels */
.editor__workspace { display: grid; grid-template-columns: var(--sidebar-width) 1fr; gap: 0.5rem; flex: 1 1 auto; min-height: 0; }
.editor__sidebar { display: flex; flex-direction: column; gap: 0.5rem; min-height: 0; overflow-y: auto; overflow-x: hidden; }

.stacks { display: flex; flex-direction: column; gap: 0.4rem; padding: 0.5rem; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: var(--radius-md); font-size: var(--text-sm); }
.stacks__head { display: flex; justify-content: space-between; align-items: center; font-weight: var(--weight-semibold); }
.stacks__upload-btn { position: relative; overflow: hidden; }
.stacks__upload-btn input[type=file] { position: absolute; opacity: 0; inset: 0; width: 100%; height: 100%; cursor: pointer; }
.stacks__empty, .stacks__phase, .stacks__error { color: var(--fg-muted); font-size: var(--text-xs); margin: 0; }
.stacks__error { color: var(--danger); }
.stacks__coreg-toggle { display: flex; align-items: center; gap: 0.35rem; font-size: var(--text-xs); cursor: pointer; }
.stacks__coreg-hint { color: var(--warning-fg); font-size: var(--text-2xs); margin: 0.15rem 0 0; }
.stack { display: flex; flex-direction: column; gap: 0.25rem; padding: 0.35rem; border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-surface); cursor: pointer; }
.stack:hover { border-color: var(--border-accent); }
.stack--active { border-color: var(--border-accent); background: var(--bg-selected); box-shadow: var(--ring-selected); cursor: default; }
.stack__row { display: flex; align-items: center; gap: 0.35rem; font-size: var(--text-xs); }
.stack__row--head { font-weight: var(--weight-medium); }
.stack__row--coreg label { display: inline-flex; flex-direction: column; font-size: var(--text-2xs); color: var(--fg-secondary); }
.stack__row--coreg input { width: 4rem; font-size: var(--text-xs); padding: 0.1rem 0.25rem; }
.stack__name { flex: 1 1 auto; }
.stack__icon { width: 14px; height: 14px; flex: 0 0 auto; color: var(--fg-muted); }
.stack__eye { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; padding: 0.15rem; border: 0; background: none; color: var(--fg-secondary); cursor: pointer; border-radius: var(--radius-sm); }
.stack__eye svg { width: 14px; height: 14px; }
.stack__eye:hover { color: var(--fg-default); background: var(--bg-sunken); }
.stack__eye--off { color: var(--fg-muted); opacity: 0.6; }
.stack__del { padding: 0 0.35rem; font-size: var(--text-2xs); }
.stack__primary { padding: 0 0.35rem; font-size: var(--text-xs); color: var(--warning-fg); }

.segpanel { display: flex; flex-direction: column; gap: 0.75rem; padding: 0.5rem; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: var(--radius-md); font-size: var(--text-sm); overflow-y: auto; overflow-x: hidden; min-height: 0; }
/* Tool-independent extras (Smoothing / Advanced) — pinned to the sidebar bottom; the debug row
   (.editor__viewsettings) trails right below it. */
.segpanel--general { margin-top: auto; flex: 0 0 auto; }
.segpanel__readonly { display: flex; align-items: center; gap: 0.35rem; font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--success-fg); background: var(--success-bg); padding: 0.3rem 0.5rem; border-radius: var(--radius-sm); }
.segpanel__toolbar { display: flex; flex-direction: column; gap: 0.3rem; }
/* Tools in a fixed 5-wide grid + a 2-wide history row, so the buttons never wrap raggedly. */
.segpanel__tools { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0.3rem; }
.segpanel__history { display: grid; grid-template-columns: 1fr 1fr; gap: 0.3rem; }

/* The TOOL zone (Editing header → tools → active-tool settings) is pinned at the TOP of the panel;
   the segment LIST sits below it, separated by a hairline. Reordered via flex `order` (the markup
   keeps segments first) so the segment list scrolls independently under a fixed tool zone. */
.segpanel__readonly { order: 0; }
.segpanel__editing-head { order: 1; }
.segpanel__toolbar { order: 2; }
.segpanel__params { order: 3; }
.segpanel__segments { order: 4; padding-top: 0.7rem; border-top: 1px solid var(--border-subtle); }

.segpanel__editing-head { display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
.segpanel__editing-lead { font-size: var(--text-2xs); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--fg-faint); flex: 0 0 auto; }
.segpanel__editing-sw { width: 12px; height: 12px; border-radius: var(--radius-xs); flex: 0 0 auto; background: var(--swatch, transparent); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.12); }
.segpanel__editing-name { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.segpanel__editing-name--none { color: var(--fg-muted); font-weight: var(--weight-medium); }

/* Live volume on the active segment row (mono, right-aligned before the row actions). */
/* Active-segment shelf: a subtle indented strip under the active row (volume + rename/delete). Indent aligns
   its content under the row's NAME (past the swatch), so it reads as a detail of the item above it. */
/* Name + volume stacked in one column: volume is a compact second line under the name, so the row barely
   grows in height. Opacity slider lives in the hover/active action cluster. */
.segpanel__seg-main { display: flex; flex-direction: column; justify-content: center; flex: 1 1 auto; min-width: 0; gap: 1px; }
.segpanel__seg-main > .segpanel__seg-name { flex: 0 0 auto; line-height: 1.2; }
.segpanel__seg-main > .segpanel__rename { flex: 0 0 auto; }
.segpanel__seg-cc { flex: 0 0 auto; font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--text-2xs); line-height: 1.05; color: var(--fg-muted); white-space: nowrap; }
.segpanel__seg-op { -webkit-appearance: none; appearance: none; flex: 0 0 auto; width: 54px; height: 4px; border-radius: var(--radius-full); background: var(--bg-active); outline: none; cursor: pointer; }
.segpanel__seg-op::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--accent); border: 2px solid var(--bg-surface); cursor: pointer; }
.segpanel__seg-op::-moz-range-thumb { width: 11px; height: 11px; border-radius: 50%; background: var(--accent); border: 2px solid var(--bg-surface); cursor: pointer; }
/* Per-segment "…" actions popover (crop / rename / delete), anchored under the row's action buttons. */
.segpanel__kebab.is-open { background: var(--bg-active); color: var(--fg-primary); }
/* Fixed (viewport-anchored) so the scrollable segments panel can't clip it; positioned at the click point
   (inline left/top) and pulled up-left so its right edge sits at the cursor. */
.segpanel__segmenu { position: fixed; z-index: var(--z-dropdown, 1000); transform: translate(-100%, 8px); display: flex; flex-direction: column; min-width: 9.5rem; padding: 0.3rem; background: var(--bg-raised, var(--bg-surface)); border: 1px solid var(--border-default); border-radius: var(--radius-md); box-shadow: var(--elevation-menu, var(--shadow-md)); cursor: default; }
.segpanel__segmenu-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.5rem; border: none; background: none; color: var(--fg-primary); font: inherit; font-size: var(--text-sm); text-align: left; border-radius: var(--radius-sm); cursor: pointer; transition: var(--transition-colors); }
/* --bg-hover is ~invisible on the raised menu surface (dark theme: #1E212B vs #1C1F28); --bg-active reads. */
.segpanel__segmenu-item:hover { background: var(--bg-active); }
.segpanel__segmenu-item--danger { color: var(--danger); }
.segpanel__segmenu-item--danger:hover { background: var(--danger-bg); }
.segpanel__menu-backdrop { position: fixed; inset: 0; z-index: calc(var(--z-dropdown, 1000) - 1); }
.segpanel__params { display: flex; flex-direction: column; gap: 0.4rem; }
.segpanel__params label { display: flex; flex-direction: column; color: var(--fg-secondary); }
.segpanel__params input[type=range] { accent-color: var(--accent); }
.segpanel__check { flex-direction: row !important; align-items: center; gap: 0.35rem; }
.segpanel__tool { display: inline-flex; align-items: center; justify-content: center; width: 100%; height: 2.2rem; padding: 0; position: static; }
/* A mouse click leaves the tool button focused — without this, a DESELECTED tool keeps the purple
   focus ring and reads as still active. Keyboard focus (:focus-visible) keeps its ring. */
.segpanel__tool:focus:not(:focus-visible) { box-shadow: none; }

/* ─── Tooltips ────────────────────────────────────────────────────────────────
   One look for every editor hover hint: a dark card that fades in after a shared
   delay (--tip-delay). Two shapes share the palette so they read as one system:
   • Tool icons (.hs-tip child span) — a rich card with a bold title + optional
     description line. Anchored to the toolbar ROW (left/right:0, max-width:100%) and
     dropped BELOW it, so even a long, multi-line hint stays inside the panel — which
     clips at its edges (overflow-x:hidden) and has little room above the near-top row.
     The button is position:static so the card resolves against the row, not the icon.
   • Everything else ([data-tip] pseudo) — a compact label that replaces the sluggish,
     unstyled native title= tooltips. Anchored to whichever edge its host hugs so it
     never spills past the clipped panel edge. */
.segpanel { --tip-delay: 0.4s; }
.segpanel__tools { position: relative; }

.hs-tip {
  position: absolute; top: calc(100% + 7px);
  left: var(--tip-cx, 50%); width: max-content; max-width: 100%;
  display: flex; flex-direction: column; gap: 0.1rem; text-align: center;
  padding: 0.4rem 0.6rem; white-space: normal;   /* host button is nowrap — let long hints wrap */
  background: var(--slate-900); color: var(--slate-0);
  border: 1px solid rgba(255, 255, 255, 0.09); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  pointer-events: none; z-index: var(--z-tooltip);
  opacity: 0; transform: translate(-50%, -4px) scale(0.97); transform-origin: top center;
  transition: opacity 0.13s ease, transform 0.13s ease; transition-delay: 0s;
}
/* Short (title-only) tips sit centered directly UNDER their own icon — --tip-cx is the icon's
   centre in the 5-column tools row (col N centre ≈ (N·2−1)·10%). */
.segpanel__tools .segpanel__tool:nth-child(1) .hs-tip { --tip-cx: 10%; }
.segpanel__tools .segpanel__tool:nth-child(2) .hs-tip { --tip-cx: 30%; }
.segpanel__tools .segpanel__tool:nth-child(3) .hs-tip { --tip-cx: 50%; }
.segpanel__tools .segpanel__tool:nth-child(4) .hs-tip { --tip-cx: 70%; }
.segpanel__tools .segpanel__tool:nth-child(5) .hs-tip { --tip-cx: 90%; }
/* Wide (described) cards fill the row and centre on it, so a long multi-line hint can't clip. */
.hs-tip:has(.hs-tip__desc) { text-align: left; left: 0; right: 0; margin-inline: auto; transform: translate(0, -4px) scale(0.97); }
.hs-tip__title { font-size: var(--text-xs); font-weight: var(--weight-semibold); line-height: 1.3; }
.hs-tip__desc { font-size: var(--text-2xs); font-weight: var(--weight-regular); line-height: 1.35; color: var(--slate-300); }
.segpanel__tool:hover .hs-tip,
.segpanel__tool:focus-visible .hs-tip {
  opacity: 1; transform: translate(-50%, 0) scale(1); transition-delay: var(--tip-delay, 0.4s);
}
.segpanel__tool:hover .hs-tip:has(.hs-tip__desc),
.segpanel__tool:focus-visible .hs-tip:has(.hs-tip__desc) { transform: translate(0, 0) scale(1); }
/* A JUST-CLICKED tool suppresses its tip until the pointer leaves it (body class set by the index.html
   click handler — on <body>, not the button, because Blazor rewrites the button's class attribute when the
   tool activates): the card drops exactly where the tool's settings appear, so a still cursor left it
   covering the controls the click revealed. Keyed to :hover so only the still-hovered button is muted. */
body.hs-tipsoff .segpanel__tool:hover .hs-tip { display: none; }
/* The active tool DOES show its tip on a genuine re-hover — the hs-tipsoff mute above already covers the
   only bad case (the tip dropping onto the just-revealed settings while the cursor holds still on the button
   right after activating). Once the pointer leaves and comes back, the hint is welcome. */

/* [data-tip] tooltips are rendered by the cursor-anchored JS driver (.hs-cursortip, see index.html):
   one shared node that spawns at the pointer and clamps to the viewport so it never clips. The old CSS
   ::after pseudo (and every positional override of it below) is suppressed — [data-tip] stays as the
   text source only. */
[data-tip] { position: relative; }
[data-tip]::after { content: none !important; }

.hs-cursortip {
  position: fixed; left: 0; top: 0; z-index: var(--z-tooltip, 3000); pointer-events: none;
  max-width: min(20rem, calc(100vw - 16px)); white-space: normal; text-align: left;
  padding: 0.3rem 0.5rem; font-size: var(--text-xs); font-weight: var(--weight-medium); line-height: 1.35;
  background: var(--slate-900); color: var(--slate-0);
  border: 1px solid rgba(255, 255, 255, 0.09); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  opacity: 0; transition: opacity 0.12s ease;
}
.hs-cursortip.is-shown { opacity: 1; }
/* Seg-row actions: the tip sits centered directly UNDER the hovered icon (default anchor).
   Cap the width so a long hint wraps instead of spilling past the panel's clipped right edge. */
.segpanel__seg-actions [data-tip]::after { max-width: 10rem; }
/* The swatch hugs the row's LEFT edge — left-anchor so its tip grows right, not off-panel. */
.segpanel__swatch-wrap[data-tip]::after { left: 0; right: auto; transform: translateX(0) translateY(4px); }
.segpanel__swatch-wrap[data-tip]:hover::after { transform: translateX(0) translateY(0); }
/* Multi-button rows: an edge-column button's centered tip would clip — anchor the tip to
   the full-width ROW container and cap it to the row, so it centers and never clips. */
.segpanel__ai-bar, .segpanel__ai-actions, .segpanel__wlpresets,
.segpanel__morph-btns, .segpanel__vessel-btns,
.ctpreset-picker__grid { position: relative; }
.segpanel__ai-bar [data-tip], .segpanel__ai-actions [data-tip], .segpanel__wlpresets [data-tip],
.segpanel__morph-btns [data-tip], .segpanel__vessel-btns [data-tip],
.ctpreset-picker__grid [data-tip] { position: static; }
.segpanel__ai-bar [data-tip]::after, .segpanel__ai-actions [data-tip]::after, .segpanel__wlpresets [data-tip]::after,
.segpanel__morph-btns [data-tip]::after, .segpanel__vessel-btns [data-tip]::after,
.ctpreset-picker__grid [data-tip]::after {
  left: 0; right: 0; margin-inline: auto; max-width: 100%;
  transform: translateX(0) translateY(4px);
}
.segpanel__ai-bar [data-tip]:hover::after, .segpanel__ai-actions [data-tip]:hover::after, .segpanel__wlpresets [data-tip]:hover::after,
.segpanel__morph-btns [data-tip]:hover::after, .segpanel__vessel-btns [data-tip]:hover::after,
.ctpreset-picker__grid [data-tip]:hover::after { transform: translateX(0) translateY(0); }

/* ─ Viewport overlay controls + top-bar stack chips ─────────────────────────────
   Same styled tip + shared delay (via the --tip-delay fallback), positioned for their
   context. These live OUTSIDE .segpanel, on the dark canvas / top bar. */
/* Top-right tool stack + per-cell fullscreen: the tip sits to the LEFT of the button,
   vertically centred. Below/beside would land it behind the next button — each control
   has backdrop-filter (its own stacking context), so a later sibling paints over an
   earlier one's tooltip. To the left it clears the whole button column, on-canvas. */
.ev-vstack [data-tip]::after, .ev-fs[data-tip]::after {
  bottom: auto; top: 50%; left: auto; right: calc(100% + 8px);
  transform: translateY(-50%) translateX(4px); transform-origin: center right;
}
.ev-vstack [data-tip]:hover::after, .ev-vstack [data-tip]:focus-visible::after,
.ev-fs[data-tip]:hover::after, .ev-fs[data-tip]:focus-visible::after { transform: translateY(-50%) translateX(0); }
/* Top bar sits at the screen top — drop stack-chip tips BELOW, centered on the chip. */
.hs-stackbar [data-tip]::after {
  bottom: auto; top: calc(100% + 6px);
  transform: translateX(-50%) translateY(-4px); transform-origin: top center;
}
.hs-stackbar [data-tip]:hover::after, .hs-stackbar [data-tip]:focus-visible::after { transform: translateX(-50%) translateY(0); }

/* The appearance menu lives inside .hs-stackbar but is its own scrolling panel, so the "drop tips BELOW"
   rule above would push its tooltips onto the clipped bottom edge of the menu. Put them ABOVE instead. */
.hs-stackbar .hs-appmenu [data-tip]::after {
  top: auto; bottom: calc(100% + 6px);
  transform: translateX(-50%) translateY(4px); transform-origin: bottom center;
}
.hs-stackbar .hs-appmenu [data-tip]:hover::after,
.hs-stackbar .hs-appmenu [data-tip]:focus-visible::after { transform: translateX(-50%) translateY(0); }
/* Colormap cards: anchor the tip to the GRID (spans its width) so edge-card tips can't clip on the
   x-overflow-hidden panel, sitting just above the grid. */
.hs-stackbar .hs-appmenu .ctpreset-picker__grid [data-tip]::after {
  left: 0; right: 0; margin-inline: auto; transform: translateY(4px);
}
.hs-stackbar .hs-appmenu .ctpreset-picker__grid [data-tip]:hover::after,
.hs-stackbar .hs-appmenu .ctpreset-picker__grid [data-tip]:focus-visible::after { transform: translateY(0); }

.segpanel__icon { width: 18px; height: 18px; }
.segpanel__hint { color: var(--fg-muted); font-size: var(--text-xs); }
/* Contrast tool settings: W/L readout + preset shelf (window/level is set by dragging the image). */
.segpanel__wl { font-size: var(--text-xs); color: var(--fg-secondary); white-space: nowrap; font-variant-numeric: tabular-nums; }
.segpanel__wl b { color: var(--fg-primary); font-weight: var(--weight-semibold); }
.segpanel__wlpresets { display: flex; flex-wrap: wrap; gap: 0.25rem; }
/* Toggle switch as a bordered card row — title + sub-label so an option reads as a real
   feature of the tool, not a bare afterthought checkbox. */
/* Raised against the panel (which is --bg-surface) with a strong border so the row reads as a
   tappable control in both themes — a bare --bg-surface fill was invisible on the same-colour panel. */
.segpanel__switch { display: flex; align-items: center; gap: 0.6rem; width: 100%; text-align: left; padding: 0.5rem 0.6rem; background: var(--bg-active); border: 1px solid var(--border-strong); border-radius: var(--radius-md); font-family: inherit; color: var(--fg-secondary); cursor: pointer; transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease; }
.segpanel__switch:hover:not(:disabled) { border-color: var(--accent); }
.segpanel__switch.is-on { border-color: var(--border-accent); background: var(--accent-subtle); color: var(--fg-primary); }
.segpanel__switch:disabled { opacity: 0.55; cursor: default; }
.segpanel__switch:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-subtle-hover); border-color: var(--border-accent); }
.segpanel__switch-track { position: relative; width: 34px; height: 18px; border-radius: var(--radius-full); background: var(--slate-300); transition: background 0.15s ease; flex: 0 0 auto; }
.segpanel__switch.is-on .segpanel__switch-track { background: var(--accent); }
.segpanel__switch-thumb { position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-sm); transition: left 0.15s ease; }
.segpanel__switch.is-on .segpanel__switch-thumb { left: 18px; }
.segpanel__switch-text { display: flex; flex-direction: column; gap: 0.05rem; min-width: 0; }
.segpanel__switch-title { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary); }
.segpanel__switch-sub { font-size: var(--text-xs); color: var(--fg-secondary); line-height: 1.35; }

/* Island inspector (Eraser tool): disconnected-piece list — hover a row to outline that piece in
   2D/3D, trash to delete it. Rows echo the segment-list look at a smaller scale. */
.islands { display: flex; flex-direction: column; gap: 0.35rem; }
.islands__head { display: flex; align-items: center; gap: 0.4rem; }
.islands__title { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary); }
.islands__badge { display: inline-flex; align-items: center; justify-content: center; min-width: 1.15rem; height: 1.15rem; padding: 0 0.3rem; border-radius: var(--radius-full); background: var(--accent-subtle); color: var(--accent); font-size: var(--text-xs); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.islands__list { display: flex; flex-direction: column; gap: 2px; max-height: 240px; overflow-y: auto; }
.islands__row { display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0.4rem; border: 1px solid transparent; border-radius: var(--radius-md); cursor: default; transition: background 0.12s ease, border-color 0.12s ease; }
.islands__row:hover { background: var(--bg-hover); border-color: var(--border-default); }
.islands__name { flex: 1 1 auto; min-width: 0; font-size: var(--text-sm); color: var(--fg-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.islands__cc { flex: 0 0 auto; font-size: var(--text-xs); color: var(--fg-secondary); font-variant-numeric: tabular-nums; }
.islands__del { flex: 0 0 auto; opacity: 0; }
.islands__row:hover .islands__del { opacity: 1; }
.islands__del:focus-visible { opacity: 1; }
.islands__all { align-self: stretch; }
.islands__thr { margin-top: 0.25rem; }
/* 3D island-hover board: floats by the cursor over the (always-dark) viewport; JS positions it via
   transform. Fixed-position + pointer-events:none so it can never intercept the orbit/tap gestures. */
.ev-islandtip { position: fixed; left: 0; top: 0; z-index: 1000; display: none; pointer-events: none; padding: 0.28rem 0.55rem; background: rgba(10, 14, 20, 0.92); border: 1px solid rgba(255, 255, 255, 0.14); border-radius: var(--radius-md); color: #eef2f7; font-size: var(--text-xs); font-weight: var(--weight-semibold); white-space: nowrap; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4); }

/* History (Undo/Redo): full-width labelled buttons — icon + text, paired in the 2-col row. */
.segpanel__histbtn { display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem; width: 100%; height: 2.4rem; padding: 0 0.5rem; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: var(--radius-md); font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary); cursor: pointer; transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease; }
.segpanel__histbtn:hover:not(:disabled) { border-color: var(--border-strong); background: var(--bg-hover); }
.segpanel__histbtn:active:not(:disabled) { background: var(--bg-active); }
.segpanel__histbtn:disabled { color: var(--fg-disabled); cursor: default; }
.segpanel__histbtn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-subtle-hover); border-color: var(--border-accent); }
.segpanel__histicon { width: 16px; height: 16px; flex: 0 0 auto; }

/* Slider: header row (label · value) above a styled range track. */
.hs-slider { display: flex; flex-direction: column; gap: 0.4rem; }
.hs-slider__head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; }
.hs-slider__label { font-size: var(--text-sm); color: var(--fg-secondary); }
.hs-slider__val { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary); font-variant-numeric: tabular-nums; }
.hs-slider__unit { margin-left: 0.25rem; font-weight: var(--weight-medium); color: var(--fg-muted); }

/* hs-range — design-system range input. Filled left portion via --range-fill (0–100%),
   chunky haloed thumb. Cross-browser via the -webkit/-moz pseudo-elements. */
.hs-range { -webkit-appearance: none; appearance: none; width: 100%; height: 18px; background: transparent; cursor: pointer; }
.hs-range:disabled { cursor: default; opacity: 0.55; }
.hs-range::-webkit-slider-runnable-track { height: 6px; border-radius: var(--radius-full); background: linear-gradient(to right, var(--accent) 0 var(--range-fill, 0%), var(--track-empty, var(--border-strong)) var(--range-fill, 0%) 100%); }
.hs-range::-moz-range-track { height: 6px; border-radius: var(--radius-full); background: var(--track-empty, var(--border-strong)); }
.hs-range::-moz-range-progress { height: 6px; border-radius: var(--radius-full); background: var(--accent); }
.hs-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; margin-top: -5px; border-radius: 50%; background: var(--accent); border: 3px solid var(--bg-surface); box-shadow: 0 0 0 1px var(--border-default), var(--shadow-sm); transition: transform 0.1s ease; }
.hs-range::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--accent); border: 3px solid var(--bg-surface); box-shadow: 0 0 0 1px var(--border-default), var(--shadow-sm); }
.hs-range:hover:not(:disabled)::-webkit-slider-thumb { transform: scale(1.12); }
.hs-range:active:not(:disabled)::-webkit-slider-thumb { transform: scale(1.12); }
.hs-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 1px var(--border-accent), 0 0 0 4px var(--accent-subtle-hover); }
.hs-range:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 1px var(--border-accent), 0 0 0 4px var(--accent-subtle-hover); }

.segpanel__section-head {
    font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--fg-primary);
    margin-top: 0.15rem;
}

/* CT intensity presets — inline in Image Appearance tool settings */
.ctpreset-section__label {
    font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--fg-muted);
    text-transform: uppercase; letter-spacing: 0.04em; margin-top: 0.5rem;
}
.ctpreset-picker__loading { font-size: var(--text-sm); color: var(--fg-secondary); padding: 0.15rem 0 0.35rem; }
.ctpreset-picker__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.4rem; }
.ctpreset-picker__card {
    display: flex; flex-direction: column; gap: 0.3rem; padding: 0.3rem;
    background: var(--bg-subtle); border: 2px solid transparent; border-radius: var(--radius-sm);
    cursor: pointer; text-align: left; font-family: inherit;
}
.ctpreset-picker__card:hover { background: var(--bg-hover); border-color: var(--border-subtle); }
.ctpreset-picker__card.is-active { border-color: var(--accent); background: var(--bg-selected); }
.ctpreset-picker__thumb {
    width: 100%; aspect-ratio: 1; border-radius: var(--radius-xs);
    background: var(--bg-canvas); display: block;
}
.ctpreset-picker__thumb--graph { position: relative; overflow: hidden; min-height: 2.5rem; }
.ctpreset-picker__img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: var(--radius-xs); }
.ctpreset-picker__svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ctpreset-picker__fill { fill: rgba(15, 15, 15, 0.72); }
.ctpreset-picker__curve { fill: none; stroke: var(--accent); stroke-width: 3; vector-effect: non-scaling-stroke; }
.ctpreset-picker__label { font-size: 0.68rem; line-height: 1.2; color: var(--fg-secondary); }

.ctpreset-graph {
    display: flex; flex-direction: column; gap: 0.2rem; margin-top: 0.5rem;
    padding: 0.4rem; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
    background: var(--bg-subtle);
}
.ctpreset-graph__header {
    display: flex; justify-content: space-between; align-items: center; gap: 0.25rem;
    font-size: var(--text-2xs); color: var(--fg-muted);
}
.ctpreset-graph__title {
    font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--fg-secondary); text-align: center; flex: 1 1 auto;
}
.ctpreset-graph__hud { font-family: var(--font-mono); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.ctpreset-graph__body {
    height: 2.75rem; border-radius: var(--radius-xs); overflow: hidden; position: relative;
    border: 1px solid var(--border-subtle);
}
/* CT: the window box is draggable (move = level, edges = width) */
.ctpreset-graph__body--drag { cursor: ew-resize; touch-action: none; }
.ctpreset-graph__svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ctpreset-graph__window {
    fill: rgba(255, 255, 255, 0.1);
    stroke: var(--accent);
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
}
.ctpreset-graph__fill { fill: rgba(15, 15, 15, 0.72); }
.ctpreset-graph__curve { fill: none; stroke: var(--accent); stroke-width: 2.5; vector-effect: non-scaling-stroke; }
.ctpreset-graph__caption { font-size: var(--text-xs); color: var(--fg-secondary); text-align: center; }

/* Threshold-brush range picker: an intensity histogram with a draggable [low,high] band. */
.thr-hist { display: flex; flex-direction: column; gap: 0.2rem; margin-top: 0.4rem; }
.thr-hist__header { display: flex; justify-content: space-between; align-items: center; gap: 0.25rem; font-size: var(--text-2xs); color: var(--fg-muted); }
.thr-hist__title { font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: 0.04em; color: var(--fg-secondary); text-align: center; flex: 1 1 auto; }
.thr-hist__hud { font-family: var(--font-mono); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.thr-hist__body {
    position: relative; height: 3.25rem; overflow: hidden; border-radius: var(--radius-xs);
    border: 1px solid var(--border-subtle); background: var(--bg-subtle);
    cursor: ew-resize; touch-action: none; user-select: none;
}
.thr-hist__body--ro { cursor: default; }
.thr-hist__svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.thr-hist__fill { fill: color-mix(in srgb, var(--fg-secondary) 48%, transparent); }
.thr-hist__band { fill: color-mix(in srgb, var(--accent) 24%, transparent); stroke: none; }
.thr-hist__handle { stroke: var(--accent); stroke-width: 2; vector-effect: non-scaling-stroke; }
.thr-hist__loading { position: absolute; inset: 0; display: grid; place-items: center; color: var(--fg-muted); font-size: var(--text-xs); }
.thr-hist__caption { font-size: var(--text-2xs); color: var(--fg-muted); text-align: center; }
.thr-hist__fine { display: block; font-size: var(--text-xs); }

.segpanel__seg-head { display: flex; justify-content: space-between; align-items: center; font-weight: var(--weight-semibold); }
.segpanel__ai-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; margin: 0.25rem 0 0.4rem; }
.segpanel__ai-view { display: inline-flex; margin-left: auto; border: 1px solid var(--border-default); border-radius: var(--radius-sm); overflow: hidden; }
.segpanel__ai-view-btn { padding: 0.1rem 0.5rem; font-size: var(--text-xs); background: var(--bg-surface); color: var(--fg-secondary); border: none; border-left: 1px solid var(--border-default); cursor: pointer; }
.segpanel__ai-view-btn:first-child { border-left: none; }
.segpanel__ai-view-btn.is-on { background: var(--accent-subtle); color: var(--accent-fg); }
.segpanel__spinner { display: inline-block; width: 12px; height: 12px; border: 2px solid var(--border-default); border-top-color: var(--accent); border-radius: 50%; animation: segpanel-spin 0.7s linear infinite; }
@keyframes segpanel-spin { to { transform: rotate(360deg); } }
.segpanel__ai-legend { display: flex; flex-wrap: wrap; gap: 0.6rem; font-size: var(--text-xs); color: var(--fg-secondary); margin: 0 0 0.4rem; }
.segpanel__ai-legend span { display: inline-flex; align-items: center; gap: 0.25rem; }
.segpanel__ai-legend i { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.segpanel__ai-tag { font-size: var(--text-xs); color: var(--fg-faint); padding: 0 0.15rem; }
.segpanel__ai-tag--err { color: var(--danger-fg, #ef4444); font-weight: var(--weight-bold); }
/* min-height reserves room for the hover/active action buttons (1.7rem + 0.6rem padding) so the row
   doesn't grow — and push its siblings down — when they appear. */
.segpanel__seg { position: relative; display: flex; align-items: center; gap: 0.45rem; padding: 0.3rem 0.35rem 0.3rem var(--seg-indent-0, 0.35rem); border-radius: var(--radius-sm); cursor: pointer; transition: var(--transition-colors); min-height: 2.3rem; }
.segpanel__seg:hover { background: var(--bg-hover); }
.segpanel__seg.is-active { background: var(--bg-selected); box-shadow: var(--ring-selected); }
/* Dim only the colour + name/volume for a hidden segment — NOT the whole row. A row-level opacity would
   also grey the ⋯ popover (a child) and, worse, create a stacking context that traps the popover below the
   click-backdrop so its items stop working. */
.segpanel__seg.is-hidden .segpanel__swatch-wrap,
.segpanel__seg.is-hidden .segpanel__seg-main { opacity: 0.55; }
.segpanel__swatch { width: 14px; height: 14px; border-radius: var(--radius-xs); display: block; background: var(--swatch, transparent); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.12); }

/* Swatch button: shows the current colour and opens the structure/colour editor modal. */
.segpanel__swatch-wrap { display: inline-flex; flex: 0 0 auto; cursor: pointer; line-height: 0; padding: 0; border: none; background: none; border-radius: var(--radius-xs); }
.segpanel__swatch-wrap:hover .segpanel__swatch { box-shadow: inset 0 0 0 1px rgba(0,0,0,0.12), 0 0 0 2px var(--border-accent); }

.segpanel__seg-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.segpanel__seg-name--muted { color: var(--fg-muted); }
.segpanel__rename { flex: 1 1 auto; min-width: 0; font-size: var(--text-sm); padding: 0.1rem 0.3rem; border: 1px solid var(--border-accent); border-radius: var(--radius-xs); background: var(--bg-surface); color: var(--fg-primary); }
.segpanel__rename:focus { outline: none; box-shadow: var(--ring-selected); }

/* Row actions: removed from layout (not just faded) until the row is hovered/active, so the name fills
   the whole row for long, unselected segments instead of being truncated to leave room for hidden buttons. */
.segpanel__seg-actions { display: none; align-items: center; gap: 0.1rem; flex: 0 0 auto; }
.segpanel__seg:hover .segpanel__seg-actions,
.segpanel__seg.is-active .segpanel__seg-actions,
.segpanel__seg.is-menuopen .segpanel__seg-actions { display: flex; }
/* Keep the row looking hovered while its ⋯ menu is open (the fixed menu isn't a child, so moving onto it
   drops :hover and the actions would otherwise vanish). */
.segpanel__seg.is-menuopen:not(.is-active) { background: var(--bg-hover); }
.segpanel__act { display: inline-flex; align-items: center; justify-content: center; width: 1.7rem; height: 1.7rem; padding: 0; border: none; background: none; color: var(--fg-muted); border-radius: var(--radius-xs); cursor: pointer; transition: var(--transition-colors); }
.segpanel__act:hover { background: var(--bg-hover); color: var(--fg-primary); }
.segpanel__act--danger:hover { background: var(--danger-bg); color: var(--danger); }
.segpanel__act-icon { width: 15px; height: 15px; }
.segpanel__confirm { font-size: var(--text-2xs); color: var(--danger-fg); margin-right: 0.15rem; }

/* Structure/colour picker modal (Add segment + edit colour/name) */
.segpick { display: flex; flex-direction: column; gap: 0.75rem; }
.segpick__custom { display: flex; gap: 0.75rem; align-items: flex-end; }
.segpick__field { display: flex; flex-direction: column; gap: 0.25rem; font-size: var(--text-xs); color: var(--fg-secondary); }
.segpick__field--name { flex: 1 1 auto; }
.segpick__name-input { font-size: var(--text-sm); padding: 0.35rem 0.5rem; border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-surface); color: var(--fg-primary); }
.segpick__name-input:focus { outline: none; border-color: var(--border-accent); box-shadow: var(--ring-selected); }
.segpick__color-wrap { position: relative; display: inline-flex; width: 2.4rem; height: 2.1rem; }
.segpick__color-wrap .segpanel__swatch, .segpick__color-wrap .segpick__swatch { width: 100%; height: 100%; border-radius: var(--radius-sm); }
.segpick__color { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; border: none; padding: 0; cursor: pointer; }
.segpick__swatch { display: block; border-radius: var(--radius-xs); background: var(--swatch, transparent); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.12); width: 14px; height: 14px; flex: 0 0 auto; }
.segpick__divider { display: flex; align-items: center; text-align: center; color: var(--fg-muted); font-size: var(--text-xs); }
.segpick__divider::before, .segpick__divider::after { content: ""; flex: 1; border-top: 1px solid var(--border-subtle); }
.segpick__divider span { padding: 0 0.6rem; }
.segpick__search { font-size: var(--text-sm); padding: 0.4rem 0.6rem; border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-surface); color: var(--fg-primary); }
.segpick__search:focus { outline: none; border-color: var(--border-accent); box-shadow: var(--ring-selected); }
.segpick__list { display: flex; flex-direction: column; gap: 0.1rem; max-height: 18rem; overflow-y: auto; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: 0.35rem; }
.segpick__group-label { font-size: var(--text-2xs); font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: 0.03em; color: var(--fg-muted); padding: 0.4rem 0.35rem 0.15rem; }
.segpick__item { display: flex; align-items: center; gap: 0.5rem; width: 100%; text-align: left; padding: 0.35rem 0.4rem; border: none; background: none; border-radius: var(--radius-xs); cursor: pointer; color: var(--fg-primary); font-size: var(--text-sm); transition: var(--transition-colors); }
.segpick__item:hover { background: var(--bg-hover); }
.segpick__item.is-selected { background: var(--bg-selected); box-shadow: var(--ring-selected); }
.segpick__item-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Member count on an anatomical group row ("Ribs 24") — it stands in for that many structures. */
.segpick__item-count { flex: none; font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--fg-muted); background: var(--bg-surface); border-radius: 999px; padding: 0.05rem 0.35rem; }

/* Grouped segment ("Ribs"): the disclosure arrow on the group row + its sub-structure rows.
   A sub-structure is not a segment — it is one member of the group's single mask — so its row is
   indented, lighter, and carries only what applies to a member: colour, name, volume, visibility. */
.segpanel__disclose { flex: none; width: 1rem; padding: 0; border: none; background: none; cursor: pointer; color: var(--fg-muted); font-size: 0.7rem; line-height: 1; transition: transform var(--duration-fast) ease, color var(--duration-fast) ease; }
.segpanel__disclose:hover { color: var(--fg-primary); }
.segpanel__disclose.is-open { transform: rotate(90deg); }
.segpanel__disclose--none { cursor: default; }
/* Nesting: a top-level row (plain segment, unified group, composite heading) starts at --seg-indent-0 and
   opens with a 1rem disclosure column; every nested row (a composite MEMBER or a unified PART) starts at
   --seg-indent-1 and has no disclosure column. Both nested kinds share the one value so a liver's parts and
   a rib cage's members line up with each other. */
/* indent-1 clears the heading's disclosure column + swatch, so a nested row's dot sits visibly INSIDE
   its parent's rather than level with it. */
:root { --seg-indent-0: 0.35rem; --seg-indent-1: 2.6rem; }
.segpanel__ghead { display: flex; align-items: center; gap: 0.4rem; padding: 0.2rem 0.35rem 0.2rem var(--seg-indent-0); border-radius: var(--radius-xs); cursor: default; }
.segpanel__ghead:hover { background: var(--bg-hover); }
.segpanel__ghead .segpanel__seg-actions { opacity: 0; transition: var(--transition-opacity); }
.segpanel__ghead:hover .segpanel__seg-actions { opacity: 1; }
.segpanel__seg--member { padding-left: var(--seg-indent-1); }
.segpanel__sub { display: flex; align-items: center; gap: 0.4rem; padding: 0.15rem 0.35rem 0.15rem var(--seg-indent-1); border-radius: var(--radius-xs); cursor: pointer; font-size: var(--text-xs); color: var(--fg-secondary); }
.segpanel__sub:hover { background: var(--bg-hover); }
.segpanel__sub.is-active { background: var(--bg-selected); color: var(--fg-primary); }
.segpanel__sub.is-hidden { opacity: 0.45; }
.segpanel__sub-swatch { flex: none; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--swatch); }
.segpanel__sub-main { display: flex; align-items: baseline; gap: 0.4rem; min-width: 0; flex: 1; }
.segpanel__sub-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.segpanel__sub-cc { flex: none; font-size: var(--text-2xs); color: var(--fg-muted); }
.segpanel__sub-actions { flex: none; display: flex; align-items: center; opacity: 0; transition: var(--transition-opacity); }
.segpanel__sub:hover .segpanel__sub-actions,
.segpanel__sub.is-hidden .segpanel__sub-actions { opacity: 1; }

/* Multi-add batch chips */
.segpick__chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.segpick__chip { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.2rem 0.4rem 0.2rem 0.35rem; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 999px; font-size: var(--text-sm); color: var(--fg-primary); }
.segpick__chip-name { max-width: 11rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.segpick__chip-ai { font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--accent-fg, #6cf); letter-spacing: 0.04em; }
.segpick__chip-x { border: none; background: none; color: var(--fg-muted); cursor: pointer; font-size: var(--text-xs); line-height: 1; padding: 0 0.1rem; }
.segpick__chip-x:hover { color: var(--danger-fg); }
.segpick__addmanual { align-self: flex-start; font-size: var(--text-sm); color: var(--fg-primary); background: var(--bg-surface); border: 1px dashed var(--border-default); border-radius: var(--radius-sm); padding: 0.35rem 0.55rem; cursor: pointer; }
.segpick__addmanual:hover { background: var(--bg-hover); border-color: var(--border-accent); }
.segpick__item-check { margin-left: auto; color: var(--accent-fg, #6cf); font-weight: var(--weight-semibold); }

/* "Use AI" toggle */
.segpick__ai { display: flex; align-items: center; gap: 0.45rem; font-size: var(--text-sm); color: var(--fg-primary); cursor: pointer; }
.segpick__ai.is-disabled { color: var(--fg-muted); cursor: not-allowed; }
.segpick__ai-hint { font-size: var(--text-2xs); color: var(--fg-muted); }
/* Auto-seg quality tier picker, tucked under the "Use AI" toggle — indented so it reads as a sub-option. */
.segpick__ai-tier { display: flex; flex-direction: column; gap: 0.15rem; margin: 0.1rem 0 0.2rem 1.65rem; }

/* Per-segment AI state in the segment list row */
.segpanel__ai-spin { flex: 0 0 auto; width: 13px; height: 13px; margin-left: 0.35rem; border: 2px solid var(--border-default); border-top-color: var(--accent-fg, #6cf); border-radius: 50%; animation: hs-ai-spin 0.7s linear infinite; }
@keyframes hs-ai-spin { to { transform: rotate(360deg); } }
/* Auto-seg row status: spinner + queued/elapsed label (Queued… / Running m:ss). */
.segpanel__ai-run { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 0.3rem; margin-left: 0.35rem; }
.segpanel__ai-run .segpanel__ai-spin { margin-left: 0; }
.segpanel__ai-run-label { font-size: var(--text-2xs); color: var(--fg-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.segpanel__ai-failed { flex: 0 0 auto; margin-left: 0.35rem; font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--danger-fg); background: none; border: 1px solid var(--danger-fg); border-radius: var(--radius-xs); padding: 0.05rem 0.3rem; cursor: pointer; }
/* Device the finished AI fill's inference ran on (GPU/CPU provenance chip). */
.segpanel__ai-device { flex: 0 0 auto; margin-left: 0.35rem; font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--fg-muted); border: 1px solid var(--border-default); border-radius: var(--radius-xs); padding: 0.05rem 0.3rem; white-space: nowrap; cursor: default; }
/* AI-brush (interactive) panel: point counts, status line, action rows. */
.segpanel__ai-counts { display: flex; gap: 0.75rem; font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.segpanel__ai-count--inc { color: #27d957; }
.segpanel__ai-count--exc { color: #ff5b5b; }
.segpanel__ai-status { display: flex; align-items: center; gap: 0.4rem; font-size: var(--text-xs); color: var(--fg-muted); min-height: 1.3em; }
.segpanel__ai-status-sub { color: var(--fg-muted); opacity: 0.75; }
.segpanel__ai-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; background: var(--border-default); }
.segpanel__ai-dot--ok { background: #27d957; }
.segpanel__ai-dot--err { background: var(--danger-fg); }
.segpanel__ai-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.segpanel__ai-actions .btn { flex: 1 1 auto; }
/* Smart-segment prompt: an obvious "AI box" — sparkle icon + accent ring, input borderless inside the
   wrapper so the whole pill reads as one control. Typeahead of accepted structures beneath it. */
.segpanel__smart { display: flex; align-items: center; gap: 0.45rem; padding: 0.5rem 0.55rem; border: 1.5px solid var(--accent-fg, #6e56cf); border-radius: var(--radius-md); background: var(--bg-default); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-fg, #6e56cf) 10%, transparent); transition: box-shadow 0.15s ease; }
.segpanel__smart:focus-within { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-fg, #6e56cf) 28%, transparent); }
.segpanel__smart-icon { flex: 0 0 auto; color: var(--accent-fg, #6e56cf); }
.segpanel__smart .segpanel__smart-input { flex: 1 1 auto; min-width: 0; border: none; outline: none; background: transparent; box-shadow: none; padding: 0; font-size: var(--text-sm); color: var(--fg-default); }
.segpanel__smart .segpanel__smart-input::placeholder { color: var(--fg-muted); }
.segpanel__smart-send { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border: none; border-radius: var(--radius-sm); background: var(--accent-fg, #6e56cf); color: #fff; cursor: pointer; }
.segpanel__smart-send:disabled { opacity: 0.45; cursor: default; }
/* Refine shortcut chips (shown once the active segment is a finished AI segment): mouse icon with the
   relevant button filled + the action name. Informational — the actual gesture is on the viewport. */
.segpanel__refinehint { display: flex; gap: 0.4rem; position: relative; }
.segpanel__refinebtn { flex: 1 1 0; display: flex; align-items: center; justify-content: center; padding: 0.5rem 0.5rem; border: 1px solid var(--border-default); border-radius: var(--radius-sm); font-size: var(--text-sm); font-family: inherit; font-weight: var(--weight-semibold); color: var(--fg-default); background: var(--bg-muted, rgba(128, 128, 128, 0.08)); cursor: pointer; appearance: none; transition: border-color .12s, background .12s, box-shadow .12s, color .12s; }
.segpanel__refinebtn:hover:not(:disabled) { border-color: var(--accent-fg, #6e56cf); }
.segpanel__refinebtn:disabled { opacity: .5; cursor: default; }
.segpanel__refinebtn--on { border-color: var(--accent-fg, #6e56cf); color: var(--accent-fg, #6e56cf); background: color-mix(in srgb, var(--accent-fg, #6e56cf) 14%, transparent); box-shadow: inset 0 0 0 1px var(--accent-fg, #6e56cf); }

/* Rich hover tooltip: a feature line, then a "Shortcut" header with a Shift keycap + mouse-button icon.
   Anchored to the row (not the half-width button) + capped to the row so it centres and never clips. */
.segpanel__refinetip {
  position: absolute; top: calc(100% + 7px); left: 0; right: 0; margin-inline: auto;
  width: max-content; max-width: 100%;
  display: flex; flex-direction: column; gap: 0.4rem; text-align: left;
  padding: 0.55rem 0.65rem; white-space: normal;
  background: var(--slate-900); color: var(--slate-0);
  border: 1px solid rgba(255, 255, 255, 0.09); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg); pointer-events: none; z-index: var(--z-tooltip, 3000);
  opacity: 0; transform: translateY(-4px) scale(0.98); transform-origin: top center;
  transition: opacity .13s ease, transform .13s ease;
}
.segpanel__refinebtn:hover:not(:disabled) .segpanel__refinetip,
.segpanel__refinebtn:focus-visible .segpanel__refinetip { opacity: 1; transform: translateY(0) scale(1); transition-delay: .35s; }
.segpanel__refinetip-desc { font-size: var(--text-xs); font-weight: var(--weight-medium); line-height: 1.4; color: var(--slate-0); }
.segpanel__refinetip-sc { display: flex; flex-direction: column; gap: 0.3rem; padding-top: 0.4rem; border-top: 1px solid rgba(255, 255, 255, 0.11); }
.segpanel__refinetip-hd { font-size: var(--text-2xs); font-weight: var(--weight-semibold); letter-spacing: 0.07em; text-transform: uppercase; color: var(--slate-400); }
.segpanel__refinetip-keys { display: flex; align-items: center; gap: 0.35rem; color: var(--slate-0); }
.segpanel__refinetip-lbl { font-size: var(--text-2xs); color: var(--slate-300); }
.segpanel__plus { font-size: var(--text-2xs); color: var(--slate-400); }
.segpanel__key { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.14rem 0.4rem; border-radius: var(--radius-sm); background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.18); font-size: var(--text-2xs); font-weight: var(--weight-semibold); font-family: inherit; line-height: 1.35; }
.segpanel__key svg { width: 11px; height: 11px; fill: currentColor; }
.segpanel__mouseicon { width: 15px; height: 15px; flex: 0 0 auto; color: var(--slate-0); }
.segpanel__mouseicon .segpanel__mouse-btn { fill: currentColor; }
.segpanel__suggest { display: flex; flex-direction: column; gap: 1px; border: 1px solid var(--border-default); border-radius: var(--radius-sm); overflow: hidden; }
.segpanel__suggest-item { display: flex; align-items: center; gap: 0.45rem; width: 100%; padding: 0.3rem 0.5rem; background: none; border: none; text-align: left; font-size: var(--text-xs); color: var(--fg-default); cursor: pointer; }
.segpanel__suggest-item:hover { background: var(--bg-muted, rgba(128, 128, 128, 0.12)); }
.segpanel__suggest-swatch { flex: 0 0 auto; width: 10px; height: 10px; border-radius: 3px; background: var(--swatch); }
.segpanel__suggest-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.segpanel__suggest-group { flex: 0 0 auto; font-size: var(--text-2xs); color: var(--fg-muted); }
/* AI-filling row: the delete button is the ONLY action (slider/eye/kebab hidden), so the spinner+elapsed
   label get the room they need instead of cramming into the hover-actions cluster. */
.segpanel__seg-actions--pending { display: flex; align-items: center; }
.segpick__empty { color: var(--fg-muted); font-size: var(--text-sm); padding: 1rem; text-align: center; }
.segpanel__count { margin-left: auto; color: var(--fg-muted); font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.segpanel__morph, .segpanel__export, .segpanel__vessel, .segpanel__ai-settings { display: flex; flex-direction: column; gap: 0.4rem; padding-top: 0.5rem; border-top: 1px solid var(--border-subtle); }
.segpanel__morph-head, .segpanel__export-head, .segpanel__vessel-head, .segpanel__ai-settings-head { display: flex; justify-content: space-between; align-items: center; font-weight: var(--weight-semibold); }
.segpanel__ai-settings-label { font-size: var(--text-xs); color: var(--fg-secondary); margin-top: 0.2rem; }
.segpanel__ai-host { color: var(--fg-muted); }
.segpanel__morph-r { display: flex; align-items: center; gap: 0.3rem; font-weight: 400; font-size: var(--text-xs); }
.segpanel__morph-r input[type=range] { width: 5rem; accent-color: var(--accent); }
.segpanel__morph-btns { display: flex; flex-wrap: wrap; gap: 0.25rem; }
.segpanel__smooth { display: flex; flex-direction: column; gap: 0.35rem; padding: 0.4rem 0 0.5rem; }
.segpanel__smooth label:not(.segpanel__check) { display: flex; flex-direction: column; color: var(--fg-secondary); }
.segpanel__smooth input[type=range] { accent-color: var(--accent); }
.segpanel__smooth-head { font-weight: var(--weight-semibold); font-size: var(--text-xs); color: var(--fg-secondary); margin-top: 0.25rem; }
.segpanel__smooth-head:first-child { margin-top: 0; }
.segpanel__select { width: 100%; padding: 0.15rem; font-size: var(--text-xs); }
.segpanel__export-row { display: flex; gap: 0.4rem; align-items: center; }
.segpanel__advtoggle { border: none; background: none; text-align: left; padding: 0.25rem 0; cursor: pointer; color: var(--fg-secondary); font-size: var(--text-xs); font-weight: var(--weight-semibold); border-top: 1px solid var(--border-subtle); }
.segpanel__advtoggle:hover { color: var(--fg-primary); }
.slice-view__toggle { color: var(--fg-on-canvas); font-size: var(--text-2xs); display: flex; gap: 0.25rem; align-items: center; opacity: 0.8; }
.slice-view__error { color: #ff9a9a; font-size: var(--text-2xs); padding: 0.15rem 0.35rem; }
/* Fixed-width so the label cycling saved↔saving doesn't shift the stack chips that follow it. */
.editor__autosave { color: var(--fg-muted); font-size: var(--text-xs); margin-left: 0.5rem; display: inline-block; min-width: 8.5rem; white-space: nowrap; }
.editor__case { display: flex; align-items: center; gap: 0.3rem; }
.editor__case-name { font-weight: var(--weight-semibold); }

/* ============================================================ Top-bar image stacks (Direction D)
   Stacks as clickable chips inline in the editor top bar. Active chip = accent tint; the primary
   stack carries the violet Master badge, every other stack reads Aligned (mint) or Coregister
   (amber, actionable). A square Add chip + a Coregister-all cluster when anything is pending. */
.hs-stackbar { display: inline-flex; align-items: center; gap: var(--space-2); padding-left: var(--space-4); border-left: 1px solid var(--border-subtle); min-width: 0; }
.tchip { position: relative; display: inline-flex; align-items: center; gap: var(--space-2); height: 32px; padding: 0 var(--space-2) 0 var(--space-3); border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-surface); color: var(--fg-secondary); font-size: var(--text-sm); font-weight: var(--weight-medium); cursor: pointer; white-space: nowrap; transition: var(--transition-colors); }
.tchip:hover { background: var(--bg-hover); border-color: var(--border-strong); color: var(--fg-primary); }
.tchip:focus-visible { outline: none; box-shadow: var(--ring-focus, 0 0 0 3px var(--border-accent)); }
.tchip.is-active { background: var(--accent-subtle); border-color: var(--border-accent); color: var(--accent-fg); }
.tchip__ico { display: inline-flex; color: var(--fg-muted); flex: 0 0 auto; }
.tchip.is-active .tchip__ico { color: var(--accent-fg); }
.tchip__name { overflow: hidden; text-overflow: ellipsis; max-width: 14rem; }
.tchip.is-off { color: var(--fg-muted); }
.tchip.is-off .tchip__name { font-style: italic; }
/* 3D-visibility eye: always visible on the chip (not hover-gated like the kebab) */
.tchip__eye { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; margin-left: 0.1rem; border-radius: var(--radius-xs); color: var(--fg-muted); flex: 0 0 auto; transition: var(--transition-colors); }
.tchip__eye:hover { background: var(--bg-active); color: var(--fg-secondary); }
.tchip__eye.is-off { color: var(--fg-faint); }
/* kebab: quiet until hover/active/open, so a single clean chip isn't busy */
.tchip__kebab { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; margin-left: 0.1rem; border-radius: var(--radius-xs); color: var(--fg-faint); opacity: 0; transition: var(--transition-colors); }
.tchip:hover .tchip__kebab, .tchip.is-active .tchip__kebab, .tchip__kebab.is-open { opacity: 1; }
.tchip__kebab:hover { background: var(--bg-active); color: var(--fg-secondary); }
.tchip__add { width: 32px; padding: 0; justify-content: center; color: var(--fg-secondary); position: relative; overflow: hidden; }
.tchip__add:hover { background: var(--accent-subtle); border-color: var(--border-accent); color: var(--accent-fg); }
.tchip__add input[type=file] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }

/* status badges (shared vocabulary: violet master · mint aligned · amber coregister) */
.sbadge { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-3xs); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-caps); text-transform: uppercase; padding: 1px var(--space-2); border-radius: var(--radius-full); white-space: nowrap; line-height: 1.5; }
.sbadge--master { background: var(--accent); color: var(--fg-on-accent); }
.sbadge--aligned { background: var(--success-bg); color: var(--success-fg); }
.sbadge--coreg { background: var(--warning-bg); color: var(--warning-fg); border: 1px solid var(--warning); cursor: pointer; transition: var(--transition-colors); }
.sbadge--coreg:hover { background: var(--warning); color: #fff; }

/* per-chip options popover */
.hs-stackmenu { position: absolute; top: calc(100% + 6px); left: 0; z-index: var(--z-dropdown, 1000); display: flex; flex-direction: column; min-width: 14rem; padding: 0.3rem; background: var(--bg-raised, var(--bg-surface)); border: 1px solid var(--border-default); border-radius: var(--radius-md); box-shadow: var(--elevation-menu, var(--shadow-md)); cursor: default; font-weight: var(--weight-normal); }
.hs-stackmenu__item { display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.5rem; border: none; background: none; color: var(--fg-primary); font: inherit; font-size: var(--text-sm); text-align: left; border-radius: var(--radius-sm); cursor: pointer; transition: var(--transition-colors); }
.hs-stackmenu__item:hover { background: var(--bg-hover); }
.hs-stackmenu__item--danger { color: var(--danger); }
.hs-stackmenu__item--danger:hover { background: var(--danger-bg); }
.hs-stackmenu__coreg { display: flex; flex-direction: column; gap: 0.35rem; padding: 0.4rem 0.5rem; border-top: 1px solid var(--border-subtle); margin-top: 0.2rem; }
.hs-stackmenu__label { font-size: var(--text-2xs); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--fg-faint); }
.hs-stackmenu__xyz { display: flex; gap: 0.3rem; }
.hs-stackmenu__xyz label { display: inline-flex; flex-direction: column; font-size: var(--text-2xs); color: var(--fg-secondary); gap: 2px; }
.hs-stackmenu__xyz input { width: 3.6rem; font-size: var(--text-xs); padding: 0.15rem 0.3rem; border: 1px solid var(--border-default); border-radius: var(--radius-xs); background: var(--bg-surface); color: var(--fg-primary); }
.hs-stackmenu__drag { display: flex; align-items: center; gap: 0.35rem; font-size: var(--text-xs); color: var(--fg-secondary); cursor: pointer; }

/* coregister-all cluster (amber dot + button), shown only while a stack is pending */
.hs-stackbar__coreg { display: inline-flex; align-items: center; gap: var(--space-2); }
.hs-stackbar__dot { width: 7px; height: 7px; border-radius: var(--radius-full); background: var(--warning); flex: 0 0 auto; }
.hs-stackbar__coreg-btn { display: inline-flex; align-items: center; gap: 0.35rem; }
.hs-stackbar__error { font-size: var(--text-xs); color: var(--danger); }
.hs-stackbar__phase { font-size: var(--text-xs); color: var(--fg-muted); }

/* ── Per-chip image-appearance (contrast) button + its drop-down menu ───────────── */
.tchip__contrast { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; margin-left: 0.1rem; border-radius: var(--radius-xs); color: var(--fg-muted); flex: 0 0 auto; transition: var(--transition-colors); }
.tchip__contrast:hover { background: var(--bg-active); color: var(--fg-secondary); }
.tchip__contrast.is-open { background: var(--accent); color: var(--slate-0); }
.tchip.is-active .tchip__contrast { color: var(--accent-fg); }
.tchip.is-active .tchip__contrast.is-open { color: var(--slate-0); }

/* transparent click-off catcher behind the open appearance menu */
.hs-appmenu__backdrop { position: fixed; inset: 0; z-index: var(--z-dropdown, 1000); }

/* the "big menu below" — wide appearance panel dropped under the stack bar. Anchored to the chip's
   RIGHT edge (grows leftward): the top-bar chips always sit in the right portion of the screen, so a
   left-anchored menu would spill off the right edge. */
.hs-appmenu {
  position: absolute; top: calc(100% + 6px); right: 0; left: auto; z-index: calc(var(--z-dropdown, 1000) + 1);
  display: block; width: 32rem; max-width: min(32rem, 94vw);
  max-height: min(92vh, 54rem); overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain;
  visibility: hidden; /* revealed by hsPlaceMenu once clamped into the viewport (avoids an off-screen flash) */
  background: var(--bg-raised, var(--bg-surface)); border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, var(--radius-md)); box-shadow: var(--elevation-menu, var(--shadow-lg));
  cursor: default; font-weight: var(--weight-normal);
}
.hs-appmenu__head {
  display: flex; align-items: baseline; gap: 0.5rem; padding: 0.7rem 0.85rem 0.55rem;
  border-bottom: 1px solid var(--border-subtle); flex: 0 0 auto;
  position: sticky; top: 0; z-index: 1; background: var(--bg-raised, var(--bg-surface));
}
.hs-appmenu__title { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary); }
.hs-appmenu__sub { font-size: var(--text-xs); color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-right: auto; }
.hs-appmenu__close { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; margin: -2px -4px 0 0; padding: 0; border: none; background: none; color: var(--fg-muted); border-radius: var(--radius-sm); cursor: pointer; transition: var(--transition-colors); flex: 0 0 auto; align-self: center; }
.hs-appmenu__close:hover { background: var(--bg-hover); color: var(--fg-primary); }
.hs-appmenu .imgapp { padding: 0.8rem 1rem 0.9rem; gap: 0.65rem; }
/* In the wide popover the colormap grid gets more columns so all presets fit without scrolling. The
   thumbs use a FIXED height (not aspect-ratio) so a scrollbar shrinking the column width can't grow
   their height and trigger a scroll-reservation feedback loop (classic Windows scrollbars). */
.hs-appmenu .ctpreset-picker__grid { grid-template-columns: repeat(5, 1fr); }
.hs-appmenu .ctpreset-picker__thumb { aspect-ratio: auto; height: 3.25rem; }
.hs-appmenu .imgapp__presets { grid-template-columns: repeat(3, 1fr); }
/* the graph/section already sit under the imgapp gap — drop their own top margins in the popover */
.hs-appmenu .ctpreset-graph { margin-top: 0; }
.hs-appmenu .ctpreset-graph__body { height: 2.4rem; }

/* ── Image Appearance panel body (shared: top-bar popover + labeling sidebar) ───── */
.imgapp { display: flex; flex-direction: column; gap: 0.7rem; }
.imgapp__section { display: flex; flex-direction: column; gap: 0.45rem; }
.imgapp__label { font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--fg-muted); text-transform: uppercase; letter-spacing: var(--tracking-caps, 0.05em); }

.imgapp__wlrow { display: flex; align-items: center; }
.imgapp__wlreadout { display: inline-flex; align-items: baseline; gap: 0.3rem; padding: 0.25rem 0.6rem; border-radius: var(--radius-full); background: var(--bg-subtle); border: 1px solid var(--border-subtle); font-size: var(--text-sm); color: var(--fg-secondary); font-variant-numeric: tabular-nums; }
.imgapp__wlreadout b { color: var(--fg-primary); font-weight: var(--weight-semibold); }
.imgapp__wltag { font-size: var(--text-2xs); font-weight: var(--weight-semibold); letter-spacing: 0.03em; color: var(--fg-faint); text-transform: uppercase; }
.imgapp__wltag:not(:first-child) { margin-left: 0.25rem; }

/* the contrast hint, restyled as a dismissible callout with inline mouse + drag-direction icons */
.imgapp__tip { display: flex; flex-direction: column; gap: 0.6rem; padding: 0.7rem 0.75rem; background: var(--accent-subtle); border: 1px solid var(--border-accent); border-radius: var(--radius-md); }
.imgapp__tip-header { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.imgapp__tip-title { font-size: var(--text-2xs); font-weight: var(--weight-semibold); letter-spacing: 0.04em; text-transform: uppercase; color: var(--fg-faint); }
.imgapp__tip-close { display: inline-flex; align-items: center; justify-content: center; width: 1.25rem; height: 1.25rem; padding: 0; border: none; background: none; color: var(--fg-secondary); cursor: pointer; border-radius: var(--radius-sm); }
.imgapp__tip-close:hover { color: var(--fg-primary); background: var(--border-accent); }
.imgapp__tip-line { margin: 0; font-size: var(--text-xs); line-height: 1.8; color: var(--fg-secondary); }
.imgapp__tip-line b { color: var(--fg-primary); font-weight: var(--weight-semibold); }
/* inline icons flow with the words — sized to the text, accent-tinted, nudged onto the baseline */
.imgapp__ico { display: inline-block; width: 1em; height: 1em; vertical-align: -0.16em; color: var(--accent); margin-right: 0.3em; }
.imgapp__ico--mouse { width: 1.15em; height: 1.15em; vertical-align: -0.28em; }
.imgapp__tip-dismiss { align-self: flex-start; padding: 0; border: none; background: none; font: inherit; font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--accent); cursor: pointer; }
.imgapp__tip-dismiss:hover { text-decoration: underline; }

/* redesigned contrast presets — Soft tissue / Bone / … as tidy cards with the W/L sub-label */
.imgapp__presets { display: grid; grid-template-columns: repeat(auto-fill, minmax(6.4rem, 1fr)); gap: 0.4rem; }
.wlpreset { display: flex; flex-direction: column; gap: 0.1rem; align-items: flex-start; padding: 0.4rem 0.55rem; background: var(--bg-subtle); border: 1px solid var(--border-default); border-radius: var(--radius-md); font-family: inherit; text-align: left; cursor: pointer; transition: border-color 0.13s ease, background 0.13s ease, box-shadow 0.13s ease; }
.wlpreset:hover { border-color: var(--border-strong); background: var(--bg-hover); }
.wlpreset:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-subtle-hover, var(--accent-subtle)); border-color: var(--border-accent); }
.wlpreset.is-active { border-color: var(--border-accent); background: var(--accent-subtle); }
.wlpreset__name { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary); line-height: 1.15; }
.wlpreset__hu { font-size: var(--text-2xs); color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.wlpreset.is-active .wlpreset__hu { color: var(--accent-fg); }
.wlpreset--auto { background: transparent; border-style: dashed; }
/* cinematic key/ambient light sliders (shown under the cinematic checkbox while it's on) */
.imgapp__cinrow { display: flex; align-items: center; gap: 0.6rem; font-size: var(--text-xs); color: var(--fg-secondary); }
.imgapp__cinrow > span { width: 3.6rem; flex: 0 0 auto; }
.imgapp__cinrow input { flex: 1 1 auto; }
/* automatic liver-VR channel: gradient strip of the live liver transfer function */
.imgapp__livergraph { height: 12px; border-radius: var(--radius-sm); border: 1px solid var(--border-default); }
@keyframes spin { to { transform: rotate(360deg); } }

/* mint-700/800 (not bright --success) so the white label clears WCAG AA (4.5:1) in both themes —
   white on the brand-bright mint was unreadable (1.8:1 dark / 2.9:1 light). */
.btn-success { color: #fff; background-color: var(--mint-700); border-color: transparent; }
.btn-success:hover:not(:disabled), .btn-success:focus:not(:disabled) { background-color: var(--mint-800); color: #fff; }
/* Green-OUTLINE success (used by the editor Validate button) — quieter than the solid fill. */
.btn-outline-success { color: var(--success-fg); background-color: transparent; border-color: var(--success); }
.btn-outline-success:hover:not(:disabled), .btn-outline-success:focus:not(:disabled) { color: var(--success-fg); background-color: var(--success-bg); border-color: var(--success); }

/* ===========================================================================
   3 · LIBRARY
=========================================================================== */
.library { min-height: 100vh; display: flex; flex-direction: column; padding: 2rem; box-sizing: border-box; background: var(--bg-app); }
.library__header, .library__status, .library__loading, .library__empty, .library__list { width: 100%; max-width: 880px; align-self: center; }
.library__header { display: flex; align-items: center; margin-bottom: 1.5rem; }
.library__title { margin: 0; margin-right: auto; font-size: var(--text-h1); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-tight); }
.library__actions { display: flex; gap: 0.5rem; align-items: center; }
.library__status { color: var(--success-fg); font-size: var(--text-sm); margin-bottom: 0.75rem; }
.library__create-hint { color: var(--fg-secondary); font-size: var(--text-xs); margin: 0 0 0.5rem; }
.library__create-row { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.library__ai-toggle { margin: 0.5rem 0 0.25rem; }
.library__create label.btn { margin: 0; cursor: pointer; }
.library__dropzone { border: 1.5px dashed var(--border-strong); border-radius: var(--radius-md); padding: 1.5rem; text-align: center; color: var(--fg-muted); background: var(--bg-sunken); }
.library__dropzone.is-drag { border-color: var(--accent); background: var(--accent-subtle); color: var(--accent-fg); }
.library__loading { display: flex; align-items: center; gap: 0.75rem; padding: 3rem 0; color: var(--fg-muted); }
.library__spinner { width: 18px; height: 18px; border: 2px solid var(--slate-150); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.7s linear infinite; flex-shrink: 0; }
.library__empty { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 5rem 2rem; color: var(--fg-faint); }
.library__empty-icon { margin-bottom: 1.25rem; color: var(--accent); opacity: 0.7; }
.library__empty-title { font-size: var(--text-h3); font-weight: var(--weight-semibold); color: var(--fg-secondary); margin: 0 0 0.5rem; }
.library__empty-sub { font-size: var(--text-base); color: var(--fg-muted); margin: 0 0 1.75rem; line-height: 1.6; }
.library__list { display: flex; flex-direction: column; gap: 0.5rem; }
.library__row { display: flex; align-items: center; gap: 1rem; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 0.85rem 1rem; box-shadow: var(--shadow-sm); transition: box-shadow 0.15s, border-color 0.15s; }
.library__row:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.library__row--clickable { cursor: pointer; }
.library__row--unsupported { background: var(--warning-bg); border-color: var(--amber-100); }
.library__row-icon { color: var(--fg-faint); flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.library__row-check { flex-shrink: 0; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0 0.15rem; }
.library__row-check input { cursor: pointer; }
.library__row-thumb { width: 72px; height: 72px; border-radius: var(--radius-sm); object-fit: cover; background: #000; display: block; }
.library__row-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.library__row-name { font-weight: var(--weight-semibold); font-size: var(--text-base); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.library__row-meta { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.library__row-date { font-size: var(--text-xs); color: var(--fg-muted); }
.library__row-warn { font-size: var(--text-xs); color: var(--warning-fg); font-weight: var(--weight-medium); }
.library__row-controls { display: flex; align-items: center; gap: 0.4rem; flex-shrink: 0; }

/* Status badges → tokens */
.library__badge { display: inline-block; padding: 0.15rem 0.55rem; border-radius: var(--radius-full); font-size: var(--text-2xs); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-wide); text-transform: uppercase; }
.library__badge--draft { background: var(--bg-active); color: var(--fg-secondary); }
.library__badge--inprogress { background: var(--info-bg); color: var(--info-fg); }
.library__badge--validated { background: var(--success-bg); color: var(--success-fg); }

/* List pager (Components/Pager.razor) — sits under a .library__list */
.pager { width: 100%; max-width: 880px; align-self: center; display: flex; align-items: center; justify-content: center; gap: 0.6rem; padding: 0.9rem 0 0.25rem; }
.pager__summary { font-size: var(--text-xs); color: var(--fg-muted); margin-right: auto; }
.pager__page { font-size: var(--text-sm); color: var(--fg-secondary); white-space: nowrap; }
.pager__size { width: auto; margin-left: auto; }

.library__rename-row { display: flex; gap: 0.4rem; align-items: center; }
.library__rename-input { flex: 1 1 auto; padding: 0.3rem 0.5rem; font-size: var(--text-base); border: 1px solid var(--accent); border-radius: var(--radius-sm); outline: none; box-shadow: var(--ring-focus); }
.library__delete-confirm-label { font-size: var(--text-sm); color: var(--danger); font-weight: var(--weight-medium); white-space: nowrap; }

/* ===========================================================================
   4 · MODALS / DIALOGS
=========================================================================== */
.hs-modal-overlay { position: fixed; inset: 0; background: var(--scrim); display: flex; align-items: center; justify-content: center; z-index: var(--z-overlay); }
.hs-modal { background: var(--bg-raised); border-radius: var(--radius-lg); width: min(480px, 92vw); box-shadow: var(--elevation-dialog); }
.hs-modal__header { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem 1rem; border-bottom: 1px solid var(--border-subtle); }
.hs-modal__header h3 { margin: 0; font-size: var(--text-h3); font-weight: var(--weight-semibold); }
.hs-modal__close { background: none; border: none; font-size: 1.1rem; cursor: pointer; color: var(--fg-muted); }
.hs-modal__close:hover { color: var(--fg-primary); }
.hs-modal__body { padding: 1rem; display: flex; flex-direction: column; gap: 0.75rem; }
.hs-modal__field { display: flex; flex-direction: column; gap: 0.25rem; }
.hs-modal__field input { padding: 0.4rem 0.5rem; border: 1px solid var(--border-default); border-radius: var(--radius-sm); }
.hs-modal__actions { display: flex; gap: 0.5rem; justify-content: flex-end; }
.hs-modal--wide { width: min(640px, 95vw); }

/* ===========================================================================
   5 · AI SEGMENT MODAL
=========================================================================== */
.ai-seg__target { display: flex; align-items: center; gap: 0.5rem; font-size: var(--text-sm); margin-bottom: 0.5rem; }
.ai-seg__target select { padding: 0.3rem 0.5rem; border: 1px solid var(--border-default); border-radius: var(--radius-sm); }
.ai-seg__hint { font-size: var(--text-xs); color: var(--fg-muted); margin: 0 0 0.5rem; }
.ai-seg__config { display: flex; flex-direction: column; gap: 0.75rem; }
.ai-seg__row { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; }
.ai-seg__row label { display: flex; flex-direction: column; gap: 0.2rem; }
.ai-seg__row select { padding: 0.3rem 0.5rem; border: 1px solid var(--border-default); border-radius: var(--radius-sm); }
.ai-seg__check { flex-direction: row !important; align-items: center; gap: 0.4rem !important; }
.ai-seg__picker { border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; }
.ai-seg__picker-header { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem; background: var(--bg-sunken); border-bottom: 1px solid var(--border-subtle); flex-wrap: wrap; }
.ai-seg__search { flex: 1; min-width: 140px; padding: 0.3rem 0.5rem; border: 1px solid var(--border-default); border-radius: var(--radius-sm); font-size: var(--text-sm); }
.ai-seg__count { font-size: var(--text-xs); color: var(--fg-muted); margin-left: auto; }
.ai-seg__groups { max-height: 350px; overflow-y: auto; padding: 0.25rem 0; }
.ai-seg__group { border-bottom: 1px solid var(--border-subtle); }
.ai-seg__group:last-child { border-bottom: none; }
.ai-seg__group-header { display: flex; align-items: center; gap: 0.4rem; padding: 0.4rem 0.6rem; cursor: pointer; user-select: none; font-size: var(--text-sm); background: var(--bg-surface); position: sticky; top: 0; }
.ai-seg__group-header:hover { background: var(--bg-hover); }
.ai-seg__group-arrow { font-size: 0.6rem; transition: transform 0.15s; display: inline-block; color: var(--fg-muted); }
.ai-seg__group-arrow--open { transform: rotate(90deg); }
.ai-seg__group-count { font-size: var(--text-xs); color: var(--fg-muted); }
.ai-seg__item { display: flex; align-items: center; gap: 0.4rem; padding: 0.2rem 0.6rem 0.2rem 1.4rem; font-size: var(--text-sm); cursor: pointer; }
.ai-seg__item:hover { background: var(--bg-hover); }
.ai-seg__color { width: 12px; height: 12px; border-radius: var(--radius-xs); flex-shrink: 0; background: var(--swatch, transparent); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.15); }
.ai-seg__progress { display: flex; flex-direction: column; gap: 0.5rem; padding: 1rem 0; }
.ai-seg__status { font-size: var(--text-base); }
.ai-seg__error { color: var(--danger); font-size: var(--text-sm); }
.ai-seg__done { display: flex; align-items: center; gap: 0.75rem; }

/* ===========================================================================
   6 · PROGRESS + ERRORS
=========================================================================== */
.hs-progress { display: flex; flex-direction: column; gap: 0.35rem; }
.hs-progress__label { font-size: var(--text-sm); color: var(--fg-secondary); }
.hs-progress__bar { height: 8px; background: var(--bg-active); border-radius: var(--radius-full); overflow: hidden; }
.hs-progress__fill { height: 100%; background: var(--accent); transition: width 0.1s linear; }
.library__open-error { display: flex; flex-direction: column; gap: 0.4rem; }
.library__open-error strong { color: var(--danger); }
.library__open-error pre { background: var(--danger-bg); border: 1px solid var(--red-100); border-radius: var(--radius-sm); padding: 0.5rem; margin: 0; white-space: pre-wrap; word-break: break-word; font-size: var(--text-sm); color: var(--red-700); }

/* ===========================================================================
   7 · RESEARCH WORKSPACE (shell + projects + case list)
=========================================================================== */
.shell { display: flex; min-height: 100vh; background: var(--bg-app); }
.shell__nav { flex: 0 0 220px; width: 220px; box-sizing: border-box; padding: 1.25rem 0.75rem; border-right: 1px solid var(--border-default); background: var(--bg-surface); display: flex; flex-direction: column; gap: 1.5rem; position: sticky; top: 0; height: 100vh; }
.shell__brand { display: flex; align-items: center; gap: 0.6rem; padding: 0 0.5rem; }
.shell__brand-mark { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: var(--radius-sm); background: var(--accent); color: #fff; font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-wide); }
.shell__brand-name { font-weight: var(--weight-semibold); font-size: var(--text-base); }
.shell__beta { padding: 0.05rem 0.4rem; border-radius: var(--radius-full); background: var(--warning-bg); color: var(--warning-fg); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; }
.shell__group { display: flex; flex-direction: column; gap: 0.15rem; }
.shell__group-label { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-faint); font-weight: var(--weight-semibold); padding: 0 0.6rem 0.35rem; }
.shell__link { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.6rem; border-radius: var(--radius-sm); color: var(--fg-secondary); font-size: var(--text-sm); font-weight: var(--weight-medium); text-decoration: none; transition: background 0.12s, color 0.12s; }
.shell__link:hover { background: var(--bg-sunken); color: var(--fg-primary); }
.shell__link.active { background: var(--accent-subtle); color: var(--accent-fg); }
.shell__link svg { flex-shrink: 0; }
.shell__soon { margin-left: auto; font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-faint); border: 1px solid var(--border-default); border-radius: var(--radius-full); padding: 0.05rem 0.4rem; }
.shell__account { margin-top: auto; padding: 0.75rem 0.6rem 0; border-top: 1px solid var(--border-default); display: flex; flex-direction: column; gap: 0.5rem; }
.shell__account-name { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--fg-secondary); }
.shell__account-link { font-size: var(--text-sm); color: var(--fg-muted); text-decoration: none; }
.shell__account-link:hover { color: var(--accent-fg); }
.shell__account-signout { align-self: flex-start; }
.shell__main { flex: 1 1 auto; min-width: 0; overflow-y: auto; height: 100vh; }

.page { max-width: 980px; margin: 0 auto; padding: 2rem; box-sizing: border-box; }
.page__crumbs { display: flex; align-items: center; gap: 0.4rem; font-size: var(--text-sm); color: var(--fg-muted); margin-bottom: 0.75rem; }
.page__crumbs a { color: var(--fg-secondary); text-decoration: none; }
.page__crumbs a:hover { color: var(--accent-fg); }
.page__header { display: flex; align-items: flex-start; gap: 1rem; margin-bottom: 1.5rem; }
.page__title { margin: 0; font-size: var(--text-h1); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-tight); }
.page__subtitle { margin: 0.3rem 0 0; color: var(--fg-muted); font-size: var(--text-sm); }
.page__actions { margin-left: auto; display: flex; gap: 0.5rem; align-items: center; flex-shrink: 0; }
.page__status { color: var(--danger); font-size: var(--text-sm); margin: 0 0 0.75rem; }
.page__loading { display: flex; align-items: center; gap: 0.75rem; padding: 3rem 0; color: var(--fg-muted); }

.card { background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 1rem; box-shadow: var(--shadow-sm); }
.card--form { display: flex; flex-direction: column; gap: 0.6rem; margin-bottom: 1.25rem; max-width: 520px; }
.card__actions { display: flex; gap: 0.5rem; }
.field { width: 100%; box-sizing: border-box; padding: 0.45rem 0.6rem; font-size: var(--text-sm); border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--bg-surface); color: var(--fg-primary); outline: none; }
.field:focus { border-color: var(--accent); box-shadow: var(--ring-focus); }

.cardgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.85rem; }
.projcard { position: relative; display: flex; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: var(--radius-md); box-shadow: var(--shadow-sm); transition: box-shadow 0.15s, border-color 0.15s; min-height: 120px; }
.projcard:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.projcard--all { background: var(--bg-sunken); }
.projcard__body { display: flex; flex-direction: column; gap: 0.3rem; flex: 1 1 auto; min-width: 0; padding: 1rem; cursor: pointer; }
.projcard__icon { color: var(--accent); opacity: 0.85; }
.projcard__name { font-weight: var(--weight-semibold); font-size: var(--text-base); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-right: 1.5rem; }
.projcard__desc { font-size: var(--text-sm); color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; flex: 1 1 auto; }
.projcard__meta { display: flex; align-items: center; justify-content: space-between; margin-top: 0.35rem; font-size: var(--text-xs); color: var(--fg-faint); }
.projcard__count { font-weight: var(--weight-semibold); color: var(--fg-secondary); }
.projcard__opts { position: absolute; z-index: 2; top: 0.55rem; right: 0.55rem; display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; border: none; border-radius: var(--radius-sm); background: transparent; color: var(--fg-faint); cursor: pointer; opacity: 0.45; transition: opacity 0.15s, background 0.15s, color 0.15s; }
.projcard:hover .projcard__opts { opacity: 1; }
.projcard__opts:hover { background: var(--bg-sunken); color: var(--fg-secondary); }
.projcard__opts:focus-visible { opacity: 1; outline: 2px solid var(--accent); outline-offset: 1px; }
.projcard--editing { cursor: default; flex-direction: column; gap: 0.5rem; justify-content: center; padding: 1rem; }
.projcard--editing:hover { box-shadow: var(--shadow-sm); border-color: var(--accent); }
.projcard__edit-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.15rem; }
.projcard__edit-delete { margin-left: auto; }
.projcard__confirm { font-size: var(--text-xs); color: var(--fg-secondary); margin-right: auto; }

.caselist__toolbar { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1rem; flex-wrap: wrap; }
.caselist__search { display: flex; align-items: center; gap: 0.45rem; flex: 1 1 240px; min-width: 180px; padding: 0.4rem 0.6rem; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--bg-surface); color: var(--fg-muted); }
.caselist__search:focus-within { border-color: var(--accent); box-shadow: var(--ring-focus); }
.caselist__search-input { border: 0; outline: 0; background: transparent; font-size: var(--text-sm); color: var(--fg-primary); flex: 1 1 auto; }
.caselist__select { padding: 0.4rem 0.6rem; font-size: var(--text-sm); border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--bg-surface); color: var(--fg-primary); }
.caselist__count { font-size: var(--text-xs); color: var(--fg-faint); margin-left: auto; }
.caselist__none { color: var(--fg-muted); font-size: var(--text-sm); padding: 2rem 0; text-align: center; }
.caselist__subject { font-size: var(--text-xs); color: var(--fg-secondary); }
.caselist__chip { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); font-weight: var(--weight-semibold); color: var(--accent-fg); background: var(--accent-subtle); border-radius: var(--radius-full); padding: 0.1rem 0.5rem; }

.caseedit { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem 0.75rem; padding: 0.25rem 0; }
.caseedit__field { display: flex; flex-direction: column; gap: 0.2rem; }
.caseedit__label { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-faint); font-weight: var(--weight-semibold); }
.caseedit__actions { grid-column: 1 / -1; display: flex; gap: 0.5rem; }
/* ---------------------------------------------------------------------------
   Labeling pages — /labeling and /labeling/{projectId}
   Shares the .library* shell from the clinical library; only the
   labeling-specific chrome (chips, status pills, status switch, tag chips,
   schema editor, project header) is bespoke.
--------------------------------------------------------------------------- */

/* Project list cards */
.lbl-chip { display: inline-flex; align-items: center; padding: 0.1rem 0.5rem; border-radius: var(--radius-full); background: var(--bg-sunken); color: var(--fg-secondary); font-size: var(--text-xs); font-weight: var(--weight-medium); }
/* Clickable project chip (image library "used in") */
.lbl-chip--link { gap: 0.35rem; border: 1px solid var(--border-default); cursor: pointer; transition: background 0.12s ease, color 0.12s ease; }
.lbl-chip--link:hover { background: var(--bg-hover); color: var(--fg-primary); }
.lbl-chip__count { display: inline-flex; align-items: center; justify-content: center; min-width: 1.1rem; height: 1.1rem; padding: 0 0.25rem; border-radius: var(--radius-full); background: var(--bg-canvas); color: var(--fg-muted); font-size: 0.65rem; }
/* Warning chip (e.g. "already in this project") */
.lbl-chip--warn { background: var(--danger-bg); color: var(--danger-fg); border: 1px solid var(--red-100); }
/* Active trained-model chip */
.lbl-chip--active { background: color-mix(in srgb, #3cb44b 18%, var(--bg-sunken)); color: var(--fg-primary); font-weight: var(--weight-semibold); }
/* Per-project coloured chip + dot (deterministic --proj colour) */
.lbl-chip__dot { display: inline-block; width: 0.55rem; height: 0.55rem; border-radius: var(--radius-full); background: var(--proj, var(--fg-muted)); flex: 0 0 auto; }
.lbl-chip--proj { border-color: color-mix(in srgb, var(--proj) 55%, transparent); background: color-mix(in srgb, var(--proj) 12%, var(--bg-sunken)); color: var(--fg-primary); }
.lbl-chip--proj:hover { background: color-mix(in srgb, var(--proj) 22%, var(--bg-sunken)); color: var(--fg-primary); }

/* Image-library toolbar (search + filters + view toggle) */
.library__toolbar { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
.library__search { display: flex; align-items: center; gap: 0.4rem; padding: 0.25rem 0.6rem; border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-surface); color: var(--fg-muted); }
.library__search input { border: none; background: transparent; outline: none; color: var(--fg-primary); font-size: var(--text-sm); min-width: 13rem; }
.library__filter { width: auto; min-width: 9rem; }
.library__toolbar-spacer { flex: 1 1 auto; }
.library__count { font-size: var(--text-xs); color: var(--fg-muted); white-space: nowrap; }
.library__view-toggle { display: inline-flex; gap: 0.25rem; }

/* Dataset detail */
.ds-meta { display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: 0.75rem; }
.ds-section { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary); margin: 1rem 0 0.5rem; display: flex; align-items: center; gap: 0.5rem; }

/* Image-library grid view */
.library__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 0.75rem; }
.lib-card { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.75rem; border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-surface); }
.lib-card__top { display: flex; align-items: center; gap: 0.5rem; }
.lib-card__name { font-weight: var(--weight-semibold); color: var(--fg-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lib-card__projects { margin-top: 0.1rem; }
.lib-card__controls { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: auto; padding-top: 0.25rem; }
/* Image-library "add to projects" picker */
.lbl-pick__rows { display: flex; flex-direction: column; gap: 0.25rem; max-height: 16rem; overflow-y: auto; }
.lbl-pick__row { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.5rem; border-radius: var(--radius-sm); cursor: pointer; }
.lbl-pick__row:hover { background: var(--bg-hover); }
.lbl-pick__name { flex: 1; font-size: var(--text-sm); color: var(--fg-primary); }

/* New-project modal label-schema editor */
.lbl-form__row { display: flex; flex-direction: column; gap: 0.25rem; }
.lbl-form__label { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--fg-secondary); }
.lbl-form__section-title { display: flex; align-items: baseline; gap: 0.75rem; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary); margin-top: 0.25rem; }
.lbl-form__hint { font-weight: var(--weight-regular); color: var(--fg-muted); font-size: var(--text-xs); }
.lbl-form__error { color: var(--danger-fg); background: var(--danger-bg); border: 1px solid var(--red-100); border-radius: var(--radius-sm); padding: 0.4rem 0.6rem; font-size: var(--text-sm); margin: 0; }
.lbl-form__progress { width: 100%; height: 0.5rem; background: var(--bg-subtle); border-radius: var(--radius-sm); overflow: hidden; margin-top: 0.4rem; }
.lbl-form__progress-bar { height: 100%; background: var(--accent-fg); transition: width 120ms linear; }

.lbl-schema__rows { display: flex; flex-direction: column; gap: 0.4rem; }
/* Dataset→project label-map editor: chip · arrow · full-width select (don't reuse the schema grid,
   whose narrow color column squeezes the select and clips its options). */
.lbl-map__rows { display: flex; flex-direction: column; gap: 0.4rem; }
.lbl-map__row { display: grid; grid-template-columns: minmax(6rem, auto) auto 1fr; gap: 0.5rem; align-items: center; }
.lbl-map__row select { width: 100%; }
.lbl-map__arrow { color: var(--fg-muted); }
.lbl-schema__row { display: grid; grid-template-columns: 70px 1fr 38px 36px; gap: 0.4rem; align-items: center; }
.lbl-schema__id { padding: 0.3rem 0.4rem; }
.lbl-schema__name { padding: 0.3rem 0.5rem; }
.lbl-schema__color { width: 38px; height: 32px; padding: 0; border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: transparent; cursor: pointer; }

/* Project page — header breadcrumb + schema bar */
.lbl-project__title-wrap { display: flex; flex-direction: column; gap: 0.15rem; margin-right: auto; }
.lbl-project__breadcrumb { font-size: var(--text-xs); color: var(--fg-muted); text-decoration: none; }
.lbl-project__breadcrumb:hover { color: var(--accent-fg); }

.lbl-schema-bar { width: 100%; max-width: 880px; align-self: center; display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 0.5rem 0; margin-bottom: 0.5rem; }
.lbl-schema-chip { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.2rem 0.55rem; border: 1px solid var(--border-default); border-radius: var(--radius-full); background: var(--bg-surface); font-size: var(--text-xs); color: var(--fg-primary); }
.lbl-schema-chip__swatch { width: 10px; height: 10px; border-radius: 50%; border: 1px solid var(--border-strong); flex-shrink: 0; }
.lbl-schema-chip__id { color: var(--fg-muted); font-variant-numeric: tabular-nums; }

/* Filters */
.lbl-filters { width: 100%; max-width: 880px; align-self: center; display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; }
.lbl-filters__pills { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.lbl-pill { padding: 0.2rem 0.7rem; border-radius: var(--radius-full); border: 1px solid var(--border-default); background: var(--bg-surface); color: var(--fg-secondary); font-size: var(--text-xs); font-weight: var(--weight-medium); cursor: pointer; transition: var(--transition-colors); }
.lbl-pill:hover { background: var(--bg-hover); color: var(--fg-primary); }
.lbl-pill--on { background: var(--accent-subtle); color: var(--accent-fg); border-color: var(--border-accent); }
/* Count badge inside a status filter pill — a subtle inset chip that inherits the pill's text colour. */
.lbl-pill__count { display: inline-block; min-width: 1.15rem; margin-left: 0.3rem; padding: 0 0.32rem; border-radius: var(--radius-full); background: var(--bg-active); color: inherit; font-size: 0.72em; font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; text-align: center; }
.lbl-pill--on .lbl-pill__count { background: var(--border-accent); }
.lbl-filters__inputs { display: flex; gap: 0.3rem; align-items: center; }
.lbl-filters__search { width: 180px; }
.lbl-filters__tag { width: 130px; }

/* Status badge (on rows) */
.lbl-status-badge { display: inline-block; padding: 0.15rem 0.55rem; border-radius: var(--radius-full); font-size: var(--text-2xs); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-wide); text-transform: uppercase; }
.lbl-status-badge--unlabeled { background: var(--bg-active); color: var(--fg-secondary); }
.lbl-status-badge--inprogress { background: var(--info-bg); color: var(--info-fg); }
.lbl-status-badge--review { background: var(--warning-bg); color: var(--warning-fg); }
.lbl-status-badge--labeled { background: var(--success-bg); color: var(--success-fg); }
.lbl-status-badge--clinical { background: var(--accent); color: var(--fg-on-accent); }
.lbl-status-badge--ailabeled { background: var(--accent-subtle); color: var(--accent-fg); }

/* Status switch (per-row button group) */
.lbl-status-switch { display: inline-flex; border: 1px solid var(--border-default); border-radius: var(--radius-sm); overflow: hidden; }
.lbl-status-switch__btn { padding: 0.2rem 0.5rem; min-width: 26px; background: var(--bg-surface); color: var(--fg-secondary); border: none; border-left: 1px solid var(--border-default); font-size: var(--text-xs); font-weight: var(--weight-semibold); cursor: pointer; transition: var(--transition-colors); }
.lbl-status-switch__btn:first-child { border-left: none; }
.lbl-status-switch__btn:hover:not(:disabled) { background: var(--bg-hover); color: var(--fg-primary); }
.lbl-status-switch__btn--on { background: var(--accent); color: var(--fg-on-accent); }
.lbl-status-switch__btn--on:hover:not(:disabled) { background: var(--accent-hover); color: var(--fg-on-accent); }
/* Labeled/Clinical (and any disabled) buttons are shown but greyed — they're reached via review
   sign-off, not set here. The current status stays highlighted (--on) even while disabled. */
.lbl-status-switch__btn:disabled:not(.lbl-status-switch__btn--on) { opacity: 0.4; cursor: not-allowed; }
.lbl-status-switch__btn:disabled.lbl-status-switch__btn--on { cursor: default; }

/* Review progress chips (case list) */
.lbl-review-chip { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.1rem 0.45rem; border-radius: var(--radius-full); background: var(--bg-hover); color: var(--fg-secondary); font-size: var(--text-2xs); font-weight: var(--weight-semibold); }
.lbl-review-who { font-size: var(--text-2xs); color: var(--fg-muted); max-width: 28ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Reviewer panel (editor toolbar) */
.lbl-review { display: inline-flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.lbl-review__group { display: inline-flex; align-items: center; gap: 0.4rem; }
.lbl-review__count { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--fg-secondary); }
.lbl-review__names { font-size: var(--text-xs); color: var(--fg-muted); max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lbl-review__error { font-size: var(--text-xs); color: var(--danger-fg); }

/* Imports panel (project page) — return to an in-progress / recent import */
.lbl-imports { border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 0.6rem 0.8rem; margin-bottom: 1rem; background: var(--bg-surface); }
.lbl-imports__head { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.4rem; }
.lbl-imports__close { margin-left: auto; background: none; border: none; color: var(--fg-muted); cursor: pointer; font-size: var(--text-sm); line-height: 1; padding: 0 0.2rem; }
.lbl-imports__close:hover { color: var(--fg-primary); }
/* highlight the top-bar Imports button while a job is running */
.lbl-imports-btn--active { border-color: var(--warning-fg); color: var(--warning-fg); }
.lbl-imports__title { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-secondary); }
.lbl-imports__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.lbl-imports__row { display: flex; align-items: center; gap: 0.6rem; }
.lbl-imports__meta { font-size: var(--text-xs); color: var(--fg-muted); }
.lbl-imports__row .btn { margin-left: auto; }

/* Import status view (?job=) */
.lbl-import__status-head { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 0.6rem 0; }

/* AI-accuracy panel (project page) */
.lbl-aiacc { border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 0.5rem 0.8rem; margin-bottom: 1rem; background: var(--bg-surface); }
.lbl-aiacc__head { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.lbl-aiacc__toggle { background: none; border: none; color: var(--fg-secondary); font-size: var(--text-sm); font-weight: var(--weight-semibold); cursor: pointer; padding: 0; }
.lbl-aiacc__filter { margin-left: auto; font-size: var(--text-xs); color: var(--fg-secondary); display: inline-flex; align-items: center; gap: 0.3rem; }
.lbl-aiacc__table { width: 100%; margin-top: 0.5rem; border-collapse: collapse; font-size: var(--text-xs); }
.lbl-aiacc__table th, .lbl-aiacc__table td { text-align: left; padding: 0.25rem 0.5rem; border-bottom: 1px solid var(--border-subtle); }
.lbl-aiacc__table th { color: var(--fg-muted); font-weight: var(--weight-semibold); }

/* Tag chips on case rows */
.lbl-tag-chip { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.1rem 0.45rem; border-radius: var(--radius-full); background: var(--accent-subtle); color: var(--accent-fg); font-size: var(--text-xs); font-weight: var(--weight-medium); }
.lbl-tag-chip__x { background: none; border: none; color: var(--accent-fg); cursor: pointer; padding: 0 0.15rem; font-size: var(--text-sm); line-height: 1; opacity: 0.6; }
.lbl-tag-chip__x:hover { opacity: 1; }
.lbl-tag-chip--add { background: transparent; border: 1px dashed var(--border-strong); color: var(--fg-muted); cursor: pointer; }
.lbl-tag-chip--add:hover { color: var(--accent-fg); border-color: var(--border-accent); }
.lbl-tag-add { display: inline-flex; gap: 0.3rem; align-items: center; }
.lbl-tag-add__input { width: 140px; }

/* Auth + platform */
/* App shell: a body that fills the viewport (no global header bar). The editor fills app-body
   exactly (height:100%); scrolling list pages scroll inside app-body. */
.app-root { display: flex; flex-direction: column; height: 100vh; }
.app-body { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* ============================================================================
   8b · PLATFORM ADMIN  (Platform.razor — sidebar + tab panels)
   ============================================================================ */
.pl { display: flex; height: 100vh; height: 100dvh; width: 100%; overflow: hidden; background: var(--bg-app); color: var(--fg-primary); }
.pl-side { flex: 0 0 220px; display: flex; flex-direction: column; background: var(--bg-surface); border-right: 1px solid var(--border-default); }
.pl-side__head { padding: 16px 14px 10px; border-bottom: 1px solid var(--border-default); }
.pl-brand { display: flex; align-items: center; gap: 9px; margin-bottom: 12px; text-decoration: none; }
.pl-brand:hover .ws-brand__name { color: var(--accent); }
.pl-side__title { margin: 0; font-size: 15px; font-weight: 700; color: var(--fg-primary); }
.pl-side__sub { margin: 4px 0 0; font-size: var(--text-xs); color: var(--fg-muted); }
.pl-side__nav { flex: 1; padding: 8px 10px; overflow-y: auto; }
.pl-nav { display: flex; flex-direction: column; gap: 2px; }
/* Sections, not a flat pile of nine. A caption must not read as another link, and tone ALONE could
   not carry that: --fg-muted and --fg-secondary are ADJACENT slate steps in light theme (500 vs
   600), so the label and the items were near enough the same ink. Separated three ways instead —
   a hairline rule per group (structure), the items promoted to --fg-primary (four steps of ink
   between them and the caption), and the caption left small/uppercase/tracked. */
.pl-nav__group { display: flex; flex-direction: column; gap: 2px; }
.pl-nav__group + .pl-nav__group { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border-default); }
.pl-nav__grouplabel { padding: 0 10px 6px; font-size: var(--text-2xs); font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--fg-muted); cursor: default; }
.pl-nav__btn { display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px; border: 0; border-radius: var(--radius-sm);
    background: transparent; color: var(--fg-primary); font-size: var(--text-sm); font-weight: var(--weight-medium); cursor: pointer; text-align: left; }
.pl-nav__btn:hover { background: var(--bg-hover); color: var(--fg-primary); }
.pl-nav__btn.is-active { background: var(--accent-subtle); color: var(--accent-fg); }
.pl-side__foot { display: flex; align-items: center; gap: 6px; padding: 10px 12px; border-top: 1px solid var(--border-default); }
.pl-foot__spacer { flex: 1 1 auto; }
.pl-foot__icon { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: 0; background: transparent; border-radius: var(--radius-sm); color: var(--fg-muted); cursor: pointer; text-decoration: none; }
.pl-foot__icon:hover { background: var(--bg-hover); color: var(--fg-primary); }
.pl-main { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
.pl-bar { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; padding: 14px 20px; background: var(--bg-surface); border-bottom: 1px solid var(--border-default); }
.pl-bar__title { margin: 0; font-size: 18px; font-weight: 700; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Which sidebar section the open tab belongs to — grounds the title now that the nav is grouped. */
.pl-bar__crumb { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--fg-muted); }
.pl-bar__crumb::after { content: "/"; margin: 0 6px; opacity: 0.6; }
/* Hamburger (mobile only — the media block shows it): three bars that morph into an X. */
.pl-bar__menu { display: none; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    width: 38px; height: 38px; flex: 0 0 auto; border: 0; background: transparent; border-radius: var(--radius-sm); cursor: pointer; }
.pl-bar__menu:hover { background: var(--bg-hover); }
.pl-bar__menu span { display: block; width: 18px; height: 2px; border-radius: 1px; background: var(--fg-primary);
    transition: transform var(--duration-fast) var(--ease-standard), opacity var(--duration-fast) var(--ease-standard); }
.pl-bar__menu.is-open span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.pl-bar__menu.is-open span:nth-child(2) { opacity: 0; }
.pl-bar__menu.is-open span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
.pl-backdrop { display: none; }
.pl-scroll { flex: 1; overflow-y: auto; padding: 20px; }
.pl-panel { max-width: 960px; }
.pl-panel--wide { max-width: none; }
.pl-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr)); gap: 12px; margin-bottom: 24px; }
.pl-card { padding: 14px 16px; background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: var(--radius-md); }
.pl-card__label { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--fg-muted); font-weight: var(--weight-semibold); margin-bottom: 6px; }
.pl-card__value { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--fg-primary); }
.pl-card__hint { font-size: var(--text-xs); color: var(--fg-muted); margin-top: 4px; }
.pl-section { margin-bottom: 28px; }
.pl-section__head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; row-gap: 4px; margin-bottom: 12px; }
.pl-section__head h3 { margin: 0; font-size: 14px; font-weight: 600; flex: 1; }
.pl-section__hint { font-size: var(--text-xs); color: var(--fg-muted); margin: -6px 0 12px; }
.pl-section__hint--inline { margin: 0; flex: 1; }
/* Sub-page switcher inside a panel (Users: browse the roster vs. add new ones). */
.pl-subnav { display: flex; gap: 4px; margin: 0 0 20px; border-bottom: 1px solid var(--border-default); overflow-x: auto; }
.pl-subnav__btn { padding: 8px 14px; border: 0; background: transparent; color: var(--fg-secondary); white-space: nowrap; flex: 0 0 auto;
    font-size: var(--text-sm); font-weight: 600; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.pl-subnav__btn:hover { color: var(--fg-primary); }
.pl-subnav__btn.is-active { color: var(--accent-fg); border-bottom-color: var(--accent); }
.pl-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: end; margin-bottom: 14px; }
.pl-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; max-width: 100%; }
/* selects size to their widest option (long hospital names / emails) — cap them to the field */
.pl-field select.pl-input { width: 100%; }
.pl-field__label { font-size: var(--text-xs); color: var(--fg-secondary); font-weight: 500; }
/* Takes the leftover row width — for a lone picker (hospital member add) next to its button. */
.pl-field--grow { flex: 1 1 220px; }
.pl-input { height: var(--control-height-sm); max-width: 100%; padding: 0 10px; border: 1px solid var(--border-default); border-radius: var(--radius-sm);
    background: var(--bg-surface); color: var(--fg-primary); font-size: var(--text-sm); min-width: 0; }
.pl-input:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring-focus); }
.pl-input--area { height: auto; min-height: 120px; padding: 10px; font-family: var(--font-mono); font-size: var(--text-xs); resize: vertical; }
.pl-check { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-sm); color: var(--fg-secondary); white-space: nowrap; }
/* Hospital-membership multi-select in the user edit row. */
.pl-hosp-edit { display: flex; flex-direction: column; gap: 2px; max-height: 140px; overflow-y: auto; }
/* Field grids hold ONLY labelled inputs; align inputs at the top so an optional
   hint under one field (e.g. password) doesn't push its input out of line with siblings.
   Buttons go in .pl-form-actions and checkboxes in .pl-form-checks — never inside the grid. */
.pl-form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr)); gap: 10px; align-items: start; margin-bottom: 10px; }
.pl-form-checks { display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center; margin: 0 0 12px; }
.pl-form-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 4px; }
/* overflow-x scrolls (not clips) when a table outgrows the panel — the mobile baseline; on desktop
   tables fit, so no scrollbar appears. overflow-y hidden keeps the border-radius clipping. */
.pl-table-wrap { border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; background: var(--bg-surface); }
.pl-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.pl-table th, .pl-table td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--border-subtle); vertical-align: middle; }
.pl-table th { background: var(--bg-sunken); color: var(--fg-secondary); font-weight: 600; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.03em; }
/* Sortable column header: the whole cell is the hit target. The caret is rendered for every
   sortable column but stays invisible until hover, so unsorted columns read as clickable
   without a row of permanent arrows. */
.pl-th-sort { cursor: pointer; user-select: none; white-space: nowrap; }
.pl-th-sort:hover { background: var(--bg-hover); color: var(--fg-primary); }
.pl-th-sort.is-sorted { color: var(--fg-primary); }
.pl-th-sort__caret { margin-left: 4px; font-size: 8px; opacity: 0; }
.pl-th-sort:hover .pl-th-sort__caret { opacity: 0.45; }
.pl-th-sort.is-sorted .pl-th-sort__caret { opacity: 1; color: var(--accent); }
.pl-table tr:last-child td { border-bottom: 0; }
.pl-table tr:hover td { background: var(--bg-hover); }
.pl-table tr.is-disabled td { opacity: 0.55; }
.pl-table tr.is-edit td { background: var(--accent-subtle); }
/* AI-server live activity sub-row: rides directly under its server row (no divider between the
   pair), one flex line of badges/mono facts + the Stop/Reset actions. */
.pl-table tr.pl-subrow td { border-top: 0; padding-top: 0; background: var(--bg-sunken); }
.pl-table tr.pl-subrow:hover td { background: var(--bg-sunken); }
.pl-subrow__err { color: var(--danger); }
.pl-badge { display: inline-block; padding: 2px 8px; border-radius: var(--radius-full); font-size: var(--text-2xs); font-weight: 600; }
.pl-badge--ok { background: var(--success-bg); color: var(--success); }
.pl-badge--warn { background: var(--warning-bg); color: var(--warning); }
.pl-badge--muted { background: var(--bg-sunken); color: var(--fg-muted); }
.pl-badge--accent { background: var(--accent-subtle); color: var(--accent-fg); }
.pl-badge--err { background: var(--danger-bg); color: var(--danger); }
.pl-actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.pl-empty { padding: 32px; text-align: center; color: var(--fg-muted); font-size: var(--text-sm); }
.pl-toast { margin: 0 20px 12px; padding: 10px 14px; border-radius: var(--radius-sm); font-size: var(--text-sm); }
.pl-toast--ok { background: var(--success-bg); color: var(--success); border: 1px solid var(--success-border, transparent); }
.pl-toast--err { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-border, transparent); }
.pl-token { font-family: var(--font-mono); font-size: var(--text-xs); word-break: break-all; padding: 8px 10px; background: var(--bg-sunken); border-radius: var(--radius-sm); margin-top: 8px; }
.pl-mono { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--fg-muted); }
/* long unbroken tokens (URLs, JSON, correlation ids) may break anywhere INSIDE a table cell, so a
   single mono value can't force a 600px column; only engages when the cell is out of room */
.pl-table .pl-mono { overflow-wrap: anywhere; }
.pl-card--clickable { cursor: pointer; transition: border-color var(--duration-fast), box-shadow var(--duration-fast); }
.pl-card--clickable:hover { border-color: var(--accent); box-shadow: var(--shadow-sm); }
.pl-card__value--warn { color: var(--danger); }
.pl-card__value--ok { color: var(--success); }
.pl-card__value--attn { color: var(--warning); }
.pl-row-clickable { cursor: pointer; }
.pl-row-clickable:hover td { background: var(--accent-subtle); }
.pl-cards--org { grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); }
.pl-org-header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 20px; }
.pl-org-header__main { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px; }
.pl-org-back { margin-top: 2px; }
.pl-org-title { margin: 0 0 4px; font-size: 20px; font-weight: 700; overflow-wrap: anywhere; }
.pl-org-sub { margin: 0; font-size: var(--text-sm); color: var(--fg-secondary); display: flex; flex-wrap: wrap; align-items: center; gap: 8px; overflow-wrap: anywhere; }
.pl-compare-strip { display: flex; flex-wrap: wrap; gap: 12px 20px; padding: 10px 14px; margin-bottom: 20px;
    background: var(--bg-sunken); border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
    font-size: var(--text-xs); color: var(--fg-secondary); }
.pl-chart-range { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 16px; }
.pl-charts-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-bottom: 16px; }
/* grid items default min-width:auto — a wide table's min-content would blow the track open
   instead of scrolling inside its .pl-table-wrap */
.pl-charts-grid > *, .pl-org-grid > *, .pl-errors-layout > * { min-width: 0; }
@media (max-width: 1120px) { .pl-charts-grid { grid-template-columns: 1fr; } }
.pl-chart-panel { background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 14px 16px; margin-bottom: 0; }
.pl-chart-panel--wide { margin-bottom: 24px; }
.pl-org-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 16px; margin-bottom: 8px; }
@media (max-width: 1120px) { .pl-org-grid { grid-template-columns: 1fr; } }
.pl-chart { margin-top: 4px; }
.pl-chart__svg { width: 100%; height: 120px; display: block; background: var(--bg-sunken); border-radius: var(--radius-sm); }
.pl-chart__bar { fill: var(--accent); opacity: 0.85; }
.pl-chart__bar.is-hover { opacity: 1; fill: var(--accent-fg, var(--accent)); }
/* Y axis. A 2-column grid, NOT padding + absolute positioning: the tick column is `auto`, so it is
   exactly as wide as its widest label. A fixed gutter has to be guessed per label vocabulary and
   then re-guessed per breakpoint — "256.0 MB" overflowed a gutter sized for "0/1/2/3" the moment
   the viewport narrowed. The x-label row lives in the SAME grid (row 2, plot column) so it tracks
   the tick column's width automatically and can never drift off its bars.
   Tick text is HTML, not SVG <text>: the plot's preserveAspectRatio="none" would squash glyphs.
   The tick column stretches to the plot row's height, so a tick's `bottom: X%` is a percentage of
   the plot itself; translateY(50%) then re-centres the label on its gridline. */
.pl-chart__area { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 6px; }
.pl-chart__yaxis { grid-column: 1; grid-row: 1; position: relative; pointer-events: none; }
.pl-chart__yaxis span { position: absolute; right: 0; transform: translateY(50%); white-space: nowrap;
    font-size: var(--text-2xs); font-family: var(--font-mono); color: var(--fg-muted); line-height: 1; }
/* Zero-height in-flow copy of the labels: the only thing giving the auto column a width, since every
   visible tick is absolutely positioned. Hidden from a11y (aria-hidden) and from paint. */
.pl-chart__yaxis-sizer { height: 0; overflow: hidden; visibility: hidden; }
.pl-chart__yaxis-sizer span { position: static; display: block; transform: none; }
.pl-chart__area > .pl-chart__plot { grid-column: 2; grid-row: 1; }
.pl-chart__area > .pl-chart__labels { grid-column: 2; grid-row: 2; }
.pl-chart__area > .pl-chart__peak { grid-column: 2; grid-row: 3; }
/* Mixed off --fg-muted rather than a --border-* token: the plot background is --bg-sunken, and the
   border tokens sit only one or two slate steps from it (subtle-on-sunken is #ECEEF3 on #F5F6F9,
   ~1.07:1 — an invisible hairline, which defeats the point of a labelled axis; even --border-default
   only reaches ~1.30:1). Mixing the muted FOREGROUND keeps a predictable ratio in both themes,
   since fg-muted is by definition legible against the surface. */
.pl-chart__grid, .pl-spark__grid { stroke: color-mix(in srgb, var(--fg-muted) 38%, transparent);
    stroke-width: 0.5; vector-effect: non-scaling-stroke; }
.pl-chart__grid.is-base, .pl-spark__grid.is-base { stroke: color-mix(in srgb, var(--fg-muted) 65%, transparent);
    stroke-width: 1; }
.pl-chart__labels { display: flex; justify-content: space-between; gap: 4px; margin-top: 6px;
    font-size: 10px; color: var(--fg-muted); font-family: var(--font-mono); overflow: hidden; }
.pl-chart__labels span { flex: 1; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-chart__peak { margin-top: 6px; font-size: var(--text-xs); color: var(--fg-muted); }
.pl-chart-empty { height: 120px; display: flex; align-items: center; justify-content: center; padding: 0; }
/* Hover readout (PlBarChart / PlSparkChart). The plot is the positioning context; one transparent
   <rect> per data point covers the full plot height so even a zero-height bucket is hoverable. The
   tooltip anchors to the plot edge near the ends so it never spills out of the panel. */
.pl-chart__plot { position: relative; }
.pl-chart__hit { fill: transparent; pointer-events: all; cursor: crosshair; }
.pl-chart__tip { position: absolute; top: 6px; transform: translateX(-50%); z-index: 2; pointer-events: none;
    display: flex; flex-direction: column; gap: 1px; padding: 4px 8px; border-radius: var(--radius-sm);
    background: var(--bg-surface); border: 1px solid var(--border-strong); box-shadow: var(--shadow-md);
    white-space: nowrap; }
.pl-chart__tip--start { left: 4px; transform: none; }
.pl-chart__tip--end { right: 4px; transform: none; }
.pl-chart__tip-val { font-size: var(--text-sm); font-weight: 600; color: var(--fg-primary);
    font-variant-numeric: tabular-nums; display: flex; gap: 8px; }
.pl-chart__tip-lbl { font-size: var(--text-2xs); color: var(--fg-muted); font-family: var(--font-mono); }
.pl-spark__cursor { stroke: var(--border-strong); stroke-width: 1; vector-effect: non-scaling-stroke; }
.pl-spark__dot { fill: var(--spark, var(--accent)); stroke: var(--bg-sunken); stroke-width: 0.5; vector-effect: non-scaling-stroke; }
.pl-spark__dot--a { fill: var(--success); }
.pl-spark__dot--b { fill: var(--info); }
.pl-hbars { display: flex; flex-direction: column; gap: 10px; }
.pl-hbar { display: grid; grid-template-columns: 5.5rem 1fr 2rem; gap: 8px; align-items: center; font-size: var(--text-sm); }
.pl-hbar__label { color: var(--fg-secondary); }
.pl-hbar__track { height: 8px; background: var(--bg-sunken); border-radius: var(--radius-full); overflow: hidden; }
.pl-hbar__fill { height: 100%; background: var(--accent); border-radius: var(--radius-full); min-width: 2px; }
.pl-hbar__fill--validated { background: var(--success); }
.pl-hbar__fill--inprogress { background: var(--accent); }
.pl-hbar__fill--draft { background: var(--fg-muted); opacity: 0.45; }
.pl-hbar__value { text-align: right; font-variant-numeric: tabular-nums; color: var(--fg-primary); font-weight: 600; }
.pl-errors-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
@media (max-width: 1120px) { .pl-errors-layout { grid-template-columns: 1fr; } }
.pl-dl { display: grid; grid-template-columns: 7rem 1fr; gap: 6px 12px; font-size: var(--text-sm); margin: 0; }
.pl-dl dt { color: var(--fg-muted); font-weight: 500; }
.pl-dl dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.pl-stack { background: var(--bg-sunken); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
    padding: 10px; font-family: var(--font-mono); font-size: 11px; overflow: auto; max-height: 200px; white-space: pre-wrap; word-break: break-word; }
.pl-stack--sm { max-height: 120px; }
.pl-timeline { list-style: none; margin: 0; padding: 0 0 0 8px; border-left: 2px solid var(--border-default); }
.pl-timeline__item { position: relative; padding: 8px 0 8px 16px; font-size: var(--text-sm); }
.pl-timeline__item::before { content: ''; position: absolute; left: -5px; top: 14px; width: 8px; height: 8px;
    border-radius: 50%; background: var(--border-default); }
.pl-timeline__item--nav::before { background: var(--accent); }
.pl-timeline__item--error::before { background: var(--danger); }
.pl-timeline__time { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--fg-muted); margin-right: 8px; }
.pl-timeline__type { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--fg-muted); margin-right: 6px; }
.pl-timeline__route { display: block; font-size: var(--text-xs); color: var(--fg-muted); margin-top: 2px; }
/* ---- Server metrics dashboard (Server tab) ---- */
.pl-metric { padding: 14px 16px; background: var(--bg-surface); border: 1px solid var(--border-default);
    border-radius: var(--radius-md); display: flex; flex-direction: column; gap: 6px; }
.pl-metric__value { font-size: 24px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--fg-primary); line-height: 1.1; }
.pl-metric__value--muted { color: var(--fg-muted); }
.pl-metric__value--net { font-size: 15px; display: flex; flex-direction: column; gap: 2px; }
.pl-meter { height: 6px; background: var(--bg-sunken); border-radius: var(--radius-full); overflow: hidden; }
.pl-meter__fill { height: 100%; background: var(--accent); border-radius: var(--radius-full); min-width: 2px;
    transition: width var(--duration-fast) linear; }
.pl-meter__fill--gpu { background: var(--success); }
.pl-meter__fill.is-warn, .pl-hbar__fill.is-warn { background: var(--warning); }
.pl-meter__fill.is-crit, .pl-hbar__fill.is-crit { background: var(--danger); }
.pl-net-dn { color: var(--success); font-variant-numeric: tabular-nums; }
.pl-net-up { color: var(--info); font-variant-numeric: tabular-nums; }
.pl-live { display: inline-flex; align-items: center; gap: 4px; margin-left: 8px; font-size: var(--text-xs);
    color: var(--success); text-transform: uppercase; letter-spacing: 0.04em; }
.pl-live--off { color: var(--fg-muted); }
.pl-live__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--success); animation: pl-pulse 1.6s ease-in-out infinite; }
.pl-live--off .pl-live__dot { background: var(--fg-muted); animation: none; }
@keyframes pl-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
.pl-server-updated { align-self: center; color: var(--fg-muted); font-size: var(--text-xs); }
.pl-chart-now { font-size: var(--text-sm); font-weight: 600; color: var(--fg-primary); font-variant-numeric: tabular-nums; }
/* Spans the panel, gutter included — it is a caption ("-8m … peak 15.3 MB/s"), not plotted data, and
   the tick column's width is now content-driven so there is no constant to align it to. */
.pl-chart-axis { display: flex; justify-content: space-between; margin-top: 6px; font-size: var(--text-2xs); color: var(--fg-muted); }
.pl-spark { width: 100%; height: 110px; display: block; background: var(--bg-sunken); border-radius: var(--radius-sm); }
.pl-spark__area { fill: color-mix(in srgb, var(--spark, var(--accent)) 20%, transparent); stroke: none; }
.pl-spark__line { fill: none; stroke: var(--spark, var(--accent)); stroke-width: 1.5;
    vector-effect: non-scaling-stroke; stroke-linejoin: round; stroke-linecap: round; }
.pl-spark--cpu { --spark: var(--accent); }
.pl-spark--ram { --spark: var(--info); }
.pl-spark--gpu { --spark: var(--success); }
.pl-spark__line--a { stroke: var(--success); }
.pl-spark__line--b { stroke: var(--info); }
.pl-cores { display: flex; flex-wrap: wrap; gap: 4px; }
.pl-core { width: 20px; height: 20px; border-radius: 4px; border: 1px solid var(--border-subtle);
    background: color-mix(in srgb, var(--accent) calc(var(--l, 0) * 1%), var(--bg-sunken)); }
.pl-gpu-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); gap: 12px; }
.pl-gpu { display: flex; flex-direction: column; gap: 8px; }
.pl-gpu__name { font-weight: 600; font-size: var(--text-sm); color: var(--fg-primary); }
.pl-gpu__stats { display: flex; flex-wrap: wrap; gap: 6px; }
.pl-hbar__fill--gpu { background: var(--success); }
.pl-drive { display: flex; flex-direction: column; gap: 4px; }
.pl-drive__head { display: flex; justify-content: space-between; gap: 8px; font-size: var(--text-sm); flex-wrap: wrap; }
.pl-drive__name { font-weight: 600; color: var(--fg-primary); }
.pl-drive__track { height: 10px; }
/* Two-segment used/free bar (storage) — both portions always visible. */
.pl-split { display: flex; height: 8px; border-radius: var(--radius-full); overflow: hidden; background: var(--bg-sunken); }
.pl-split--lg { height: 12px; }
.pl-split__used { flex: 0 0 auto; min-width: 2px; background: var(--accent); }
.pl-split__used.is-warn { background: var(--warning); }
.pl-split__used.is-crit { background: var(--danger); }
.pl-split__free { flex: 1 1 auto; background: color-mix(in srgb, var(--success) 45%, var(--bg-sunken)); }
.pl-gpu__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.pl-gpu__big { display: flex; gap: 22px; flex-wrap: wrap; }
.pl-gpu__big > div { display: flex; flex-direction: column; }
.pl-gpu__num { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--fg-primary); line-height: 1.15; }
.pl-gpu__cap { font-size: var(--text-xs); color: var(--fg-muted); }

/* ============================================================================
   8c · AI SERVERS  (PlatformAiServers.razor)
   A registered Bolo-AI box is a 2-D object — identity + two endpoints + hardware
   + build + quality + a live job — and there are only ever 1-3 of them, so the
   fleet is a CARD LIST, not a 7-column table with two colspan escapes. Cards
   carry every field at 390px (nothing needs .pl-mhide here) and priority reorder
   works on a phone.
   COLOUR ROLES, enforced: --success = reachable/serving · --accent = the GPU is
   working RIGHT NOW · --warning = a chore or a slow path · --danger = broken.
   Density rule: at most ONE saturated chip per resting card.
   ============================================================================ */
.pl-srv-list { display: flex; flex-direction: column; gap: 10px; }
.pl-srv { position: relative; padding: 12px 14px 12px 17px; background: var(--bg-surface);
    border: 1px solid var(--border-default); border-radius: var(--radius-md); }
/* 3px left rail: reachability, and --accent while the GPU is working. Readable in
   peripheral vision, so it costs no chip in a head that already carries four things. */
.pl-srv::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
    border-radius: var(--radius-md) 0 0 var(--radius-md); background: transparent; }
.pl-srv--serving::before { background: var(--success); }
.pl-srv--standby::before { background: color-mix(in srgb, var(--success) 45%, transparent); }
.pl-srv--warn::before { background: var(--warning); }
.pl-srv--down::before { background: var(--danger); }
.pl-srv.is-busy::before { background: var(--accent); }
.pl-srv--off { opacity: 0.62; }
.pl-srv--form { border-color: var(--accent); background: var(--accent-subtle); }
.pl-srv__head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pl-srv__rank { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
    font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--fg-muted); }
.pl-srv__name { font-size: var(--text-base); font-weight: var(--weight-semibold);
    color: var(--fg-primary); min-width: 0; overflow-wrap: anywhere; }
.pl-srv__gap { flex: 1 1 auto; }
.pl-srv__facts { margin-top: 10px; }
.pl-srv__foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 10px;
    padding-top: 10px; border-top: 1px solid var(--border-subtle); }
.pl-srv__foot:empty { display: none; }
.pl-srv--add { display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
    padding: 13px 14px; border-style: dashed; background: transparent; color: var(--fg-secondary);
    font-size: var(--text-sm); font-weight: var(--weight-medium); cursor: pointer; }
.pl-srv--add:hover:not(:disabled) { border-color: var(--accent); color: var(--accent-fg); background: var(--bg-hover); }
.pl-srv--add:disabled { opacity: 0.5; cursor: default; }

/* Reachability is ONE exclusive state: colour in the dot, word in readable ink.
   Replaces up to four equal-weight pills per server (Healthy + ACTIVE said the same
   thing twice), which frees the runner-up to say the more useful "Standby". */
.pl-state { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; white-space: nowrap;
    font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--fg-secondary); }
.pl-state__dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: var(--fg-muted); }
.pl-state--serving { color: var(--fg-primary); }
.pl-state--serving .pl-state__dot { background: var(--success); animation: pl-pulse 1.6s ease-in-out infinite; }
.pl-state--standby .pl-state__dot { background: var(--success); opacity: 0.45; }
.pl-state--warn { color: var(--warning-fg); }
.pl-state--warn .pl-state__dot { background: var(--warning); }
.pl-state--down { color: var(--danger-fg); }
.pl-state--down .pl-state__dot { background: var(--danger); }
.pl-state--off { color: var(--fg-muted); }
.pl-state--off .pl-state__dot { background: var(--fg-disabled); }

/* Live readout. Four fixed cells so the layout cannot jump between 5s polls. 18px
   values, not .pl-card__value's 22px — these are row-level facts, and a 22px em-dash
   is a lot of ink for "no data". */
.pl-srv__live { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
    gap: 12px 14px; margin-top: 10px; padding: 10px 12px;
    background: var(--bg-sunken); border-radius: var(--radius-sm); }
.pl-stat { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.pl-stat__k { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps);
    font-weight: var(--weight-semibold); color: var(--fg-muted); }
.pl-stat__v { font-size: 18px; font-weight: 700; line-height: 1.15;
    font-variant-numeric: tabular-nums; color: var(--fg-primary); overflow-wrap: anywhere; }
.pl-stat__v--muted { color: var(--fg-muted); }
.pl-stat__v--busy { color: var(--accent-fg); }
.pl-stat__v--warn { color: var(--warning-fg); }
.pl-stat__v--err { color: var(--danger-fg); }
.pl-stat__s { font-size: var(--text-xs); color: var(--fg-muted); overflow-wrap: anywhere; }
.pl-stat__s.is-warn { color: var(--warning-fg); }
.pl-stat .pl-meter { margin: 2px 0 1px; }

/* Advisories are chores, not states: one quiet tinted line each. Usually absent. */
.pl-advise { margin-top: 8px; padding: 6px 10px; border-radius: var(--radius-sm);
    font-size: var(--text-xs); background: var(--warning-bg); color: var(--warning-fg);
    overflow-wrap: anywhere; }
.pl-advise--err { background: var(--danger-bg); color: var(--danger-fg); }

/* ONE confirm shape for every destructive step: consequence clause, then
   Confirm <verb> / Cancel. Replaces five hand-rolled inline style="color:var(--danger)"
   spans with four different phrasings. */
.pl-confirm { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px;
    padding: 5px 10px; border-radius: var(--radius-sm); background: var(--danger-bg); }
.pl-confirm__msg { min-width: 0; overflow-wrap: anywhere; font-size: var(--text-xs); color: var(--danger-fg); }

/* Run history's Device column. GPU and CPU share ONE box — same padding, same min-width, same
   line-height — so the column's left edge and baseline hold whichever value a row carries. Only
   CPU is filled: it is the notable case, and 25 green GPU chips would drown the one that matters. */
.pl-dev { display: inline-block; min-width: 3.25rem; padding: 2px 8px; border-radius: var(--radius-full);
    font-size: var(--text-2xs); font-weight: 600; line-height: 1.45; text-align: center;
    color: var(--fg-muted); background: transparent; }
.pl-dev--cpu { background: var(--warning-bg); color: var(--warning-fg); }

.pl-org-title--bad { color: var(--danger); }
/* Probe age beside the pulsing dot — sentence case, unlike PlatformServer's caps "LIVE". */
.pl-live--age { text-transform: none; letter-spacing: 0; color: var(--fg-muted); }
/* Push a trailing action to the far end of a .pl-compare-strip. */
.pl-push { margin-left: auto; }
/* A failed run's badge is the expand trigger — .pl-badge was authored for a <span>. */
button.pl-badge { border: 0; cursor: pointer; font-family: inherit; }
button.pl-badge:hover { box-shadow: inset 0 0 0 1px currentColor; }

@media (max-width: 640px) {
    .pl-srv__live { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
    .pl-srv { padding: 10px 10px 10px 13px; }
    .pl-srv__live { padding: 10px; gap: 10px; }
}
/* The serving dot pulses; honour a reduced-motion preference (also fixes the
   pre-existing .pl-live__dot, which never had an opt-out). */
@media (prefers-reduced-motion: reduce) {
    .pl-state--serving .pl-state__dot, .pl-live__dot { animation: none; }
}

/* ---------- Platform admin: mobile ----------
   ≤768px the sidebar becomes an off-canvas drawer: the hamburger in the top bar slides it in
   from the left over a scrim; tapping the scrim (or picking a tab) closes it. Tables keep every
   feature and scroll sideways inside .pl-table-wrap; columns flagged PlColumn.MobileHide
   (.pl-mhide) drop at ≤640px. */
@media (max-width: 768px) {
    .pl-side { position: fixed; top: 0; bottom: 0; left: 0; z-index: 1200; width: min(300px, 85vw);
        box-shadow: var(--shadow-lg); transform: translateX(-100%);
        transition: transform 240ms var(--ease-standard); will-change: transform; }
    .pl--nav-open .pl-side { transform: translateX(0); }
    .pl-backdrop { display: block; position: fixed; inset: 0; z-index: 1190;
        background: rgba(10, 12, 18, 0.45); opacity: 0; pointer-events: none;
        transition: opacity 200ms var(--ease-standard); }
    .pl--nav-open .pl-backdrop { opacity: 1; pointer-events: auto; }
    .pl-bar__menu { display: inline-flex; }
    /* drawer items settle in with a soft stagger (--i = tab index, set in markup) */
    .pl--nav-open .pl-nav__btn { animation: pl-nav-in 240ms var(--ease-standard) both;
        animation-delay: calc(var(--i) * 25ms); }
    /* horizontal overflow lives ONLY inside .pl-table-wrap — the page itself never side-scrolls */
    .pl-scroll { overflow-x: hidden; padding: 14px; }
    .pl-toast { margin: 0 14px 10px; }
    .pl-bar { padding: 10px 14px; gap: 8px; }
    /* colspan cells (inline edit forms, live-activity sub-rows) ride a sideways-scrolling table —
       pin their content to the visible viewport instead of smearing across the full table width */
    .pl-table td[colspan] > * { position: sticky; left: 8px; max-width: calc(100vw - 44px); max-width: calc(100dvw - 44px); }
    /* section-head hints drop to their own full-width line under the title/actions */
    .pl-section__head .pl-section__hint, .pl-section__head .pl-section__hint--inline { flex: 0 0 100%; order: 3; margin: 0; min-width: 0; }
    /* tapping an error group must show the detail without scrolling past the whole list */
    .pl-errors-layout__detail { order: -1; }
    /* Users inline edit spans multiple real tds (not one colspan cell) — stack it as a block
       form pinned to the visible viewport instead of a row smeared across the scroll width */
    .pl-table--users tr.is-edit { display: grid; grid-template-columns: 1fr; }
    .pl-table--users tr.is-edit td { display: block; position: sticky; left: 8px;
        width: calc(100vw - 44px); width: calc(100dvw - 44px); max-width: 100%; border-bottom: 0; }
    .pl-table--users tr.is-edit td:last-child { border-bottom: 1px solid var(--border-subtle); }
    .pl-table--users tr.is-edit td > .pl-input { width: 100%; }
}

@keyframes pl-nav-in {
    from { opacity: 0; transform: translateX(-10px); }
    to { opacity: 1; transform: none; }
}

@media (max-width: 640px) {
    .pl-mhide { display: none; }                     /* PlColumn.MobileHide columns */
    /* .pl-move (AI-server priority reorder) used to be hidden here because it lived in a
       side-scrolling table cell. It is a wrapping card head now, so the arrows stay. */
    .pl-check { white-space: normal; align-items: flex-start; }
    /* 45-label chart rows: keep only the first/last label at the track's edges */
    .pl-chart__labels span { display: none; }
    .pl-chart__labels span:first-child, .pl-chart__labels span:last-child { display: inline; flex: 0 0 auto; }
    .pl-chart__labels { justify-content: space-between; }
}

@media (max-width: 480px) {
    .pl-scroll { padding: 12px; }
    .pl-toast { margin: 0 12px 10px; }
    .pl-table th, .pl-table td { padding: 8px; }
    .pl-bar { padding: 8px 12px; }
    .pl-bar__title { font-size: 16px; }
    .pl-bar__crumb { display: none; }                /* the tab name alone; the drawer shows its section */
    .pl-brand .ws-brand__name { display: none; }     /* the BC mark carries the brand */
    .pl-dl { grid-template-columns: 1fr; gap: 2px 0; }
    .pl-dl dt { margin-top: 6px; }
    .pl-dl dt:first-child { margin-top: 0; }
}

/* Touch: sort carets are hover-revealed on desktop — show them where hover doesn't exist,
   and give clickable rows a pressed state in place of the hover highlight. */
@media (hover: none) {
    .pl-th-sort__caret { opacity: 0.35; }
    .pl-row-clickable:active td { background: var(--accent-subtle); }
}
/* Touch targets: btn-sm is ~30px tall — bump interactive controls toward the 40px guideline. */
@media (pointer: coarse) {
    .pl .btn-sm { min-height: 40px; }
    .pl-input:not(.pl-input--area) { min-height: 40px; }
    .pl-nav__btn { padding: 10px 12px; }
    .pl-subnav__btn { padding: 10px 14px; }
}
/* "Report a problem" trigger — inline in each page's top bar (no longer floating). */
.report-btn { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
    border-radius: var(--radius-full); border: 1px solid var(--border-default); background: var(--bg-surface);
    color: var(--fg-secondary); font-size: 15px; font-weight: 700; line-height: 1; cursor: pointer;
    transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
.report-btn:hover { background: var(--bg-hover); color: var(--fg-primary); border-color: var(--border-strong); }
/* Pushes the button to the far right of bars that have no flex spacer of their own. */
.report-btn--push { margin-left: auto; }
.report-problem-backdrop { position: fixed; inset: 0; background: rgba(14,16,22,.35); z-index: 2000;
    display: flex; align-items: center; justify-content: center; padding: 1rem; }
.report-problem { background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: var(--radius-md);
    padding: 1.25rem; max-width: 28rem; width: 100%; box-shadow: var(--shadow-lg); }
.report-problem h3 { margin: 0 0 0.5rem; font-size: 1rem; }
/* Full-width, readable textarea (not the platform mono/auto-width default). */
.report-problem .pl-input--area { display: block; width: 100%; box-sizing: border-box; margin: 4px 0 0;
    font-family: var(--font-sans); font-size: var(--text-sm); }
.report-problem .pl-section__hint { margin: 0 0 4px; }

/* Auth — sign-in front page (Login.razor) */
.login-page { min-height: 100dvh; display: grid; place-items: center; padding: var(--space-6);
    background: var(--bg-app); }
.login-page::before { content: ""; position: fixed; inset: 0; pointer-events: none;
    background: var(--gradient-violet-wash); opacity: 0.6; }
.login-card { position: relative; width: 100%; max-width: 24rem; display: flex; flex-direction: column;
    gap: var(--space-4); padding: var(--space-8) var(--space-7); background: var(--bg-surface);
    border: 1px solid var(--border-subtle); border-radius: var(--radius-xl); box-shadow: var(--elevation-card); }
.login-brand { display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
    margin-bottom: var(--space-2); text-align: center; }
.login-brand__logo { width: 72px; height: 72px; border-radius: var(--radius-lg);
    border: 1px solid var(--border-subtle); box-shadow: var(--shadow-sm); }
.login-brand__name { margin: 0; font-size: var(--text-h2); font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tight); color: var(--fg-primary); }
.login-brand__tagline { margin: 0; font-size: var(--text-sm); color: var(--fg-muted); }
.login-form { display: flex; flex-direction: column; gap: 0.4rem; }
.login-form .login__label { margin-top: var(--space-2); }
.login-form__submit { margin-top: var(--space-4); height: var(--control-height); }
.login-sso { height: var(--control-height); }
.login-divider { display: flex; align-items: center; gap: var(--space-3); color: var(--fg-faint);
    font-size: var(--text-xs); }
.login-divider::before, .login-divider::after { content: ""; flex: 1; border-top: 1px solid var(--border-subtle); }
.login-dev { display: flex; flex-direction: column; gap: 0.75rem; margin-top: var(--space-2); }

/* Auth + platform (legacy login helpers) */
.login { max-width: 24rem; margin: 4rem auto; padding: 2rem; display: flex; flex-direction: column; gap: 0.75rem; }
.login__label { font-size: var(--text-sm); color: var(--fg-secondary); }
.login__input { padding: 0.5rem 0.75rem; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
    background: var(--bg-surface); color: var(--fg-primary); font-size: var(--text-base); }
.login__input:focus-visible { outline: none; border-color: var(--border-accent); box-shadow: var(--ring-focus); }
.login__error { color: var(--danger); font-size: var(--text-sm); }
.login__hint, .login__seeds { font-size: var(--text-sm); color: var(--fg-muted); }
.login__users { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.login__user-btn { width: 100%; display: flex; justify-content: space-between; align-items: center; padding: 0.65rem 0.85rem; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--bg-surface); cursor: pointer; text-align: left; }
.login__user-btn:hover:not(:disabled) { background: var(--bg-hover); }
.login__user-btn:disabled { opacity: 0.6; cursor: wait; }
.login__user-email { font-size: var(--text-sm); font-weight: 500; }
.login__user-role { font-size: var(--text-xs); color: var(--fg-muted); }
.login__manual { margin-top: 1rem; font-size: var(--text-sm); color: var(--fg-secondary); }
.login__manual summary { cursor: pointer; margin-bottom: 0.5rem; }
.login__input--sm { padding: 0.35rem 0.5rem; font-size: var(--text-sm); }

/* ============================================================================
   9 · LIBRARY WORKSPACE  (Library.razor — full-viewport sidebar + tiles/list)
   Global (not scoped) because the markup renders icons as raw-SVG MarkupString,
   which CSS-isolation can't attribute. All classes are ws-* to avoid clashes.
   ============================================================================ */
.ws { display: flex; height: 100vh; width: 100%; overflow: hidden; background: var(--bg-app); color: var(--fg-primary); }
.ws svg { flex-shrink: 0; }

/* ---- sidebar ---- */
.ws-side { flex: 0 0 252px; width: 252px; box-sizing: border-box; display: flex; flex-direction: column;
    background: var(--bg-surface); border-right: 1px solid var(--border-default); }
.ws-side__top { padding: 14px 14px 0; }
.ws-side__scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 6px 10px 12px; }
.ws-side__edu { padding: 8px 10px; border-top: 1px solid var(--border-default); }
.ws-side__foot { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--border-default); }

.ws-brand { display: flex; align-items: center; gap: 9px; margin-bottom: 14px; position: relative; }
.ws-brand__mark { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
    border-radius: 8px; background: var(--gradient-brand); color: #fff; font-size: 11px; font-weight: 700; letter-spacing: .02em; }
.ws-brand__text { display: flex; flex-direction: column; min-width: 0; }
.ws-brand__name { font-size: 16px; font-weight: 700; color: var(--fg-primary); line-height: 1.15; }

/* Hospital line under the app name; becomes a dropdown trigger for multi-hospital users. */
.ws-hosp { display: inline-flex; align-items: center; gap: 3px; font-size: var(--text-2xs); color: var(--fg-muted); }
.ws-hosp--btn { border: 0; padding: 0; background: transparent; cursor: pointer; }
.ws-hosp--btn:hover { color: var(--fg-primary); }
.ws-hosp__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 150px; }
.ws-hosp-scrim { position: fixed; inset: 0; z-index: var(--z-dropdown); }
.ws-hosp-menu { left: 0; right: auto; top: calc(100% - 8px); z-index: calc(var(--z-dropdown) + 1); }
.ws-hosp-menu .ws-menu__item { justify-content: space-between; gap: 10px; }

.ws-search { display: flex; align-items: center; gap: 7px; height: var(--control-height-sm); padding: 0 9px;
    border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-surface); color: var(--fg-muted); }
.ws-search:focus-within { border-color: var(--accent); box-shadow: var(--ring-focus); }
.ws-search__input { border: 0; outline: 0; background: transparent; flex: 1 1 auto; min-width: 0;
    font-size: var(--text-sm); color: var(--fg-primary); }

.ws-over { display: flex; align-items: center; justify-content: space-between; gap: 6px;
    font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps);
    color: var(--fg-muted); font-weight: var(--weight-semibold); padding: 12px 8px 5px; }
.ws-over--folders { padding-top: 14px; }
.ws-over__toggle { display: inline-flex; align-items: center; gap: 4px; border: 0; background: transparent; cursor: pointer;
    font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit; padding: 0; }
.ws-over__add { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px;
    border: 0; border-radius: var(--radius-xs); background: transparent; color: var(--fg-muted); cursor: pointer; }
.ws-over__add:hover { background: var(--bg-hover); color: var(--fg-primary); }

.ws-item { position: relative; display: flex; align-items: center; gap: 9px; width: 100%; box-sizing: border-box; padding: 7px 8px;
    border: 0; background: transparent; border-radius: var(--radius-sm); cursor: pointer; text-align: left;
    color: var(--fg-secondary); font-size: var(--text-sm); font-weight: var(--weight-medium);
    transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
.ws-item svg { color: var(--fg-muted); }
.ws-item:hover { background: var(--bg-hover); color: var(--fg-primary); }
.ws-item.is-active { background: var(--accent-subtle); color: var(--accent-fg); }
.ws-item.is-active svg { color: var(--accent); }
.ws-item__name { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ws-item__count { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--fg-faint); font-variant-numeric: tabular-nums; }
.ws-item.is-active .ws-item__count { color: var(--accent-fg); }
/* Hover actions are absolutely positioned so revealing them never reflows the row (no "bounce"). */
.ws-item__acts { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); display: inline-flex;
    align-items: center; gap: 1px; opacity: 0; pointer-events: none; }
.ws-item--folder:hover .ws-item__acts { opacity: 1; pointer-events: auto; }
.ws-item--folder:hover .ws-item__count { opacity: 0; }

.ws-fic { display: inline-flex; flex-shrink: 0; }

.ws-item.is-soon { color: var(--fg-faint); cursor: default; }
.ws-item.is-soon:hover { background: transparent; color: var(--fg-faint); }
.ws-item.is-soon svg { color: var(--fg-faint); }
.ws-soon { font-size: var(--text-3xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-caps);
    color: var(--fg-faint); border: 1px solid var(--border-default); border-radius: var(--radius-full); padding: 1px 6px; }
/* "Beta" tag on the Labeling nav group (preview feature) */
.ws-beta { font-size: var(--text-3xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-caps);
    color: var(--warning-fg); background: var(--warning-bg); border-radius: var(--radius-full); padding: 1px 6px; }
a.ws-item { text-decoration: none; color: inherit; }

.ws-folder-edit { display: flex; align-items: center; gap: 4px; padding: 3px 8px; }
.ws-folder-edit__input { flex: 1 1 auto; min-width: 0; height: 24px; padding: 0 7px; font-size: var(--text-sm);
    border: 1px solid var(--accent); border-radius: var(--radius-sm); outline: none; box-shadow: var(--ring-focus); }
.ws-folder-confirm { display: flex; align-items: center; gap: 4px; padding: 5px 8px; font-size: var(--text-xs); color: var(--fg-secondary); }
.ws-folder-confirm span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-folders-empty { padding: 6px 10px; font-size: var(--text-xs); color: var(--fg-faint); }

.ws-mini { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px;
    border: 0; border-radius: var(--radius-xs); background: transparent; color: var(--fg-muted); cursor: pointer; text-decoration: none; }
.ws-mini:hover { background: var(--bg-hover); color: var(--fg-primary); }
.ws-mini--ok:hover { background: var(--accent-subtle); color: var(--accent); }
.ws-mini--danger { color: var(--danger); }
.ws-mini--danger:hover { background: var(--danger-bg); color: var(--danger); }

.ws-avatar { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 28px; height: 28px;
    border-radius: var(--radius-full); background: var(--gradient-brand); color: #fff; font-size: 11px; font-weight: 700; }
.ws-foot__name { flex: 1 1 auto; min-width: 0; font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- main ---- */
.ws-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; position: relative; }
/* Drag-and-drop import: dropping a scan folder over the library stages files + jumps to /import. */
.ws-drop { position: absolute; inset: 8px; z-index: var(--z-overlay); display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg-app) 72%, transparent); backdrop-filter: blur(2px);
  border: 2px dashed var(--border-accent); border-radius: var(--radius-md); pointer-events: none; }
.ws-drop__card { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; text-align: center; color: var(--fg-primary); }
.ws-drop__ic { color: var(--accent); }
.ws-drop__title { font-size: var(--text-h3); font-weight: var(--weight-semibold); }
.ws-drop__sub { font-size: var(--text-sm); color: var(--fg-muted); }
.ws-bar { flex: 0 0 56px; display: flex; align-items: center; gap: 10px; padding: 0 18px;
    background: var(--bg-surface); border-bottom: 1px solid var(--border-default); }
.ws-bar__title { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.ws-bar__name { font-size: 15px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ws-bar__sub { font-size: var(--text-sm); color: var(--fg-muted); white-space: nowrap; }
.ws-bar__spacer { flex: 1 1 auto; }

.ws-select { height: var(--control-height); padding: 0 26px 0 10px; font-size: var(--text-sm); color: var(--fg-primary);
    border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-surface);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236C7283' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 8px center; -webkit-appearance: none; appearance: none; cursor: pointer; }
.ws-select:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring-focus); }

.ws-seg { display: inline-flex; padding: 2px; gap: 2px; background: var(--bg-sunken); border: 1px solid var(--border-default); border-radius: var(--radius-sm); }
.ws-seg button { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 24px;
    border: 0; border-radius: var(--radius-xs); background: transparent; color: var(--fg-muted); cursor: pointer; }
.ws-seg button:hover { color: var(--fg-primary); }
.ws-seg button.is-active { background: var(--bg-surface); color: var(--accent-fg); box-shadow: var(--shadow-xs); }

.ws-btn { display: inline-flex; align-items: center; gap: 6px; height: var(--control-height); padding: 0 12px;
    border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-surface);
    color: var(--fg-primary); font-size: var(--text-sm); font-weight: var(--weight-medium); cursor: pointer;
    transition: var(--transition-colors); }
.ws-btn:hover { background: var(--bg-hover); }
.ws-btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.ws-btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.ws-btn--danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.ws-btn--danger:hover { filter: brightness(0.95); }

.ws-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.ws-banner { display: flex; align-items: center; gap: 10px; margin: 12px 22px 0; padding: 9px 12px;
    background: var(--danger-bg); border: 1px solid var(--red-100); border-radius: var(--radius-sm);
    color: var(--danger-fg); font-size: var(--text-sm); }
.ws-banner__ic { display: flex; flex-shrink: 0; color: var(--danger); }
.ws-banner__msg { flex: 1 1 auto; }
.ws-banner__x { display: flex; flex-shrink: 0; padding: 2px; background: none; border: 0; cursor: pointer;
    color: var(--fg-muted); border-radius: var(--radius-sm); }
.ws-banner__x:hover { color: var(--fg-primary); background: var(--bg-hover); }
.ws-fail { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
    min-height: 60vh; padding: 40px 22px; text-align: center; }
.ws-fail__ic { display: flex; align-items: center; justify-content: center; width: 76px; height: 76px; margin-bottom: 12px;
    border-radius: var(--radius-xl); background: var(--danger-bg);
    border: 1px solid var(--border-subtle); color: var(--danger); }
.ws-fail h3 { margin: 0; font-size: var(--text-h3); font-weight: var(--weight-semibold); color: var(--fg-primary); }
.ws-fail p { margin: 0 0 14px; font-size: var(--text-sm); color: var(--fg-muted); max-width: 380px; }
.ws-fail__actions { display: flex; gap: 8px; }
.ws-fail__detail { margin-top: 16px; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--fg-faint);
    background: var(--bg-sunken); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: 3px 8px; }
.ws-loading { display: flex; align-items: center; gap: 10px; padding: 48px 22px; color: var(--fg-muted); }
.ws-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
    min-height: 60vh; padding: 40px 22px; text-align: center; }
.ws-empty__ic { display: flex; align-items: center; justify-content: center; width: 76px; height: 76px; margin-bottom: 12px;
    border-radius: var(--radius-xl); background: var(--gradient-violet-wash); border: 1px solid var(--border-subtle); color: var(--accent); }
.ws-empty h3 { margin: 0; font-size: var(--text-h3); font-weight: var(--weight-semibold); color: var(--fg-primary); }
.ws-empty p { margin: 0 0 14px; font-size: var(--text-sm); color: var(--fg-muted); max-width: 360px; }
.ws-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.ws-faint { color: var(--fg-faint); }

/* Recently deleted (trash) view: flat restorable rows, no tiles. */
.ws-trash { display: flex; flex-direction: column; gap: 8px; padding: 4px 0; max-width: 860px; }
.ws-trash__row { display: flex; align-items: center; gap: 12px; padding: 10px 14px;
    border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); background: var(--bg-surface); }
.ws-trash__ic { display: flex; color: var(--fg-faint); }
.ws-trash__name { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--fg-primary);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-trash__meta { margin-left: auto; font-size: var(--text-xs); color: var(--fg-muted); white-space: nowrap; }

/* ---- tiles ---- */
.ws-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(326px, 1fr)); gap: 18px; padding: 22px; }
.ws-tile { display: flex; flex-direction: column; background: var(--bg-surface); border: 1px solid var(--border-default);
    border-radius: var(--radius-md); box-shadow: var(--elevation-card); overflow: hidden; cursor: pointer;
    transition: transform var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard), border-color var(--duration-base) var(--ease-standard); }
.ws-tile:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); transform: translateY(-2px); }
.ws-tile--warn { border-color: var(--amber-100); }

.ws-cover { position: relative; aspect-ratio: 16 / 10; background: var(--bg-canvas); overflow: hidden; }
.ws-cover__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ws-cover__ph { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
    color: #3A3F52; background: radial-gradient(120% 120% at 50% 35%, #181B26 0%, #0E1016 70%); }

.ws-glass { position: absolute; display: inline-flex; align-items: center; gap: 6px; padding: 3px 8px;
    border-radius: var(--radius-full); background: rgba(8, 10, 16, 0.62); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    color: #EAECF3; font-size: 10.5px; line-height: 1; text-transform: uppercase; letter-spacing: var(--tracking-caps); font-weight: 600; }
.ws-glass--tl { top: 9px; left: 9px; }
.ws-glass--tr { top: 9px; right: 9px; text-transform: none; letter-spacing: 0; font-family: var(--font-mono); }
/* Collab (phase 1): "X editing" badge — bottom-left of the tile cover (status=tl, modality=tr, kebab=br). */
.ws-glass--lock { bottom: 9px; left: 9px; max-width: calc(100% - 18px); text-transform: none; letter-spacing: 0;
    background: rgba(180, 83, 9, 0.86); color: #FFF7ED; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ws-glass--lock svg { flex-shrink: 0; }
.ws-dot { width: 6px; height: 6px; border-radius: var(--radius-full); }

.ws-kebab { position: absolute; right: 7px; bottom: 7px; display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border: 0; border-radius: var(--radius-sm); background: rgba(8, 10, 16, 0.55);
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); color: #EAECF3; cursor: pointer; opacity: 0; transition: opacity var(--duration-fast); }
.ws-tile:hover .ws-kebab { opacity: 1; }

.ws-tile__body { display: flex; flex-direction: column; gap: 5px; padding: 13px 15px; }
.ws-tile__title { font-size: 14.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ws-tile__sub { display: flex; align-items: center; gap: 7px; font-size: var(--text-xs); color: var(--fg-muted);
    white-space: nowrap; overflow: hidden; }
.ws-meta-dot { flex-shrink: 0; width: 3px; height: 3px; border-radius: var(--radius-full); background: var(--fg-faint); }
.ws-tag { display: inline-flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-tag svg { color: var(--fg-faint); }
.ws-tile__foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 3px;
    padding-top: 9px; border-top: 1px solid var(--border-subtle); font-size: var(--text-xs); }
.ws-foot__left { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.ws-seg-count { display: inline-flex; align-items: center; gap: 5px; color: var(--fg-secondary); }
.ws-seg-count svg { color: var(--fg-faint); }
/* "+Add AI" in flight (any segment carries a pending marker) — spinner + AI tag on the tile foot / list row. */
.ws-ai, .ws-row__ai { display: inline-flex; align-items: center; gap: 5px; flex-shrink: 0; padding: 1px 8px;
    border-radius: var(--radius-full); background: color-mix(in srgb, var(--accent) 14%, transparent);
    color: var(--accent); font-size: var(--text-xs); font-weight: 600; white-space: nowrap; }
/* Beat `.ws-row__name span` (0,1,1), which would otherwise mute the chip to --fg-muted. */
.ws-row__name .ws-row__ai { color: var(--accent); margin-left: 8px; }
.ws-ai__spin { width: 9px; height: 9px; flex-shrink: 0; border: 1.6px solid color-mix(in srgb, var(--accent) 35%, transparent);
    border-top-color: var(--accent); border-radius: 50%; animation: spin 0.7s linear infinite; }
.ws-tile__date { display: inline-flex; align-items: center; gap: 6px; color: var(--fg-faint); min-width: 0; }
.ws-tile__editor { color: var(--fg-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Collab (phase 1): "X editing" chip in the dense list row name cell. */
.ws-row__lock { display: inline-flex; align-items: center; gap: 4px; margin-left: 8px; padding: 1px 7px;
    border-radius: var(--radius-full); background: rgba(180, 83, 9, 0.14); color: #B45309;
    font-size: var(--text-xs); font-weight: 600; white-space: nowrap; }

/* Collab (phase 1): editor read-only banner — "X is editing this case". Solid dark-amber bar with
   light text + a bright white name, so it reads clearly over the dark editor chrome. */
.collab-banner { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.85rem;
    background: #7C2D12; color: #FDE9C8; font-size: var(--text-sm); font-weight: 500;
    border-bottom: 1px solid rgba(0, 0, 0, 0.25); }
.collab-banner__ic { flex-shrink: 0; color: #FBBF24; }
.collab-banner__msg { flex: 1; }
.collab-banner strong { color: #FFFFFF; font-weight: 700; }
.collab-banner--free { background: #14532D; color: #DCFCE7; }
/* Editor's live-broadcast banner. */
.collab-banner--live { background: #0B3B5E; color: #D6ECFF; }
.collab-banner--live strong { color: #FFFFFF; }
.collab-banner__live { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; background: #EF4444;
    box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.6); animation: collab-pulse 1.6s ease-out infinite; }
@keyframes collab-pulse {
    0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.6); }
    70% { box-shadow: 0 0 0 7px rgba(239, 68, 68, 0); }
    100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); }
}
.collab-banner--free .collab-banner__ic { color: #4ADE80; }
.collab-banner__x { border: 0; background: transparent; color: inherit; cursor: pointer; font-size: 13px; opacity: 0.75; padding: 0 4px; }
.collab-banner__x:hover { opacity: 1; }
/* Phase 3: handoff / request controls inside banners. */
.collab-banner--req { background: #3B2E0B; color: #FDE9C8; }
.collab-banner--req strong { color: #FFFFFF; }
.collab-watcher { display: inline-flex; align-items: center; gap: 5px; margin-left: 8px; }
.collab-banner__btn { border: 1px solid rgba(255,255,255,0.35); background: rgba(255,255,255,0.10); color: inherit;
    cursor: pointer; font-size: 11.5px; font-weight: 600; line-height: 1; padding: 3px 8px; border-radius: var(--radius-full); }
.collab-banner__btn:hover:not(:disabled) { background: rgba(255,255,255,0.22); }
.collab-banner__btn:disabled { opacity: 0.55; cursor: default; }
.collab-banner__btn--ok { background: #16A34A; border-color: #16A34A; color: #FFFFFF; }
.collab-banner__btn--ok:hover:not(:disabled) { background: #15803D; }
.collab-banner__note { margin-left: 8px; opacity: 0.85; font-style: italic; }

/* ---- list ---- */
.ws-table { padding: 0 22px 22px; }
.ws-thead { position: sticky; top: 0; z-index: 1; display: grid; align-items: center; height: 38px; gap: 12px;
    grid-template-columns: 64px minmax(0, 2fr) 116px 104px 96px minmax(0, 1.4fr) 138px;
    background: var(--bg-app); border-bottom: 1px solid var(--border-default); }
.ws-th { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-muted); font-weight: var(--weight-semibold); }
.ws-th--num { text-align: right; }
.ws-th--sort { cursor: pointer; display: inline-flex; align-items: center; gap: 3px; user-select: none; }
.ws-th--num.ws-th--sort { justify-content: flex-end; }
.ws-th--sort:hover { color: var(--fg-primary); }

.ws-row { position: relative; display: grid; align-items: center; height: 60px; gap: 12px;
    grid-template-columns: 64px minmax(0, 2fr) 116px 104px 96px minmax(0, 1.4fr) 138px;
    border-bottom: 1px solid var(--border-subtle); cursor: pointer; transition: background var(--duration-fast); }
.ws-row:hover { background: var(--bg-hover); }
.ws-row__thumb { width: 52px; height: 40px; border-radius: var(--radius-sm); overflow: hidden; background: var(--bg-canvas); }
.ws-row__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ws-row__thumb-ph { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; color: #3A3F52; }
.ws-row__name { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ws-row__name b { font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ws-row__name span { font-size: 11.5px; color: var(--fg-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ws-row__cell { min-width: 0; font-size: var(--text-xs); color: var(--fg-secondary); }
.ws-row__cell .ws-tag svg { color: var(--fg-faint); }
.ws-row__num { text-align: right; font-size: var(--text-sm); color: var(--fg-secondary); }
.ws-row__date { font-size: var(--text-xs); color: var(--fg-faint); }
.ws-row__editor { display: block; color: var(--fg-secondary); }
.ws-kebab--row { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 26px; height: 26px;
    background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; color: var(--fg-muted); opacity: 0; }
.ws-row:hover .ws-kebab--row { opacity: 1; }
.ws-kebab--row:hover { background: var(--bg-active); color: var(--fg-primary); }

.ws-badge { display: inline-flex; align-items: center; padding: 2px 9px; border-radius: var(--radius-full);
    font-size: var(--text-2xs); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-wide); text-transform: uppercase; }
.ws-badge--draft { background: var(--bg-active); color: var(--fg-secondary); }
.ws-badge--inprogress { background: var(--info-bg); color: var(--info-fg); }
.ws-badge--validated { background: var(--success-bg); color: var(--success-fg); }

/* ---- case kebab menu ---- */
.ws-menu { position: absolute; z-index: var(--z-dropdown); right: 8px; top: calc(100% - 4px); min-width: 150px;
    display: flex; flex-direction: column; padding: 4px; background: var(--bg-raised); border: 1px solid var(--border-default);
    border-radius: var(--radius-md); box-shadow: var(--elevation-menu); }
.ws-cover .ws-menu { top: auto; bottom: 40px; }
.ws-menu__item { display: flex; align-items: center; padding: 7px 10px; border: 0; background: transparent; cursor: pointer;
    text-align: left; font-size: var(--text-sm); color: var(--fg-primary); border-radius: var(--radius-sm); }
.ws-menu__item:hover { background: var(--bg-hover); }
.ws-menu__item--danger { color: var(--danger); }
.ws-menu__item--danger:hover { background: var(--danger-bg); }

/* ---- modals ---- */
.ws-scrim { position: fixed; inset: 0; z-index: var(--z-dialog); display: flex; align-items: center; justify-content: center;
    background: var(--scrim); padding: 20px; }
.ws-modal { width: 100%; max-width: 380px; display: flex; flex-direction: column; gap: 12px; padding: 20px;
    background: var(--bg-raised); border-radius: var(--radius-lg); box-shadow: var(--elevation-dialog); }
.ws-modal__head { font-size: var(--text-h3); font-weight: var(--weight-semibold); }
.ws-modal__text { margin: 0; font-size: var(--text-sm); color: var(--fg-secondary); }
.ws-field { display: flex; flex-direction: column; gap: 4px; font-size: var(--text-xs); color: var(--fg-muted); }
.ws-input { height: var(--control-height); padding: 0 10px; font-size: var(--text-sm); color: var(--fg-primary);
    border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-surface); }
.ws-input:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring-focus); }
.ws-modal__acts { display: flex; gap: 8px; margin-top: 4px; }

@media (prefers-reduced-motion: reduce) {
    .ws-tile, .ws-item, .ws-btn, .ws-kebab { transition: none; }
    .ws-tile:hover { transform: none; }
    .pl-side, .pl-backdrop, .pl-bar__menu span { transition: none; }
    .pl--nav-open .pl-nav__btn { animation: none; }
}
