/* ============================================================================
   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("people.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; }
/* For bars with no spacer of their own (settings, platform) — the assistant leads the right-hand group. */
.editor-chatbtn--push { margin-left: auto; }
.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); }
/* Picked in the 3D pane — the row lights up the same way a mouse-over does, so "selected" reads the
   same in both places (Seg.HoveredIsland, set by whichever side started the hover). */
.islands__row--hot { background: var(--bg-hover); border-color: var(--accent); }
.islands__row--hot .islands__del { opacity: 1; }
.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; }
/* 4 columns × 2 rows — CtPresets.All is exactly 8, so the grid is always full and never orphans a
   card on a third row. Adding a 9th preset means re-thinking this, not letting it wrap. */
.ctpreset-picker__grid { display: grid; grid-template-columns: repeat(4, 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); }

/* The 2D transfer-function graph: HU across, the preset's opacity curve up, and the draggable W/L
   window box over it. This is the W/L CONTROL, not decoration — the flat 1D liver gradient strip that
   used to live under it is what got removed. */
.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; }
/* One built vessel tree: which segment it came from, its role, and its own remove. The name takes the slack
   and ellipsises — structure names are long ("liver_vessels") and must not push the role picker off-panel. */
.segpanel__vessel-tree { display: flex; gap: 0.3rem; align-items: center; }
.segpanel__vessel-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-xs); }
.segpanel__vessel-role { width: auto; flex: 0 0 auto; }
.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; }
/* The popover keeps the same 4×2 colormap grid as the inline panel. 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__thumb { aspect-ratio: auto; height: 3.25rem; }
/* the graph already sits under the imgapp gap — drop its own top margin 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); }

/* One line: the W/L readout on the left, whatever the host puts in HeaderEnd on the right (the case
   workspace hangs its volume-rendering switch there). */
.imgapp__wlrow { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; }
.imgapp__wlrow > :not(.imgapp__wlreadout) { flex: 0 0 auto; }
.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; }

/* Window presets for a data-driven modality (MR/PET/NIfTI) — shown INSTEAD of nothing, since the
   Hounsfield preset list means nothing there. One compact row under the transfer-function graph. */
.imgapp__wlpresets { display: flex; gap: 0.3rem; margin-top: 0.4rem; }
.imgapp__wlpreset {
    flex: 1 1 0; min-width: 0; padding: 0.3rem 0.2rem; border-radius: var(--radius-sm);
    border: 1px solid transparent; background: var(--bg-subtle); color: var(--fg-secondary);
    font-size: var(--text-xs); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.imgapp__wlpreset:hover { background: var(--bg-hover); border-color: var(--border-subtle); }
.imgapp__wlpreset.is-active { border-color: var(--accent); background: var(--bg-selected); color: var(--fg-primary); }

/* 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; }
@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; }

/* 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; }

/* ===========================================================================
   8 · AUTH — THE SIGN-IN PAGE
===========================================================================
   THESE RULES WERE INSIDE THE PLATFORM CONSOLE'S BLOCK, which is why they are
   suddenly a section of their own: /platform moved to HQ and eight hundred
   `pl-` lines went with it, and the sign-in page — the one screen every person
   in the estate sees before anything else — was sitting in the middle of them.
   Nothing here is changed; it is the same CSS, lifted out of a neighbourhood it
   never belonged to and given a heading so the next deletion cannot repeat the
   mistake. Login.razor is its only consumer. */

.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, .login-google { 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; }
/* Sentinel that pulls in the next page of cases as it nears the viewport. Needs real height so
   an IntersectionObserver can see it; sits after the grid, never inside it. */
.ws-more { height: 1px; margin: 0 22px 22px; }
.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); }
/* patient sex/age chips, from the DICOM header. flex-shrink:0 so the folder name (which ellipses)
   gives up width first — these are two short words and truncating them would be nonsense. */
.ws-pchip { flex-shrink: 0; display: inline-flex; align-items: center; padding: 0 6px; height: 16px;
    border-radius: var(--radius-full); background: var(--bg-sunken); border: 1px solid var(--border-subtle);
    font-size: var(--text-2xs); font-weight: 600; color: var(--fg-secondary); white-space: nowrap; }
.ws-row__meta { display: flex; align-items: center; gap: 6px; min-width: 0; }
.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; }
}


/* ===========================================================================
   10 · REPORT A PROBLEM
===========================================================================
   THIS BLOCK IS A RESCUE, and worth a line on why. The "Report a problem" button
   and its dialog are app-wide — the Library bar, the case workspace, /settings —
   but their styling lived inside the platform console's stylesheet and leaned on
   `.pl-input`, `.pl-section__hint` and `.pl-actions` for the field, the hint and
   the button row. /platform moved to HQ and took all eight hundred `pl-` lines
   with it, which would have left this dialog rendering as unstyled boxes on
   every page that offers it. So the four rules it actually used are restated
   here under its own names, and it now depends on nothing that can leave. */
.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; }
.report-problem__hint { font-size: var(--text-xs); color: var(--fg-muted); margin: 0 0 4px; }
/* Full-width and readable — the platform textarea this replaces was mono and auto-width. */
.report-problem__note { display: block; width: 100%; box-sizing: border-box; margin: 4px 0 0; min-height: 120px;
    padding: 10px; border: 1px solid var(--border-default); border-radius: var(--radius-sm);
    background: var(--bg-surface); color: var(--fg-primary);
    font-family: var(--font-sans); font-size: var(--text-sm); resize: vertical; }
.report-problem__note:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring-focus); }
.report-problem__actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 12px; }
