:root {
  /* Viewer/app chrome — deep violet-black instead of the old neutral
     grey/teal. #000 stays #000 wherever it's the actual image display
     surface (.viewport-area, .viewport-cell, series thumbnails) — that
     one is left alone everywhere in this file, since a tinted image
     background would be a real window/level regression, not a look. */
  --bg-0: #1a1445;
  --bg-1: #241c52;
  --bg-2: #2b2260;
  --bg-3: #33296c;
  --border: #453a80;
  --text-0: #f2f0fb;
  --text-1: #a79fc7;
  --text-2: #837aa8;
  --accent: #7c5cff;
  --accent-bright: #8b6ef2;
  --accent-dim: #2c2260;
  --accent-border: #5847a8;
  --accent-2: #ff6b5c;
  --on-accent: #ffffff;
  --green: #34d399;
  --amber: #f0a63a;
  --red: #e9553f;
  --radius: 3px;
  /* Only used by the redesigned login/library pages, never by viewer
     chrome — keeps every existing toolbar/panel shape in the viewer
     exactly as it was, per "retain our dicom structure". */
  --radius-lg: 14px;
  --cream: #f5f3fb;
  --cream-ink: #1e1a3a;
  --cream-border: #ded8ef;
  /* Brand wordmark font (logo lockup, nav "RadIQ" links) — the rounded
     geometric bold this app's actual UI text was never meant to run in
     wholesale, so it's scoped to brand elements only via var(--font-brand)
     rather than replacing the base font-family below. Loaded in each
     page's <head> (fonts.googleapis.com) since it's a real webfont, not
     a system one. */
  --font-brand: "Manrope", "Segoe UI", -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;
  font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  background: var(--bg-0);
  color: var(--text-0);
  overflow: hidden;
  user-select: none;
}

.hidden { display: none !important; }

/* ---------- RadIQ login gate — split panel: plain sign-in form on a
   light panel, product panel on a violet/magenta gradient. Only real
   sign-in (Supabase email/password, see radiq-auth-gate.js) — no SSO
   or trust-affiliation copy; the eyebrow/feature pills below name only
   things this app actually does (viewer, saved-scan library, synthetic
   MPR reconstruction). ---------- */
.login-gate {
  position: fixed; inset: 0; z-index: 200;
  display: flex;
  font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;
  user-select: text;
}
.login-panel-form {
  flex: 1 1 46%; min-width: 320px;
  background: var(--cream); color: var(--cream-ink);
  display: flex; align-items: center; justify-content: center;
  padding: 40px 32px;
}
.login-card { width: 100%; max-width: 360px; }
.login-eyebrow {
  font-size: 10.5px; font-weight: 700; color: var(--accent-2);
  text-transform: uppercase; letter-spacing: .14em; margin: 0 0 10px;
}
.login-brand { display: flex; align-items: center; gap: 9px; margin-bottom: 28px; }
.login-brand-text { font-family: var(--font-brand); font-size: 19px; font-weight: 800; color: var(--cream-ink); letter-spacing: -.3px; }
/* Base "IQ"/"Studio" treatment for the wordmark — shared by every lockup
   that uses it (login card/hero, launch screen heading below), not just
   .login-brand-text, so each only needs to override where its background
   isn't the default cream/dark-violet contrast this assumes. */
.brand-iq { color: var(--accent-bright); }
.brand-light { font-weight: 500; color: var(--text-1); }
.login-brand-text .brand-iq { color: var(--accent); }
.login-hero-brand .login-brand-text .brand-iq { color: var(--accent-bright); }
.login-brand-text .brand-light { font-weight: 500; color: #6d658a; }
.login-hero-brand .login-brand-text .brand-light { color: rgba(255,255,255,.6); }
.login-heading { font-size: 28px; font-weight: 800; color: var(--cream-ink); text-align: left; margin: 0 0 8px; letter-spacing: -.02em; }
.login-sub { font-size: 13px; color: #5c5578; text-align: left; margin: 0 0 26px; line-height: 1.5; }
.login-form { display: flex; flex-direction: column; }
.login-label { font-size: 10.5px; font-weight: 700; color: #6d658a; text-transform: uppercase; letter-spacing: .7px; margin: 0 0 6px; }
.login-input {
  width: 100%; padding: 11px 13px; border: 1px solid var(--cream-border); border-radius: 8px;
  font-size: 13.5px; color: var(--cream-ink); font-family: inherit; outline: none;
  background: #ffffff; margin-bottom: 14px; transition: border-color .15s;
}
.login-input::placeholder { color: #a49dbd; }
.login-input:focus { border-color: var(--accent); }
.login-error {
  background: rgba(233,85,63,0.1); color: #c03d2a; font-size: 12px;
  border: 1px solid rgba(233,85,63,0.3);
  padding: 9px 12px; border-radius: 8px; margin-bottom: 14px; line-height: 1.5;
}
.login-submit {
  width: 100%; background: var(--cream-ink); color: #ffffff; border: none; border-radius: 999px;
  padding: 13px 0; font-size: 14px; font-weight: 700; cursor: pointer;
  font-family: inherit;
}
.login-submit:hover { filter: brightness(1.15); }
.login-submit:disabled { opacity: .6; cursor: wait; }
.login-below-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  border-top: 1px solid var(--cream-border); margin-top: 18px; padding-top: 14px;
  font-size: 12px; flex-wrap: wrap;
}
.login-below-row a { color: #6d658a; text-decoration: none; }
.login-below-row a:hover { color: var(--cream-ink); text-decoration: underline; }
.login-below-row .login-sso-note { color: #9791ac; }
.login-footer { font-size: 11.5px; color: #8a82a3; text-align: left; margin: 20px 0 0; line-height: 1.5; }

.login-panel-hero {
  flex: 1 1 54%; min-width: 320px; position: relative; overflow: hidden;
  background: radial-gradient(ellipse at 12% 10%, #33236f 0%, transparent 55%),
              radial-gradient(ellipse at 90% 95%, #2a2260 0%, transparent 60%),
              linear-gradient(160deg, #1a1445 0%, #211a4e 55%, #241a52 100%);
  color: #fff;
  display: flex; flex-direction: column; justify-content: flex-start;
  gap: 26px;
  padding: 40px 48px 32px;
  overflow-y: auto;
}
.login-hero-brand { display: flex; align-items: center; gap: 9px; }
.login-hero-brand .login-brand-text { color: #fff; }
.login-hero-eyebrow-pill {
  display: inline-flex; align-items: center; gap: 8px; align-self: flex-start;
  font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(255,255,255,.7); border: 1px solid rgba(255,255,255,.2); border-radius: 999px;
  padding: 6px 13px 6px 10px; background: rgba(255,255,255,.04);
}
.login-hero-eyebrow-pill .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent-2); flex-shrink: 0; }
.login-hero-dots { display: none; }
.login-hero-heading { font-size: 40px; font-weight: 800; line-height: 1.14; margin: 0; max-width: 520px; letter-spacing: -.02em; }
.login-hero-sub { font-size: 14.5px; line-height: 1.65; color: rgba(242,240,251,.72); max-width: 500px; margin: 0; }

.login-hero-pills { display: none; }

/* ---------- Feature grid (2x3), between the headline and the bottom
   tag row — static marketing content, no JS wiring needed. ---------- */
.login-feature-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(2, 1fr);
  border: 1px solid rgba(255,255,255,.12); border-radius: var(--radius-lg);
  background: rgba(255,255,255,.02); overflow: hidden;
}
.login-feature-card {
  padding: 16px 16px 18px; border-right: 1px solid rgba(255,255,255,.1); border-bottom: 1px solid rgba(255,255,255,.1);
  min-width: 0;
}
.login-feature-card:nth-child(3n) { border-right: none; }
.login-feature-card:nth-child(n+4) { border-bottom: none; }
.login-feature-tag {
  display: inline-block; font-size: 10px; font-weight: 800; letter-spacing: .04em;
  background: var(--accent-2); color: #241445; border-radius: 5px; padding: 2px 7px; margin-bottom: 10px;
}
.login-feature-title { font-size: 13.5px; font-weight: 700; color: #fff; margin: 0 0 5px; letter-spacing: -.01em; }
.login-feature-desc { font-size: 11.5px; line-height: 1.5; color: rgba(242,240,251,.62); margin: 0; }

.login-hero-tagrow {
  border-top: 1px solid rgba(255,255,255,.12); padding-top: 16px; margin-top: auto;
  display: flex; flex-wrap: wrap; gap: 6px 0; font-size: 10.5px; letter-spacing: .08em;
  color: rgba(242,240,251,.42); text-transform: uppercase;
}
.login-hero-tagrow span:not(:last-child)::after { content: " \00b7 "; opacity: .6; }

.login-hero-foot { display: none; }

@media (max-width: 980px) {
  .login-feature-grid { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(3, 1fr); }
  .login-feature-card:nth-child(3n) { border-right: 1px solid rgba(255,255,255,.1); }
  .login-feature-card:nth-child(2n) { border-right: none; }
  .login-feature-card:nth-child(n+4) { border-bottom: 1px solid rgba(255,255,255,.1); }
  .login-feature-card:nth-child(n+5) { border-bottom: none; }
}

@media (max-width: 760px) {
  .login-panel-hero { display: none; }
  .login-panel-form { flex: 1 1 100%; }
}

/* ---------- Dropzone ---------- */
.dropzone {
  height: 100vh;
  width: 100vw;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(ellipse at top, #1c1533 0%, #0b0815 60%);
  cursor: pointer;
}
.dropzone.dragover .dropzone-inner {
  border-color: var(--accent);
  background: var(--bg-2);
}
.dropzone-inner {
  text-align: center;
  padding: 64px 72px;
  border: 2px dashed var(--border);
  border-radius: 16px;
  max-width: 560px;
  transition: border-color .15s, background .15s;
}
.dz-icon { margin-bottom: 8px; border-radius: 13px; } /* icon now carries its own dark tile fill — no currentColor tint needed */
.dropzone-inner h1 { font-family: var(--font-brand); font-size: 22px; font-weight: 800; color: var(--text-0); letter-spacing: -.3px; margin: 12px 0 8px; }
.dropzone-inner p { color: var(--text-1); font-size: 14px; line-height: 1.6; margin: 0 0 24px; }
.dz-buttons { display: flex; gap: 12px; justify-content: center; }
.dz-buttons-secondary { margin-top: 10px; }
.dz-hint { min-height: 20px; font-size: 12.5px; color: var(--accent); margin-top: 18px !important; }

/* Kept in the layout (not display:none) so Safari/WebKit reliably opens the
   native picker on .click() — visually invisible and unreachable instead. */
.visually-hidden-input {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

.btn {
  background: var(--bg-3);
  color: var(--text-0);
  border: 1px solid var(--border);
  padding: 10px 20px;
  border-radius: var(--radius);
  font-size: 13.5px;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.btn:hover { background: #2c2547; border-color: #453a72; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
.btn.primary:hover { background: #b07bff; }

/* ---------- App shell ---------- */
.app { height: 100vh; width: 100vw; display: flex; flex-direction: column; }

.menubar {
  display: flex;
  height: 26px;
  min-height: 26px;
  background: #140f24;
  border-bottom: 1px solid var(--border);
  align-items: center;
  justify-content: space-between;
  padding: 0 12px;
  font-size: 11.5px;
  color: var(--text-1);
}
.menubar-items { display: flex; gap: 16px; }
.menubar-items span { cursor: pointer; }
.menubar-items span:hover { color: var(--text-0); }
.menubar-brand { font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--text-2); }
.menubar-brand b { color: var(--accent); font-weight: 700; }
.menubar-right { display: flex; align-items: center; gap: 12px; }

/* On a phone-width viewport there isn't enough room for every menubar
   button (Save/Video→Stack/Record via Camera/Region→Stack/Record/account/
   logout) at once — without this, the ones that don't fit are simply
   pushed off-screen with no way to reach them at all (this is what made
   the new camera-record button invisible on a real phone, not a network
   issue). Letting the bar scroll horizontally keeps every button reachable
   via a swipe instead of silently hiding some of them; the taller min-height
   and bigger touch targets make that swipe/tap actually usable on a phone
   screen, where the desktop-tuned 26px-tall row is too cramped to tap
   reliably. */
@media (max-width: 760px) {
  .menubar {
    height: auto;
    min-height: 40px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .menubar::-webkit-scrollbar { display: none; }
  .menubar-items { flex-shrink: 0; }
  .menubar-right { flex-shrink: 0; gap: 8px; }
  .menubar-record-btn, .menubar-save-scan, .menubar-logout {
    padding-top: 7px; padding-bottom: 7px; /* bigger tap target than the desktop sizing */
  }
}
.menubar-account { font-size: 11px; color: var(--text-2); }
.menubar-logout {
  background: none; border: 1px solid var(--border); color: var(--text-1);
  font-size: 10.5px; padding: 2px 8px; border-radius: var(--radius); cursor: pointer;
}
.menubar-logout:hover { color: var(--text-0); border-color: var(--text-1); }

.toolbar {
  height: 46px;
  min-height: 46px;
  background: linear-gradient(#241b3f, #171129);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 12px;
  overflow-x: auto;
}
.tb-group { display: flex; align-items: center; gap: 2px; }
.tb-divider { width: 1px; height: 24px; background: var(--border); margin: 0 4px; flex-shrink: 0; }
.tb-label { font-size: 11px; color: var(--text-2); margin-right: 4px; }

.tb-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-1);
  padding: 4px 7px;
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: .04em;
  line-height: 1;
  flex-shrink: 0;
}
.tb-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.tb-btn:hover { background: var(--bg-3); color: var(--text-0); }
.tb-btn.active { background: var(--accent-dim); color: var(--accent); border-color: var(--accent-border); }
/* #btnBackToMyScans is an <a>, not a <button> — .tb-btn's other rules
   (display:flex, padding, etc.) apply to it identically, it just also
   needs the anchor default underline turned off. */
a.tb-btn { text-decoration: none; }

.tb-presets select, select#wlPreset, select#mipSlabThickness {
  background: var(--bg-3);
  color: var(--text-0);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 6px 8px;
  font-size: 12.5px;
}

.tb-load { margin-left: auto; flex-shrink: 0; }

.compare-hint {
  background: var(--accent-dim);
  color: var(--accent);
  border-bottom: 1px solid var(--accent-border);
  font-size: 12.5px;
  padding: 7px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}
#compareHintCount { color: var(--text-0); font-weight: 600; }
.btn-link {
  background: none; border: none; color: var(--accent); cursor: pointer;
  font-size: 12.5px; text-decoration: underline; padding: 0; margin-left: auto;
}
.btn-link:hover { color: var(--accent-bright); }

.body { flex: 1; display: flex; min-height: 0; position: relative; }

/* ---------- Series panel ---------- */
.series-panel {
  width: 220px;
  min-width: 220px;
  background: var(--bg-1);
  border-right: 1px solid var(--border);
  overflow-y: auto;
  padding-bottom: 20px;
  transition: width .18s ease, min-width .18s ease, padding .18s ease;
}
.series-panel.collapsed {
  width: 0;
  min-width: 0;
  padding-bottom: 0;
  border-right: none;
  overflow: hidden;
}

/* Small tab docked on the panel/viewport seam so it stays reachable whether
   the panel is open or collapsed — sits outside .series-panel itself so its
   own overflow:hidden while collapsing never clips the button. */
.panel-toggle-btn {
  position: absolute;
  top: 50%;
  left: 220px;
  transform: translate(-50%, -50%);
  width: 18px;
  height: 44px;
  border-radius: 3px;
  border: 1px solid var(--border);
  background: var(--bg-1);
  color: var(--text-2);
  cursor: pointer;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  padding: 0;
  transition: left .18s ease, color .12s, border-color .12s;
}
.panel-toggle-btn:hover { color: var(--text-0); border-color: #5c4f8a; }
.series-panel.collapsed + .panel-toggle-btn { left: 0; }
.panel-tabs {
  display: flex;
  border-bottom: 1px solid var(--border);
}
.ptab {
  flex: 1;
  text-align: center;
  padding: 9px 0;
  font-size: 11.5px;
  color: var(--text-2);
  cursor: pointer;
  border-bottom: 2px solid transparent;
}
.ptab.active { color: var(--accent); border-bottom-color: var(--accent); }

.panel-header {
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-2);
  padding: 12px 14px 6px;
  font-weight: 600;
}
.study-info { padding: 10px 14px 10px; font-size: 12px; color: var(--text-1); line-height: 1.7; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.study-info b { color: var(--text-0); font-weight: 600; font-size: 13px; }

.series-list { display: flex; flex-direction: column; gap: 1px; padding: 0 10px; }
.series-item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 4px 12px;
  cursor: pointer;
  border-bottom: 1px solid #241d3f;
}
.series-item:hover .series-thumb { border-color: #5c4f8a; }
.series-item.active .series-thumb { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.series-item.active .s-desc { color: var(--accent); }

.series-item.compare-pick-a .series-thumb { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.series-item.compare-pick-a .s-desc { color: var(--accent); }
.series-item.compare-pick-b .series-thumb { border-color: var(--amber); box-shadow: 0 0 0 1px var(--amber); }
.series-item.compare-pick-b .s-desc { color: var(--amber); }
.series-item .compare-badge {
  display: none;
  position: absolute;
  top: 6px; left: 6px;
  width: 18px; height: 18px;
  border-radius: 50%;
  font-size: 10.5px;
  font-weight: 700;
  align-items: center;
  justify-content: center;
  color: var(--on-accent);
  z-index: 2;
}
.series-item.compare-pick-a .compare-badge { display: flex; background: var(--accent); }
.series-item.compare-pick-b .compare-badge { display: flex; background: var(--amber); }

.series-remove-btn {
  position: absolute;
  top: 6px; right: 6px;
  width: 18px; height: 18px;
  border-radius: 50%;
  border: none;
  background: rgba(0,0,0,.55);
  color: #fff;
  font-size: 12px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 3;
  opacity: 0;
  transition: opacity .12s, background .12s;
}
.series-item:hover .series-remove-btn,
.series-remove-btn:focus-visible { opacity: 1; }
.series-remove-btn:hover { background: var(--danger, #c0392b); }

.study-group-header {
  padding: 10px 4px 4px;
  font-size: 10px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-2);
  border-top: 1px solid var(--border);
  margin-top: 4px;
}
.study-group-header:first-child { border-top: none; margin-top: 0; }
.series-thumb {
  width: 100%;
  aspect-ratio: 1;
  border-radius: 2px;
  background: #000;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  border: 1px solid var(--border);
  position: relative;
}
.series-thumb::after {
  content: "+";
  position: absolute; inset: auto 0 0 0; top: 0; left: 0; right: 0; bottom: 0;
  background:
    linear-gradient(to right, transparent 49.4%, rgba(255,255,255,.35) 49.4%, rgba(255,255,255,.35) 50.6%, transparent 50.6%),
    linear-gradient(to bottom, transparent 49.4%, rgba(255,255,255,.35) 49.4%, rgba(255,255,255,.35) 50.6%, transparent 50.6%);
  color: transparent;
  pointer-events: none;
  opacity: .5;
}
.series-thumb canvas, .series-thumb img { width: 100%; height: 100%; object-fit: cover; position: relative; z-index: 1; }
.series-meta { min-width: 0; }
.series-meta .s-desc { font-size: 12px; color: var(--text-0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.series-meta .s-sub { font-size: 10.5px; color: var(--text-2); margin-top: 2px; }

/* ---------- Viewport area ---------- */
.viewport-area { flex: 1; background: #000; min-width: 0; position: relative; }
.viewport-grid {
  height: 100%;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 2px;
  background: var(--border);
}
.viewport-grid.layout-1x1 { grid-template-columns: 1fr; grid-template-rows: 1fr; }
.viewport-grid.layout-1x1 .viewport-cell { display: none; }
.viewport-grid.layout-1x1 #cell-axial { display: block; }

.viewport-grid.layout-compare { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr; }
.viewport-grid.layout-compare .viewport-cell { display: none; }
.viewport-grid.layout-compare #cell-compareA,
.viewport-grid.layout-compare #cell-compareB { display: block; }

/* Double-click any image pane to expand it to fill the whole viewport area;
   double-click again (or select a different layout) to restore. Works on
   top of whichever layout (1x1 / MPR / compare) is currently active. */
.viewport-grid.pane-maximized .viewport-cell { display: none; }
.viewport-grid.pane-maximized .viewport-cell.maximized {
  display: block;
  grid-column: 1 / -1;
  grid-row: 1 / -1;
}

/* Drag a series thumbnail from the left panel onto a pane to load it there. */
.viewport-cell.drop-target::after {
  content: "";
  position: absolute;
  inset: 6px;
  border: 2px dashed var(--accent);
  border-radius: 4px;
  z-index: 6;
  pointer-events: none;
  background: rgba(157, 107, 255, 0.10);
}

.viewport-cell {
  position: relative;
  background: #000;
  overflow: hidden;
  min-width: 0;
  min-height: 0;
}
.viewport-cell.focused { outline: 2px solid var(--accent); outline-offset: -2px; }
.cs-viewport { width: 100%; height: 100%; position: relative; touch-action: none; }
.cs-viewport canvas { outline: none; }
.crosshair-canvas {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  z-index: 4; pointer-events: none;
}
.crosshair-canvas.hidden { display: none; }
/* Rotation-handle hit targets for the axial pane's oblique crosshair
   lines (see positionAxialHandleEls/wireAxialRotationHandles in
   app.js). Deliberately small, real DOM elements rather than making
   the whole crosshair-axial canvas interactive — that earlier approach
   also swallowed the window/level drag, pan, zoom and scroll-wheel
   events meant for the real Cornerstone viewport underneath. */
.synth-axial-handle {
  position: absolute; width: 18px; height: 18px; z-index: 6;
  border-radius: 50%; cursor: grab; pointer-events: auto;
}
.synth-axial-handle.hidden { display: none; }
/* Per-pane manual window/level readout for the coronal/sagittal oblique
   panes (see wireObliqueWindowHandles/updateObliqueWinLabel in app.js) —
   same corner-label convention as the real Cornerstone overlay on the
   axial pane, just a plain positioned div since these panes are a plain
   canvas, not a Cornerstone viewport. */
.synth-oblique-winlabel {
  position: absolute; left: 8px; bottom: 8px; z-index: 6;
  font: 11px/1.3 var(--mono-font, monospace); color: #f5c344;
  text-shadow: 0 1px 2px rgba(0,0,0,0.9); pointer-events: none;
}
.synth-oblique-winlabel.hidden { display: none; }
.vp-stretch-wrap {
  width: 100%; height: 100%; position: relative;
  transform-origin: center center;
}
/* Oblique coronal/sagittal reslice — a plain canvas we draw into
   directly (see renderObliqueCanvas in app.js), replacing the
   Cornerstone viewport for these two panes while the synthetic MPR
   view's rotatable crosshair lines are in use. The pixel buffer is
   deliberately small (sample width x real frame count); CSS stretches
   it to fill the panel, same "not to true scale without the optional
   spacing field" caveat as the rest of the synthetic reconstruction. */
.oblique-canvas {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  z-index: 3; object-fit: contain; /* preserve the buffer's aspect ratio rather than stretching to fill */
}
.oblique-canvas.hidden { display: none; }

/* Reformat-angle dials on the coronal/sagittal panes (see
   ensureObliqueDialEls/wireObliqueRotationHandles in app.js) — lets
   either oblique angle be dragged from any of the three panes, not
   just via the axial pane's own crosshair-line handles. These are
   small self-contained widgets (not tied to the oblique canvas's own
   tiny, non-square pixel buffer) rather than a line drawn through the
   reformatted image itself: the reformat's own axes are (distance
   along its cut line) x (frame depth), not a real 2D spatial plane, so
   there's no anatomically meaningful position for a second plane's
   line inside it — a small angle dial says "this adjusts an angle"
   honestly instead of implying a spatial crossing that isn't real. */
.synth-oblique-dial {
  position: absolute; top: 8px; width: 26px; height: 26px; z-index: 6;
  border-radius: 50%; cursor: grab; pointer-events: auto;
  background: rgba(11, 8, 21, 0.55); border: 1.5px solid;
  box-sizing: border-box;
}
.synth-oblique-dial.hidden { display: none; }
.synth-oblique-dial.dragging { background: rgba(11, 8, 21, 0.8); }
.synth-oblique-dial[data-axis="coronal"] { right: 42px; color: rgba(230, 180, 40, 0.95); border-color: rgba(230, 180, 40, 0.9); }
.synth-oblique-dial[data-axis="sagittal"] { right: 8px; color: rgba(41, 194, 214, 0.95); border-color: rgba(41, 194, 214, 0.9); }
.synth-oblique-dial-needle {
  position: absolute; left: 50%; top: 50%; width: 2px; height: 10px;
  margin-left: -1px; background: currentColor; transform-origin: 50% 0%;
  pointer-events: none;
}

.vp-label {
  position: absolute; top: 8px; left: 8px;
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  color: var(--accent); z-index: 5; pointer-events: none;
  text-shadow: 0 1px 3px #000;
}
.vp-overlay {
  position: absolute; z-index: 5; font-size: 10.5px; color: #d8dde5;
  line-height: 1.6; pointer-events: none; white-space: pre; font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 2px #000;
}
.vp-overlay.top-left { top: 26px; left: 8px; }
.vp-overlay.bottom-left { bottom: 26px; left: 8px; }
.vp-overlay.bottom-right { bottom: 26px; right: 8px; text-align: right; }

.vp-maximize-btn {
  position: absolute; top: 6px; right: 6px; z-index: 6;
  width: 26px; height: 26px; border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.45); border: 1px solid rgba(255,255,255,.12);
  color: var(--text-1); cursor: pointer;
  opacity: 0; transition: opacity .12s ease, background .12s ease, color .12s ease;
}
.vp-maximize-btn svg { width: 14px; height: 14px; display: block; }
.viewport-cell:hover .vp-maximize-btn,
.viewport-cell.maximized .vp-maximize-btn { opacity: 1; }
.vp-maximize-btn:hover { background: rgba(0,0,0,.7); color: var(--text-0); border-color: var(--accent); }

.vp-datebar {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  height: 22px;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 8px;
  font-size: 10.5px;
  background: rgba(0,0,0,.55);
  color: var(--amber);
  pointer-events: none;
}
.vp-datebar.is-prior { color: var(--red); }
.vp-datebar .db-arrow { color: var(--text-1); }

.patient-card {
  height: 100%; width: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; color: var(--text-1); font-size: 12px; text-align: center; padding: 20px;
  background: radial-gradient(ellipse at center, #101318 0%, #000 100%);
}
.patient-card .pc-name { font-size: 16px; color: var(--text-0); font-weight: 600; }
.patient-card .pc-row { color: var(--text-2); }
.patient-card .pc-row b { color: var(--text-1); font-weight: 500; }

/* ---------- Educational panel ---------- */
.edu-panel {
  width: 260px;
  min-width: 260px;
  background: var(--bg-1);
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: margin-right .18s ease, opacity .18s ease;
}
.edu-panel.collapsed {
  width: 0;
  min-width: 0;
  border-left: none;
  margin-right: -260px;
  opacity: 0;
  pointer-events: none;
}
.edu-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.edu-close-btn {
  background: none;
  border: none;
  color: var(--text-2);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
}
.edu-close-btn:hover { color: var(--text-0); }
.edu-reopen-tab {
  display: none;
  position: absolute;
  right: 0;
  top: 90px;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-right: none;
  color: var(--text-2);
  border-radius: var(--radius) 0 0 var(--radius);
  padding: 10px 6px;
  cursor: pointer;
  writing-mode: vertical-rl;
  text-orientation: mixed;
  font-size: 10.5px;
  letter-spacing: .06em;
  z-index: 5;
}
.edu-reopen-tab:hover { color: var(--accent); border-color: var(--accent-dim); }
.edu-reopen-tab.visible { display: block; }
.edu-content { padding: 0 14px; overflow-y: auto; font-size: 12px; line-height: 1.6; color: var(--text-1); flex-shrink: 0; max-height: 46%; }
.edu-content p { margin: 0 0 14px; }
.edu-content strong { color: var(--text-0); font-size: 12.5px; }
.status-log {
  flex: 1; overflow-y: auto; padding: 6px 14px 14px; font-size: 11px; color: var(--text-2);
  font-family: ui-monospace, "SF Mono", Menlo, monospace; display: flex; flex-direction: column-reverse;
}
.status-log div { padding: 3px 0; border-bottom: 1px solid #241d3f; }

/* ---------- HU calibration (estimated) ----------
   Non-blocking floating panel (unlike .modal-overlay) — the user needs
   to keep click-dragging on the viewport underneath while this is open.
   See setHUToolMode/wireHUCalibrationTool/renderHUCalibPanel in app.js. */
.hu-calib-panel {
  position: fixed; top: 70px; right: 280px; z-index: 20;
  width: 280px; max-height: 60vh; overflow-y: auto;
  background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 8px 28px rgba(0,0,0,.4);
}
.hu-calib-panel.hidden { display: none; }
.hu-calib-panel .panel-header { display: flex; align-items: center; justify-content: space-between; }
.hu-calib-body { padding: 0 14px 14px; font-size: 12px; color: var(--text-1); }
.hu-calib-hint { line-height: 1.5; color: var(--text-2); margin: 0 0 10px; }
.hu-calib-body select, .hu-calib-body .btn { width: 100%; margin-top: 6px; }
.hu-calib-point-list { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
.hu-calib-point {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: #201a38; border: 1px solid #2a2350; border-radius: 6px; padding: 6px 8px; line-height: 1.4;
}
.hu-calib-empty { color: var(--text-2); font-style: italic; padding: 8px 0; }
.hu-calib-remove {
  background: none; border: none; color: var(--text-2); cursor: pointer; font-size: 15px; line-height: 1; flex-shrink: 0;
}
.hu-calib-remove:hover { color: #f2545b; }
.hu-calib-summary { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); color: var(--text-0); font-weight: 600; }

.hu-sample-box {
  position: fixed; top: 70px; right: 280px; z-index: 20;
  background: var(--bg-1); border: 1px solid var(--accent-dim, var(--border)); border-radius: var(--radius);
  padding: 10px 14px; font-size: 13px; color: var(--text-0); font-weight: 600;
  box-shadow: 0 8px 28px rgba(0,0,0,.4);
}
.hu-sample-box.hidden { display: none; }

/* ---------- Loading overlay ---------- */
.loading-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(6,7,9,.85);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px;
}
.spinner {
  width: 36px; height: 36px; border-radius: 50%;
  border: 3px solid #2c2547; border-top-color: var(--accent);
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
#loadingText { font-size: 13px; color: var(--text-1); }

/* scrollbars */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #2c2547; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #5c4f8a; }

/* ---------- My Scans panel ---------- */
.my-scans-panel {
  width: 100%; max-width: 640px; margin: 28px auto 0; padding: 18px 22px;
  border: 1px solid var(--border, #EBEDF3); border-radius: 12px; background: rgba(255,255,255,0.02);
}
.my-scans-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.my-scans-header h2 { font-size: 14px; margin: 0; color: var(--text-1, #6B7280); text-transform: uppercase; letter-spacing: .04em; }
.my-scans-empty { font-size: 12.5px; color: var(--text-2, #6B7280); margin: 6px 0; }
.my-scans-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; max-height: 260px; overflow-y: auto; }
.my-scans-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-radius: 8px; border: 1px solid transparent; cursor: pointer;
  background: rgba(255,255,255,0.03);
}
.my-scans-item:hover { border-color: var(--accent-dim, #9B8BF7); background: rgba(155,139,247,0.08); }
.my-scans-item-main { display: flex; flex-direction: column; gap: 2px; overflow: hidden; }
.my-scans-item-label { font-size: 13px; color: var(--text-0, #1A1D3A); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.my-scans-item-meta { font-size: 11px; color: var(--text-2, #6B7280); }
.my-scans-item-delete { background: none; border: none; color: var(--text-2, #6B7280); cursor: pointer; font-size: 14px; padding: 4px 8px; }
.my-scans-item-delete:hover { color: #E85DA3; }
.btn.small { padding: 4px 8px; font-size: 12px; }

/* ---------- Save-to-My-Scans / generic modal ---------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 200; background: rgba(6,7,9,.7);
  display: flex; align-items: center; justify-content: center;
}
.modal-overlay.hidden { display: none; }
.modal-card {
  width: 380px; max-width: 90vw; background: var(--bg-1); color: var(--text-0);
  border: 1px solid var(--border); border-radius: var(--radius); padding: 22px 24px; box-shadow: 0 20px 60px rgba(0,0,0,.5);
  /* Without this, a dialog whose content is taller than the viewport
     (e.g. Video -> Stack's slice-thickness/pixel-spacing/window-level
     form, or Camera Record's preview + guide + stats) just overflows off
     both the top AND bottom of the screen — .modal-overlay centers it
     with no scroll of its own, so on a short mobile viewport the
     Build/Continue button at the bottom becomes completely unreachable.
     Capping height and scrolling INSIDE the card keeps it fully visible
     (and centered) at any viewport height, phone included. This was
     already applied ad hoc to a couple of specific dialogs
     (.region-stack-card, .camera-record-card); moving it to the shared
     base class here means every modal gets it, not just the ones that
     happened to get flagged. */
  max-height: 90vh; overflow-y: auto;
}
.modal-card h2 { font-size: 15px; font-weight: 600; margin: 0 0 6px; }
.modal-sub { font-size: 12.5px; color: var(--text-1); margin: 0 0 16px; line-height: 1.5; }
.modal-status { font-size: 12px; min-height: 16px; margin: 8px 0 0; color: var(--text-1); font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.modal-status.error { color: var(--red); }
.modal-buttons { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }

/* ---------- Save-to-My-Scans dialog: key image + tags ---------- */
.save-scan-key-image-row { margin: 0 0 14px; }
.save-scan-key-image-preview {
  display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: contain;
  background: #000; border: 1px solid var(--border); border-radius: 8px; margin-bottom: 8px;
}
.save-scan-key-image-slider { width: 100%; }
.save-scan-tags-row { margin: 0 0 16px; }
.save-scan-tags-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.save-scan-tags-chips:empty { margin: 0; }
.save-scan-tag-chip {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600;
  color: var(--text-0); background: var(--bg-2); border: 1px solid var(--border);
  border-radius: 999px; padding: 3px 6px 3px 10px;
}
.save-scan-tag-chip button {
  all: unset; cursor: pointer; line-height: 1; color: var(--text-1); padding: 2px 4px;
}
.save-scan-tag-chip button:hover { color: var(--red); }

/* ---------- PHI review dialog ---------- */
.phi-review-card { width: 760px; }
/* Single-preview redaction review (radiq-redaction-review.js) — one image,
   not a multi-card grid, so this is deliberately a plain block layout
   rather than reusing .phi-review-grid's multi-column auto-fill (which was
   splitting the canvas/caption/buttons into separate narrow columns and
   squeezing the preview image down to a fraction of its width). */
.redaction-review-single {
  display: flex; flex-direction: column; gap: 10px;
  max-height: 65vh; overflow-y: auto; padding: 2px;
}
.redaction-review-single .phi-canvas-wrap { max-width: 100%; }
/* Three-plane redaction marking (radiq-volume-redact-ui.js) — one panel
   per axis, each its own labeled canvas/box-layer pair, stacked on narrow
   screens and side-by-side once there's room. */
.volume-redact-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
  max-height: 60vh; overflow-y: auto; padding: 2px;
}
@media (max-width: 640px) { .volume-redact-grid { grid-template-columns: 1fr; } }
.volume-redact-panel { display: flex; flex-direction: column; gap: 6px; }
.volume-redact-panel-label { font-size: 11px; font-weight: 600; color: var(--text-1); }
.volume-redact-panel .phi-canvas-wrap { max-width: 100%; }
.phi-review-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 14px; max-height: 52vh; overflow-y: auto; padding: 2px;
}
.phi-review-item {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: #000; padding: 8px; display: flex; flex-direction: column; gap: 6px;
}
.phi-review-item.is-clean { border-color: var(--border); }
.phi-review-item.needs-attention { border-color: var(--amber); }
.phi-item-label { font-size: 11px; font-weight: 600; color: var(--text-1); display: flex; justify-content: space-between; align-items: center; }
.phi-canvas-wrap {
  position: relative; width: 100%; background: #000; border-radius: 4px; overflow: hidden;
  cursor: crosshair; user-select: none; touch-action: none;
}
.phi-canvas-wrap canvas.phi-review-canvas { display: block; width: 100%; height: auto; }
.phi-box-layer { position: absolute; inset: 0; }
.phi-box {
  position: absolute; border: 2px solid var(--red); background: rgba(224, 71, 71, 0.22);
  cursor: pointer; box-sizing: border-box;
}
.phi-box::after {
  content: "\2715"; position: absolute; top: -1px; right: -1px; transform: translate(50%, -50%);
  width: 14px; height: 14px; border-radius: 50%; background: var(--red); color: #fff;
  font-size: 9px; line-height: 14px; text-align: center; opacity: 0; transition: opacity .1s;
}
.phi-box:hover::after { opacity: 1; }
.phi-box.manual { border-color: var(--accent); background: rgba(157, 107, 255, 0.22); }
.phi-box.removed { display: none; }
.phi-box.suggestion {
  border: 2px dashed var(--text-1); background: rgba(255, 255, 255, 0.06); cursor: copy;
}
.phi-box.suggestion::after { content: "+"; background: var(--green); }
.phi-box.suggestion:hover { border-color: var(--green); background: rgba(70, 200, 120, 0.15); }
.phi-draw-rect {
  position: absolute; border: 2px dashed var(--accent); background: rgba(157, 107, 255, 0.15);
  pointer-events: none; box-sizing: border-box;
}
.phi-item-note { font-size: 10.5px; color: var(--text-1); line-height: 1.4; }
.phi-item-note.warn { color: var(--amber); }
.phi-item-note.ok { color: var(--green); }
.phi-item-actions { display: flex; justify-content: flex-end; }
.phi-clear-btn {
  font-size: 10.5px; color: var(--text-1); background: none; border: 1px solid var(--border);
  border-radius: 4px; padding: 2px 7px; cursor: pointer;
}
.phi-clear-btn:hover { color: var(--text-0); border-color: var(--text-1); }

.menubar-save-scan {
  background: var(--accent); color: var(--on-accent); border: none; border-radius: var(--radius);
  font-size: 11px; font-weight: 600; padding: 5px 10px; cursor: pointer; margin-right: 4px;
}
.menubar-save-scan:hover { filter: brightness(1.08); }
.menubar-save-scan.hidden, .menubar-save-scan:disabled { opacity: .4; cursor: not-allowed; }

/* ---------- Launch-screen nav (My Scans / Upload) ---------- */
.launch-nav {
  position: fixed; top: 16px; right: 20px; z-index: 5;
  display: flex; gap: 6px;
}
.launch-nav-link {
  font-size: 12px; color: var(--text-1); text-decoration: none; padding: 7px 14px;
  border-radius: var(--radius); border: 1px solid var(--border); background: var(--bg-1);
}
.launch-nav-link:hover { color: var(--accent); border-color: var(--accent-dim); }

/* ---------- Screen record / snapshot dialog ---------- */
.record-card { width: 440px; }
.record-checklist { list-style: none; margin: 0 0 4px; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.record-checklist li label { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--text-0); cursor: pointer; }
.record-checklist input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.record-live { color: var(--red); font-size: 12.5px; font-weight: 600; margin: 0 0 8px; }
.record-live::before { content: ''; }

.menubar-record-btn {
  background: var(--bg-3); color: var(--text-0); border: 1px solid var(--border); border-radius: var(--radius);
  font-size: 11px; font-weight: 600; padding: 5px 10px; cursor: pointer; margin-right: 4px;
}
.menubar-record-btn:hover { border-color: var(--red); color: var(--red); }

/* ---------- Record dialog: unverified-frame override ---------- */
.record-override {
  display: flex; align-items: flex-start; gap: 8px; font-size: 12px; color: var(--text-1);
  line-height: 1.5; margin: 4px 0 10px; cursor: pointer;
}
.record-override input[type="checkbox"] { width: 14px; height: 14px; margin-top: 2px; accent-color: var(--amber); cursor: pointer; flex-shrink: 0; }
.record-override-warn { color: var(--amber); }

/* ---------- Video -> pseudo-stack dialog ---------- */
.video-stack-card { width: 480px; }
.video-stack-canvas {
  display: block; width: 100%; max-width: 440px; height: auto; margin: 4px auto 0;
  background: var(--bg-0); border: 1px solid var(--border); border-radius: var(--radius); cursor: crosshair;
}

/* ---------- Single radiograph photo import dialog (see
   radiq-image-import.js) ---------- */
.image-import-card { width: 480px; }

/* ---------- Live phone-camera capture dialog (see
   radiq-camera-record.js) ---------- */
.camera-record-card { width: 420px; max-width: 92vw; max-height: 90vh; overflow-y: auto; }
.modal-header-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.modal-header-row h2 { margin: 0; }
.modal-close {
  background: none; border: none; color: var(--text-1); font-size: 20px; line-height: 1; cursor: pointer;
  padding: 2px 6px; border-radius: var(--radius);
}
.modal-close:hover { color: var(--text-0); background: var(--bg-2); }
.camera-preview-wrap {
  position: relative; width: 100%; aspect-ratio: 3 / 4; background: #000; border-radius: var(--radius);
  overflow: hidden; border: 1px solid var(--border);
}
.camera-preview-wrap video { width: 100%; height: 100%; object-fit: cover; display: block; }
.camera-guide-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; pointer-events: none; }
.camera-guide-box {
  width: 82%; height: 62%; border: 2px dashed rgba(41, 194, 214, 0.85); border-radius: 4px;
  box-shadow: 0 0 0 2000px rgba(0, 0, 0, 0.25);
}
.camera-stats-overlay {
  position: absolute; top: 8px; left: 8px; right: 8px; display: flex; justify-content: space-between; gap: 8px;
}
.camera-stat {
  font-size: 11px; font-family: ui-monospace, "SF Mono", Menlo, monospace; padding: 3px 7px; border-radius: 4px;
  background: rgba(6, 7, 9, 0.75); color: var(--text-1);
}
.camera-stat.stat-good { color: #3ecf8e; }
.camera-stat.stat-warn { color: var(--amber); }
.camera-stat.stat-bad { color: var(--red); }
.camera-review-video {
  display: block; width: 100%; max-height: 60vh; background: #000; border-radius: var(--radius);
  border: 1px solid var(--border); margin-top: 8px;
}

/* ---------- Region -> pseudo-stack dialog (live screen capture, no
   video file in between — see radiq-region-stack.js) ---------- */
.region-stack-card { width: 520px; max-height: 88vh; overflow-y: auto; }
.region-stack-preview-wrap {
  position: relative; width: 100%; max-width: 460px; margin: 0 auto; aspect-ratio: 16 / 9;
  background: var(--bg-0); border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; cursor: crosshair; user-select: none;
}
.region-stack-video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain;
}
/* The drawn selection box — a plain DOM rectangle over the live preview
   (see wireRegionSelection in radiq-region-stack.js), converted to the
   video's native pixel coordinates only when capture actually starts. */
.region-stack-box {
  position: absolute; border: 2px solid var(--accent-bright);
  background: rgba(157, 107, 255, 0.12); pointer-events: none;
}
.region-stack-box.hidden { display: none; }

/* ---------- Cine play (stack viewport) ---------- */
.tb-cine { display: flex; align-items: center; gap: 6px; }
.tb-cine select {
  background: var(--bg-3); color: var(--text-0); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 5px 6px; font-size: 11.5px;
}
#btnCinePlay.active { background: var(--accent-dim); color: var(--accent); border-color: var(--accent-border); }

/* ---------- Bottom status bar (static shell — see index.html comment
   near #appStatusBar: current tool/WW/WC/zoom/image-index text content
   has no existing live-updating data source in app.js, so this renders
   fixed placeholder text rather than fabricating live-looking numbers.
   TODO: wire to real tool/viewport state if/when app.js exposes it. ---------- */
.app-statusbar {
  height: 22px; min-height: 22px; flex-shrink: 0;
  background: #140f24; border-top: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 12px; font-size: 10.5px; color: var(--text-2);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.app-statusbar-left { display: flex; align-items: center; gap: 14px; }
.app-statusbar-right { color: var(--text-2); letter-spacing: .08em; text-transform: uppercase; }
