/* ═══════════════════════════════════════════════════
   VibeEdit — Synthwave Design System
   Apple structure · Synthwave palette · Space Mono
   ═══════════════════════════════════════════════════ */

/* ── Font (from local assets) ────────────────────── */
@font-face {
  font-family: 'Space Mono';
  src: url('../../assets/fonts/SpaceMono-Regular.ttf') format('truetype');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Space Mono';
  src: url('../../assets/fonts/SpaceMono-Bold.ttf') format('truetype');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Space Mono';
  src: url('../../assets/fonts/SpaceMono-Italic.ttf') format('truetype');
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Space Mono';
  src: url('../../assets/fonts/SpaceMono-BoldItalic.ttf') format('truetype');
  font-weight: 700; font-style: italic; font-display: swap;
}

/* ── Tokens ──────────────────────────────────────── */
:root {
  /* (v0.18.0) Accent-rail design language — one hue → alpha tokens, built with
     rgb triplets + rgba() only (color-mix() does NOT render on CEP 12's CEF). */
  --play-rgb:  167, 139, 250;   /* playhead purple (CHỐT — fallback: cyan 34,211,238) */
  --tc-idle:   #6F6488;         /* timecode at rest — muted grey-purple */
  --tc-live:   #C4A9FF;         /* timecode on the playing row */

  /* Synthwave surfaces — deep purple base */
  --bg-base:        #15101f;   /* deepest purple-black */
  --bg-panel:       #1c1530;   /* panel surface */
  --bg-card:        #251b3d;   /* elevated card */
  --bg-card-hi:     #2e2148;   /* hover card */
  --bg-input:       #1a1329;   /* input wells */
  --bg-sidebar:     #120c1c;   /* sidebar darker */

  /* Borders / lines — neon purple */
  --line-subtle:    rgba(168, 120, 255, 0.10);
  --line-normal:    rgba(168, 120, 255, 0.18);
  --line-strong:    rgba(168, 120, 255, 0.32);

  /* Text */
  --text-primary:   #f3edff;
  --text-secondary: #b9a8d9;
  --text-tertiary:  #7c6b9c;
  --text-disabled:  #4a3d63;

  /* Accents — purple primary, yellow special */
  --purple:         #a855f7;   /* neon purple accent */
  --purple-bright:  #c47bff;
  --purple-glow:    rgba(168, 85, 247, 0.45);
  --purple-dim:     rgba(168, 85, 247, 0.14);

  /* yellow removed — unified purple tone */

  /* Status */
  --success:        #4ade80;
  --warn:           #ffd60a;
  --error:          #ff5470;

  /* Spacing */
  --sp-xs: 4px; --sp-sm: 8px; --sp-md: 12px;
  --sp-lg: 16px; --sp-xl: 22px; --sp-2xl: 30px;

  /* Radius — soft Apple corners */
  --r-sm: 8px; --r-md: 12px; --r-lg: 18px; --r-xl: 24px; --r-full: 999px;

  /* Font — Space Mono everywhere */
  --font: 'Space Mono', 'SF Mono', 'Consolas', monospace;

  /* TYPE SCALE — base sizes +10 for ergonomics per brief.
     Original ~11-15px → now ~16-25px equivalents tuned for mono */
  --fs-micro:  10px;
  --fs-small:  11px;
  --fs-body:   12px;
  --fs-label:  12px;
  --fs-value:  13px;
  --fs-title:  16px;
  --fs-brand:  15px;
}

/* ── Reset ───────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overflow: hidden; }
body {
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--text-primary);
  background: var(--bg-base);
  display: flex;
  -webkit-font-smoothing: antialiased;
  user-select: none;
}

/* Scrollbar */
::-webkit-scrollbar       { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--purple-dim); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--purple-glow); }

/* ═════════════════════════════════════════════════
   APP SHELL — sidebar + content
═════════════════════════════════════════════════ */
.app {
  display: flex;
  width: 100%;
  height: 100vh;
}

/* ── SIDEBAR ──────────────────────────────────────── */
.sidebar {
  width: 92px;
  flex-shrink: 0;
  background: var(--bg-sidebar);
  border-right: 1px solid var(--line-subtle);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--sp-lg) 0;
  gap: var(--sp-xs);
  /* (v0.23.0) Short panel heights cut off the lower tabs — let the rail scroll
     (wheel) from Silence through Settings. Scrollbar hidden for a clean look. */
  overflow-y: auto;
  scrollbar-width: none;              /* Firefox */
}
.sidebar::-webkit-scrollbar { width: 0; height: 0; }   /* CEF/Chromium */

.sidebar-brand {
  margin-bottom: var(--sp-lg);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* (v0.18.0) New mark: white fill + a soft purple glow behind the logo. */
.brand-logo { filter: drop-shadow(0 0 7px rgba(168, 85, 247, 0.55)); }

.nav-item {
  width: 72px;
  flex-shrink: 0;                     /* (v0.23.0) keep size when the rail scrolls */
  padding: var(--sp-sm) 0;
  border: none;
  background: transparent;
  border-radius: var(--r-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  color: var(--text-tertiary);
  transition: background 0.18s, color 0.18s;
}
.nav-item svg { width: 22px; height: 22px; }
.nav-label {
  font-size: var(--fs-micro);
  font-weight: 400;
  letter-spacing: 0.02em;
}
.nav-item:hover { color: var(--text-secondary); background: var(--purple-dim); }
.nav-item[data-active="true"] {
  color: var(--purple-bright);
  background: var(--purple-dim);
  box-shadow: inset 0 0 0 1px var(--line-normal),
              0 0 18px -6px var(--purple-glow);
}
.nav-item[data-active="true"] svg { filter: drop-shadow(0 0 6px var(--purple-glow)); }

/* (C1) Pro lock badge on nav-item */
.nav-item { position: relative; }
.nav-lock {
  position: absolute;
  top: 4px; right: 12px;
  display: flex;
  color: var(--text-tertiary);
  opacity: 0.85;
  pointer-events: none;
}
.nav-lock svg { width: 11px; height: 11px; }
.nav-item.is-locked { color: var(--text-disabled); }
.nav-item.is-locked:hover { color: var(--text-tertiary); }

/* (C3a) Locked rows inside Settings (Model Setting / AI Setting on free tier) */
.snav-lock {
  display: inline-flex;
  margin-left: 7px;
  color: var(--text-tertiary);
  vertical-align: middle;
}
.snav-lock svg { width: 11px; height: 11px; }
.snav-row.is-locked .snav-name { color: var(--text-secondary); }
.snav-row.is-locked .snav-sub  { color: var(--text-disabled); }
.snav-row.is-locked .snav-chev { opacity: 0.35; }

/* (C1) Pro upgrade overlay over the locked view */
.views { position: relative; }
.views.scroll-lock { overflow: hidden !important; }
.pro-lock-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(21, 16, 31, 0.80);
  backdrop-filter: blur(2px);
  z-index: 40;
}
.pro-lock-overlay.hidden { display: none; }
.pro-lock-card {
  text-align: center;
  padding: var(--sp-2xl) var(--sp-xl);
  max-width: 300px;
  background: var(--bg-card);
  border: 1px solid var(--line-normal);
  border-radius: var(--r-lg);
  box-shadow: 0 12px 40px -12px rgba(0, 0, 0, 0.6);
}
.pro-lock-icon {
  color: var(--purple-bright);
  margin-bottom: var(--sp-md);
}
.pro-lock-icon svg { width: 34px; height: 34px; }
.pro-lock-title {
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: var(--sp-xs);
}
.pro-lock-sub {
  font-size: var(--fs-label);
  color: var(--text-secondary);
  margin-bottom: var(--sp-lg);
}
.pro-lock-btn {
  padding: var(--sp-sm) var(--sp-xl);
  border: none;
  border-radius: var(--r-full);
  background: var(--purple);
  color: #fff;
  font-size: var(--fs-label);
  font-weight: 600;
  cursor: pointer;
  transition: background 0.18s;
}
.pro-lock-btn:hover { background: var(--purple-bright); }



.nav-spacer { flex: 1; }

.nav-settings {
  color: var(--text-tertiary);
}
.nav-settings[data-active="true"] {
  color: var(--purple-bright);
  background: var(--purple-dim);
}

/* ── CONTENT AREA ─────────────────────────────────── */
.content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Header bar */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-lg) var(--sp-xl);
  border-bottom: 1px solid var(--line-subtle);
  flex-shrink: 0;
}
.brand-wordmark {
  font-size: var(--fs-brand);
  letter-spacing: -0.01em;
}
.brand-vibe { font-style: italic; font-weight: 400; color: var(--purple-bright); }
.brand-edit { font-weight: 700; color: #ffffff; }
.transcript-list.painting { user-select: none; cursor: cell; }

/* Activity log panel (Debug mode) */
.log-panel {
  flex-shrink: 0;
  border-top: 1px solid var(--line-subtle);
  background: rgba(0,0,0,0.25);
  max-height: 200px;
  display: flex;
  flex-direction: column;
}
/* While a task runs (body.proc-active), float the debug log above the
   processing overlay (z-index 200) so activity stays readable. */
body.proc-active #log-panel:not(.hidden) {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 210;
  max-height: 42vh;
  box-shadow: 0 -12px 32px -12px rgba(0,0,0,0.6);
}
.log-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 12px; border-bottom: 1px solid var(--line-subtle);
}
.log-title { font-size: var(--fs-micro); color: var(--text-muted); letter-spacing: 0.08em; text-transform: uppercase; }
.log-actions { display: flex; gap: 6px; }
.log-btn {
  font-size: var(--fs-micro); font-family: inherit;
  color: var(--accent); background: transparent;
  border: 1px solid var(--line-subtle); border-radius: var(--r-sm);
  padding: 2px 10px; cursor: pointer;
}
.log-btn:hover { border-color: var(--accent); }
.log-body { overflow-y: auto; padding: 6px 12px; font-size: 11px; line-height: 1.5; }
.log-empty { color: var(--text-disabled); font-size: var(--fs-micro); }
.log-entry { display: flex; gap: 8px; white-space: pre-wrap; word-break: break-word; }
.log-time { color: var(--text-disabled); flex-shrink: 0; }
.log-msg  { color: var(--text-muted); }
.log-entry[data-level="ERROR"]   .log-msg { color: var(--error); }
.log-entry[data-level="WARN"]    .log-msg { color: var(--warn); }
.log-entry[data-level="SUCCESS"] .log-msg { color: var(--success); }
.seq-warn {
  cursor: pointer;
  font-size: var(--fs-small);
  line-height: 1;
  filter: drop-shadow(0 0 6px rgba(255,84,112,0.5));
}

/* View container */
.views {
  flex: 1;
  overflow-y: auto;
  padding: var(--sp-xl);
  min-height: 0;
}
.view { display: none; }
.view[data-active="true"] { display: block; animation: viewIn 0.25s ease; }
@keyframes viewIn { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:translateY(0)} }

/* ── PANEL CARD ───────────────────────────────────── */
.panel {
  background: var(--bg-panel);
  border: 1px solid var(--line-subtle);
  border-radius: var(--r-xl);
  padding: var(--sp-xl);
  box-shadow: 0 0 40px -20px var(--purple-glow);
}

.panel-title {
  font-size: var(--fs-title);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

/* ── CONTROL: slider rows ─────────────────────────── */
.control { margin-bottom: var(--sp-xl); }

.control-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--sp-md);
}
.control-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-label);
  color: var(--text-secondary);
}
.control-value {
  font-size: var(--fs-value);
  font-weight: 700;
  color: var(--text-primary);
}
.control-value[data-accent="yellow"] { color: var(--purple-bright); }

/* Info icon */
.info-dot {
  width: 18px; height: 18px;
  border-radius: 50%;
  border: 1px solid var(--line-normal);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: help;
  color: var(--text-tertiary);
  flex-shrink: 0;
  position: relative;
}
.info-dot svg { width: 11px; height: 11px; }
.info-dot:hover { border-color: var(--purple); color: var(--purple-bright); }

/* Tooltip on info hover */
.info-dot[data-tip]:hover::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: 220px;
  padding: 10px 12px;
  background: var(--bg-card-hi);
  border: 1px solid var(--line-normal);
  border-radius: var(--r-sm);
  font-size: var(--fs-micro);
  line-height: 1.45;
  color: var(--text-secondary);
  z-index: 50;
  box-shadow: 0 8px 24px rgba(0,0,0,0.6);
  white-space: normal;
  text-align: left;
  pointer-events: none;
}

/* ── SLIDER (range) ───────────────────────────────── */
.slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 4px;
  border-radius: 2px;
  background: var(--bg-input);
  outline: none;
  cursor: pointer;
}
.slider::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--purple) 0%, var(--purple) var(--fill, 50%), var(--bg-input) var(--fill, 50%));
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 20px; height: 20px;
  margin-top: -8px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--purple);
  box-shadow: 0 0 12px -2px var(--purple-glow);
  cursor: grab;
  transition: transform 0.1s;
}
.slider::-webkit-slider-thumb:active { cursor: grabbing; transform: scale(1.12); }

/* Padding Cut now uses standard purple slider */

/* Slider help text */
.control-help {
  font-size: var(--fs-micro);
  color: var(--text-tertiary);
  line-height: 1.5;
  margin-top: var(--sp-sm);
}

/* ── SEGMENTED TOGGLE (Selected / Entire) ─────────── */
.segmented {
  display: flex;
  background: var(--bg-input);
  border: 1px solid var(--line-subtle);
  border-radius: var(--r-md);
  padding: 4px;
  gap: 4px;
  margin-bottom: var(--sp-lg);
}
.seg-btn {
  flex: 1;
  padding: 11px;
  border: none;
  background: transparent;
  border-radius: var(--r-sm);
  font-family: var(--font);
  font-size: var(--fs-small);
  color: var(--text-tertiary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.seg-btn[data-active="true"] {
  background: var(--purple-dim);
  color: var(--purple-bright);
  box-shadow: inset 0 0 0 1px var(--line-normal);
}

/* ── OPTION ROWS (toggles) ────────────────────────── */
.option-group {
  background: var(--bg-card);
  border: 1px solid var(--line-subtle);
  border-radius: var(--r-lg);
  padding: var(--sp-xs) var(--sp-lg);
  margin-bottom: var(--sp-lg);
}
.option-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-md) 0;
}
.option-row + .option-row { border-top: 1px solid var(--line-subtle); }
.option-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-label);
  color: var(--text-primary);
}

/* Toggle switch */
.toggle {
  position: relative;
  width: 46px; height: 26px;
  flex-shrink: 0;
  cursor: pointer;
}
.toggle input { opacity: 0; width: 0; height: 0; }
.toggle-track {
  position: absolute; inset: 0;
  background: var(--bg-input);
  border: 1px solid var(--line-normal);
  border-radius: var(--r-full);
  transition: background 0.2s, border-color 0.2s;
}
.toggle-track::before {
  content: '';
  position: absolute;
  width: 18px; height: 18px;
  left: 3px; top: 3px;
  background: var(--text-tertiary);
  border-radius: 50%;
  transition: transform 0.2s, background 0.2s;
}
.toggle input:checked + .toggle-track {
  background: var(--purple-dim);
  border-color: var(--purple);
}
.toggle input:checked + .toggle-track::before {
  transform: translateX(20px);
  background: var(--purple-bright);
  box-shadow: 0 0 10px -1px var(--purple-glow);
}

/* ── ACTION BUTTONS ───────────────────────────────── */
.action-row {
  display: flex;
  gap: var(--sp-sm);
  align-items: center;
  margin-top: var(--sp-xl);
}

.btn {
  flex: 1;
  height: 50px;
  border: none;
  border-radius: var(--r-md);
  font-family: var(--font);
  font-size: var(--fs-label);
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s, box-shadow 0.15s, opacity 0.2s;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  /* (v0.16.0) When a button is squeezed narrow, wrap at word boundaries only —
     never split a word mid-letter ("AI Fin\nRepea"). keep-all keeps each word
     intact; the label breaks between words as the button shrinks. */
  white-space: normal;
  word-break: keep-all;
  overflow-wrap: normal;
  hyphens: none;
  line-height: 1.15;
  text-align: center;
}
.btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* Ghost button (Analyze, Transcribe) */
.btn-ghost {
  background: transparent;
  color: var(--purple-bright);
  box-shadow: inset 0 0 0 1px var(--line-normal);
}
.btn-ghost:hover:not(:disabled) { background: var(--purple-dim); }

/* Secondary (Preview) */
.btn-secondary {
  background: var(--bg-card);
  color: var(--text-primary);
  box-shadow: inset 0 0 0 1px var(--line-normal);
}
.btn-secondary:hover:not(:disabled) { background: var(--bg-card-hi); }

/* Primary (Apply, Find repeats) — purple glow */
.btn-primary {
  background: var(--purple);
  color: #fff;
  box-shadow: 0 0 22px -6px var(--purple-glow);
}
.btn-primary:hover:not(:disabled) {
  background: var(--purple-bright);
  transform: translateY(-1px);
  box-shadow: 0 0 28px -4px var(--purple-glow);
}
.btn-primary:active:not(:disabled) { transform: none; }

/* ── RESULT ROWS ──────────────────────────────────── */
.result-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--bg-card);
  border: 1px solid var(--line-subtle);
  border-radius: var(--r-md);
  padding: var(--sp-md) var(--sp-lg);
  margin-top: var(--sp-md);
  font-size: var(--fs-label);
}
.result-row .rv { font-weight: 700; color: var(--text-primary); }
.result-row .rv[data-accent="yellow"] { color: var(--purple-bright); }
.result-label { color: var(--text-secondary); }

/* ═════════════════════════════════════════════════
   FOOTER
═════════════════════════════════════════════════ */
.footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-md) var(--sp-xl);
  border-top: 1px solid var(--line-subtle);
  flex-shrink: 0;
}
.footer-version { font-size: var(--fs-micro); color: var(--text-disabled); }
.status-dot { width: 7px; height: 7px; border-radius: 50%; transition: background 0.3s; }
.status-dot[data-status="idle"]    { background: var(--text-disabled); }
.status-dot[data-status="ready"]   { background: var(--success); }
.status-dot[data-status="running"] { background: var(--purple-bright); animation: pulse 1.4s ease-in-out infinite; }
.status-dot[data-status="error"]   { background: var(--error); }
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }
.status-text { font-size: var(--fs-micro); color: var(--text-tertiary); }

/* ═════════════════════════════════════════════════
   TOAST (popup notification)
═════════════════════════════════════════════════ */
.toast {
  position: fixed;
  bottom: 70px;
  /* Center on the MAIN content area (exclude 92px sidebar) → +46px */
  left: calc(50% + 46px);
  transform: translateX(-50%) translateY(20px);
  background: var(--bg-card-hi);
  border: 1px solid var(--success);
  border-radius: var(--r-lg);
  padding: 12px 20px;
  font-size: var(--fs-small);
  color: var(--success);
  box-shadow: 0 8px 32px rgba(0,0,0,0.6), 0 0 24px -8px var(--success);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s, transform 0.3s;
  z-index: 200;
  max-width: min(560px, 80vw);
  line-height: 1.45;
}
.toast[data-show="true"] {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;   /* allow clicking the X */
}
.toast[data-type="error"] { border-color: var(--error); color: var(--error); box-shadow: 0 8px 32px rgba(0,0,0,0.6), 0 0 24px -8px var(--error); }
.toast[data-type="warn"]  { border-color: rgba(245,176,66,0.55); color: #F5B042; box-shadow: 0 8px 32px rgba(0,0,0,0.6), 0 0 24px -8px rgba(245,176,66,0.6); }

/* ═════════════════════════════════════════════════
   REPEATS — transcript review list
═════════════════════════════════════════════════ */
.review-list {
  margin-top: var(--sp-lg);
  background: var(--bg-card);
  border: 1px solid var(--line-subtle);
  border-radius: var(--r-lg);
  max-height: 260px;
  overflow-y: auto;
}
.review-item {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-md);
  padding: var(--sp-md) var(--sp-lg);
  cursor: pointer;
  transition: background 0.15s;
}
.review-item + .review-item { border-top: 1px solid var(--line-subtle); }
.review-item:hover { background: var(--bg-card-hi); }
.review-item[data-keep="false"] { opacity: 0.45; }
.review-toggle {
  width: 22px; height: 22px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-normal);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  color: var(--success);
}
.review-item[data-keep="false"] .review-toggle { color: var(--error); border-color: var(--error); }

/* ═════════════════════════════════════════════════
   FORMAT — preset grid
═════════════════════════════════════════════════ */
.preset-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-md);
  margin-top: var(--sp-lg);
}
.preset-card {
  background: var(--bg-card);
  border: 1px solid var(--line-subtle);
  border-radius: var(--r-lg);
  padding: var(--sp-lg);
  cursor: pointer;
  transition: border-color 0.18s, background 0.18s, transform 0.1s;
  display: flex;
  flex-direction: column;
  gap: var(--sp-sm);
  align-items: center;
  text-align: center;
}
.preset-card:hover {
  border-color: var(--line-strong);
  background: var(--bg-card-hi);
  transform: translateY(-2px);
}
.preset-card[data-active="true"] {
  border-color: var(--purple);
  box-shadow: 0 0 20px -8px var(--purple-glow);
}
.preset-ratio {
  width: 100%;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.preset-shape {
  background: var(--purple-dim);
  border: 1.5px solid var(--purple);
  border-radius: 4px;
}
.preset-name { font-size: var(--fs-label); font-weight: 700; color: var(--text-primary); }
.preset-desc { font-size: var(--fs-micro); color: var(--text-tertiary); }

/* ═════════════════════════════════════════════════
   VIBE EDIT — chat (future)
═════════════════════════════════════════════════ */
.chat-wrap {
  display: flex;
  flex-direction: column;
  height: 100%;
  justify-content: flex-end;
}

/* ═════════════════════════════════════════════════
   SETTINGS OVERLAY (reuse)
═════════════════════════════════════════════════ */
.overlay {
  position: fixed; inset: 0;
  background: rgba(10,6,18,0.8);
  backdrop-filter: blur(6px);
  z-index: 100;
  display: flex;
  animation: fadeIn 0.15s ease;
}
@keyframes fadeIn { from{opacity:0} to{opacity:1} }
.settings-panel {
  width: 100%; height: 100%;
  background: var(--bg-panel);
  display: flex; flex-direction: column;
}
.settings-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-lg) var(--sp-xl);
  border-bottom: 1px solid var(--line-subtle);
}
.settings-title { font-size: var(--fs-title); font-weight: 700; }

/* (v0.20.2) CapCut footer — Save (purple) fills left, Cancel (grey) fixed
   right. Sits below the scrolling body, inside the flex-column panel. The two
   header ✕ buttons are retired in favour of this. */
.settings-foot {
  display: flex; gap: 10px;
  padding: var(--sp-lg) var(--sp-xl);
  border-top: 1px solid var(--line-subtle);
}
.settings-save   { flex: 1 1 0; height: 42px; border-radius: 10px; font-weight: 600; }
.settings-cancel { flex: 1 1 0; height: 42px; border-radius: 10px; font-weight: 600; }
/* Header close buttons replaced by the footer. */
#btn-settings-close, #btn-settings-close-d { display: none; }
.settings-body {
  flex: 1; overflow-y: auto;
  padding: var(--sp-xl);
  display: flex; flex-direction: column; gap: var(--sp-2xl);
}
.field { display: flex; flex-direction: column; gap: 6px; }
.field-label { font-size: var(--fs-small); color: var(--text-secondary); }
.field-row { display: flex; gap: var(--sp-xs); }
.field-input {
  flex: 1; height: 40px;
  background: var(--bg-input);
  border: 1px solid var(--line-normal);
  border-radius: var(--r-sm);
  padding: 0 var(--sp-md);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: var(--fs-small);
  outline: none;
}
.field-input:focus { border-color: var(--purple); }
.field-input::placeholder { color: var(--text-disabled); }
.field-select {
  height: 40px; width: 100%;
  -webkit-appearance: none; appearance: none;
  background-color: var(--bg-input);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M4 6l4 4 4-4' stroke='%23a855f7' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center;
  border: 1px solid var(--line-normal);
  border-radius: var(--r-sm);
  padding: 0 34px 0 var(--sp-md);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: var(--fs-small);
  outline: none; cursor: pointer;
}
.field-select:focus { border-color: var(--purple); }
.btn-browse {
  width: 40px; height: 40px;
  background: var(--bg-input);
  border: 1px solid var(--line-normal);
  border-radius: var(--r-sm);
  color: var(--text-secondary);
  cursor: pointer; flex-shrink: 0;
}
.btn-browse:hover { background: var(--bg-card-hi); }
.btn-icon {
  width: 36px; height: 36px;
  background: transparent; border: none;
  border-radius: var(--r-sm);
  color: var(--text-tertiary);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.btn-icon:hover { background: var(--purple-dim); color: var(--text-secondary); }

.hidden { display: none !important; }

/* ── SILENCE WAVEFORM PREVIEW ─────────────────────── */
.wave-preview {
  margin-top: var(--sp-lg);
  background: var(--bg-card);
  border: 1px solid var(--line-subtle);
  border-radius: var(--r-lg);
  padding: var(--sp-md) var(--sp-lg);
  animation: viewIn 0.25s ease;
}
.silence-canvas {
  width: 100%;
  height: 72px;
  display: block;
  border-radius: var(--r-sm);
  background: var(--bg-input);
}

/* ── PRO badge (yellow) ───────────────────────────── */
.pro-badge {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #8a8597;
  border: 1px solid #4a4458;
  border-radius: var(--r-full);
  padding: 2px 9px;
}

/* ── Sticky toast (long ops: transcribing...) ─────── */
.toast[data-sticky="true"] {
  border-color: var(--purple);
  color: var(--purple-bright);
  box-shadow: 0 8px 32px rgba(0,0,0,0.6), 0 0 24px -8px var(--purple-glow);
}
.toast[data-sticky="true"]::before {
  content: '';
  display: inline-block;
  width: 11px; height: 11px;
  margin-right: 8px;
  border: 2px solid var(--purple-bright);
  border-top-color: transparent;
  border-radius: 50%;
  vertical-align: -1px;
  animation: toastSpin 0.7s linear infinite;
}
@keyframes toastSpin { to { transform: rotate(360deg); } }

/* ── Transcript (word-level, scrollable) ──────────── */
.transcript-block { margin-top: var(--sp-lg); animation: viewIn 0.25s ease; }
.transcript-head { margin-bottom: var(--sp-md); }
.transcript-title {
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-tertiary);
  display: block; margin-bottom: 4px;
}
.transcript-hint { font-size: var(--fs-micro); color: var(--text-tertiary); }
.transcript-list {
  max-height: 380px; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--sp-sm);
  padding-right: 4px;
  padding-left: 4px;    /* (v0.12.3) glow/border of .is-playing was clipped on the left edge */
  padding-top: 4px;     /* (v0.13.14) same clip on the TOP edge — the first line's */
  padding-bottom: 4px;  /* glow ring sat under the frame; bottom padded to match. */
}
.tr-line {
  display: flex; gap: var(--sp-md); align-items: flex-start;
  /* (v0.18.0) Accent-rail rework: no more 4-side border — verdicts live on the
     mark + word styling, the playhead on the left rail. padding-left reserves
     the 3px rail on BOTH states so text never jumps when playback moves. */
  padding: var(--sp-sm) var(--sp-md);
  padding-left: calc(var(--sp-md) + 3px);
  border-radius: var(--r-md);
  background: rgba(255,255,255,0.02);
  border: none;
  transition: background 0.12s;
}
.tr-time {
  font-size: var(--fs-micro); color: var(--tc-idle);
  flex-shrink: 0; min-width: 92px; padding-top: 2px;
  font-variant-numeric: tabular-nums; cursor: default;
  transition: color 0.12s;
}
.tr-text { font-size: var(--fs-small); color: var(--text-primary); line-height: 1.6; flex: 1; }
.tr-word {
  cursor: pointer; border-radius: 3px; padding: 0 1px;
  transition: background 0.12s;
  user-select: none; -webkit-user-select: none;
}
.tr-word:hover { background: var(--purple-glow); color: var(--purple-bright); }
.tr-word.sel { background: var(--purple); color: #fff; }

/* ── Review legend ────────────────────────────────── */
.review-legend {
  display: flex; gap: var(--sp-md); flex-wrap: wrap; row-gap: 3px;
  margin-top: 6px; justify-content: flex-start;
  font-size: var(--fs-micro); color: var(--text-tertiary);
}
/* (v0.15.0) Ryan's catch: the red 'removed' dot sat off-edge relative to
   kept/consider — no stray indent on the first item, all rows share one edge. */
.review-legend .lg:first-child { margin-left: 0; padding-left: 0; }
.lg { display: inline-flex; align-items: center; gap: 5px; }
.lg-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.lg-red   { background: #ff4d5e; }
.lg-green { background: #36d399; }
.lg-purple { background: #a855f7; }

/* Review line states — verdicts read from the round mark + word styling now;
   the soft background tints stay as a scanning aid (borders are gone). */
.tr-line.line-keep  { background: rgba(54,211,153,0.05); }
.tr-line.line-consider { background: rgba(168,120,255,0.06); }

/* "Now playing" — accent rail (v0.18.0). box-shadow inset, NEVER border-left:
   border-left + border-radius tapers into a hook-shaped wedge at the corners
   and shifts the box model. The inset shadow clips to the radius and costs no
   reflow. Placed after the verdict states so the live tint wins. */
.tr-line.is-playing {
  background: rgba(var(--play-rgb), 0.08);
  box-shadow: inset 3px 0 0 rgb(var(--play-rgb));
}
.tr-line.is-playing .tr-time { color: var(--tc-live); }

/* ── Focus Mode (scaffold — cut logic wired in a later pass) ── */
.tr-line.is-tangent { opacity: 0.4; }
/* Off-topic lines fold into the cut (words carry w-drop) but must READ as merely
   dimmed — suppress the red strike + drop border so it isn't mistaken for a bad take. */
.tr-line.is-tangent .tr-word.w-drop,
.tr-line.is-tangent .tr-word.w-consider {
  color: var(--text-primary);
  text-decoration: none;
}
/* (v0.18.0) .is-tangent.line-drop border override removed — .tr-line has no border. */
.focus-topic {
  margin-bottom: var(--sp-md);
  padding: var(--sp-sm) var(--sp-md);
  background: var(--purple-dim);
  border: 1px solid var(--line-subtle);
  border-radius: var(--r-md);
  font-size: var(--fs-label);
  color: var(--purple-bright);
}
.focus-topic::before { content: 'Main topic — '; color: var(--text-tertiary); }
.tr-mark {
  flex-shrink: 0; width: 18px; height: 18px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; margin-right: 2px; margin-top: 1px;
}
.tr-mark.mk-drop { background: #ff4d5e; color: #fff; }
.tr-mark.mk-keep { background: #36d399; color: #062; }
.tr-mark.mk-consider { background: #a855f7; color: #fff; }
.tr-text .tr-word.w-drop { color: #ff6b78; text-decoration: line-through; }
.tr-word.w-keep { color: #36d399; }
/* consider = soft-removed (purple): in the cut set but flagged for review.
   Placed AFTER w-drop so the purple color wins over red for w-drop.w-consider. */
.tr-text .tr-word.w-consider { color: #c084fc; text-decoration: line-through; text-decoration-style: dashed; }

/* ── Toast close button ───────────────────────────── */
.toast { display: inline-flex; align-items: flex-start; gap: 12px; }
.toast-msg { flex: 1; }
.toast-close {
  background: transparent; border: none; color: inherit;
  cursor: pointer; font-size: 14px; opacity: 0.7; padding: 0 2px;
  display: none; flex-shrink: 0; line-height: 1.45;
}
.toast-close:hover { opacity: 1; }
.toast[data-type="error"] .toast-close { display: inline; }
.toast[data-type="done"]  .toast-close { display: inline; }

/* ── Brand wordmark clickable + About modal ───────── */
.brand-wordmark { cursor: pointer; user-select: none; }
.brand-wordmark:hover { opacity: 0.85; }

.about-overlay {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  background: rgba(8, 5, 14, 0.72);
  backdrop-filter: blur(3px);
}
.about-overlay.hidden { display: none; }
.about-card {
  display: flex; flex-direction: column;
  width: 340px; max-width: 90vw;
  background: var(--bg-surface, #1a1326);
  border: 1px solid var(--line-subtle, rgba(168,85,247,0.25));
  border-radius: var(--r-lg, 16px);
  box-shadow: 0 18px 60px -12px rgba(0,0,0,0.7), 0 0 40px -16px rgba(168,85,247,0.5);
  overflow: hidden;
  animation: aboutPop 0.18s ease-out;
}
@keyframes aboutPop {
  from { transform: scale(0.92); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}
/* Tab header — two equal-width tabs */
.about-tabs {
  display: flex;
  padding: 14px 20px 0;
  border-bottom: 1px solid var(--line-subtle);
}
.about-tab {
  flex: 1; text-align: center;
  padding: 6px 2px 10px;
  background: none; border: none; cursor: pointer;
  font-family: var(--font); font-size: var(--fs-small);
  color: var(--text-tertiary);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color .15s, border-color .15s;
}
.about-tab:hover { color: var(--text-secondary); }
.about-tab[data-active="true"] { color: var(--text-primary); border-bottom-color: var(--purple); }
/* Body / panes — ONE fixed height drives every tab (bump this to grow them all) */
.about-body { padding: 20px 22px; min-height: 176px; box-sizing: border-box; }
.about-pane { display: none; }
.about-pane[data-active="true"] { display: flex; flex-direction: column; height: 100%; }
.about-name { display: flex; align-items: baseline; font-size: 22px; font-weight: 700; letter-spacing: 0.01em; }
.about-head { display: flex; align-items: center; gap: 10px; }
.tier-pill {
  display: inline-flex; align-items: center;
  padding: 2px 11px; border-radius: var(--r-full);
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: 0.03em;
  color: #ffffff; line-height: 1.6;
}
.tier-pill-free { background: #22c55e; }
.tier-pill-pro  { background: #f97316; }
.pill-tip {
  display: block; padding: 0;
  border: none; background: transparent; text-align: center;
  font-size: var(--fs-micro); color: var(--text-tertiary);
  opacity: 0.75; cursor: pointer; letter-spacing: 0.01em;
  transition: opacity .18s, color .18s;
  animation: pillTipPulse 2.4s ease-in-out infinite;
}
.pill-tip:hover { opacity: 1; color: var(--purple-bright); }
@keyframes pillTipPulse { 0%,100% { opacity: 0.55; } 50% { opacity: 0.9; } }
.about-version { margin-top: 4px; font-size: 12px; color: var(--text-secondary); letter-spacing: 0.04em; }
.about-meta { margin-top: 18px; display: flex; flex-direction: column; gap: 10px; }
.about-row { display: flex; gap: 12px; font-size: var(--fs-small); align-items: center; }
.about-row-user { align-items: baseline; }
.about-row-user .about-key { flex: 0 0 auto; min-width: 0; }
.about-row-user .about-val {
  flex: 1 1 auto; min-width: 0;
  text-align: left; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.about-key { color: var(--text-tertiary); min-width: 100px; }
.about-val { color: var(--text-primary); font-weight: 600; }
.about-credit { font-size: var(--fs-small); color: var(--text-secondary); line-height: 1.5; }
/* About pane centers its two lines (credit + slogan) for visual balance */
.about-pane[data-apane="about"] { justify-content: center; align-items: center; text-align: center; }
.about-quote { margin-top: 10px; font-weight: 700; font-size: var(--fs-small); color: var(--purple-bright); letter-spacing: 0.06em; }
/* Social links row (centered under the slogan) */
.about-socials { display: flex; gap: 14px; justify-content: center; margin-top: 16px; }
.about-social {
  width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
  background: var(--bg-input); border: 1px solid var(--line-subtle); border-radius: 50%;
  color: var(--text-secondary); cursor: pointer; transition: color .15s, border-color .15s, background .15s;
}
.about-social svg { width: 16px; height: 16px; }
.about-social:hover { color: var(--purple-bright); border-color: var(--purple); background: var(--purple-dim); }
/* Language pane */
.about-lang-label { font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-secondary); margin-bottom: 10px; }
/* AI model description under the model dropdown */
.ai-model-desc { margin-top: 9px; font-size: var(--fs-micro); color: var(--text-tertiary); line-height: 1.55; }

/* ── Settings: 3 tabs ─────────────────────────────── */
.settings-tabs { display: flex; gap: 4px; padding: 0 var(--sp-lg); border-bottom: 1px solid var(--line-subtle); }
.settings-pane { display: none; }
.settings-pane[data-active="true"] { display: block; }
/* AI method switch + panes */
.ai-method { width: 100%; margin-bottom: var(--sp-lg); }
.ai-method .seg-btn { flex: 1; }
/* password eye toggle */
.password-row { position: relative; }
.password-row .field-input { padding-right: 40px; }
.eye-toggle { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; background: none; border: none; color: var(--text-tertiary); cursor: pointer; border-radius: var(--r-sm); }
.eye-toggle:hover { color: var(--purple-bright); }
.eye-toggle svg { width: 18px; height: 18px; }
/* chat-bar style result input */
.chatbar { display: flex; align-items: flex-end; gap: 6px; background: var(--bg-input); border: 1px solid var(--line-normal); border-radius: 14px; padding: 6px 6px 6px 8px; }
.chatbar:focus-within { border-color: var(--purple); }
.chatbar-attach, .chatbar-send { flex: none; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center; border-radius: 50%; border: none; cursor: pointer; transition: background .15s, color .15s; }
.chatbar-attach { background: transparent; color: var(--text-secondary); }
.chatbar-attach:hover { background: var(--purple-dim); color: var(--purple-bright); }
.chatbar-send { background: var(--purple); color: #fff; }
.chatbar-send:hover { background: var(--purple-bright); }
.chatbar-attach svg, .chatbar-send svg { width: 18px; height: 18px; }
.chatbar-input { flex: 1; resize: none; max-height: 120px; min-height: 22px; background: transparent; border: none; outline: none; color: var(--text-primary); font-family: var(--font); font-size: var(--fs-small); line-height: 1.4; padding: 7px 2px; }
.chatbar-input::placeholder { color: var(--text-tertiary); }
/* AI Setting: keep the Copy button the same height as inputs; smaller send arrow */
.settings-pane .action-row .btn { height: 44px; padding: 0 16px; }
.settings-pane .chatbar-send { width: 28px; height: 28px; }
.settings-pane .chatbar-send svg { width: 15px; height: 15px; }
.settings-pane .chatbar-attach { width: 28px; height: 28px; }

/* Apple-style settings polish */
.settings-tabs { padding: 8px var(--sp-lg) 10px; border-bottom: 1px solid var(--line-subtle); gap: 6px; }
.settings-body { padding: var(--sp-xl); gap: 0; }   /* (v0.11.10) match main-tab inset */
.settings-pane[data-active="true"] { display: flex; flex-direction: column; gap: var(--sp-lg); }
/* content cards group related options (Marker-tab wrapper vibe) */
.settings-card { display: flex; flex-direction: column; gap: var(--sp-lg); padding: var(--sp-lg); border: 1px solid var(--line-subtle); border-radius: 12px; background: rgba(168,85,247,0.035); }
/* two AI cards side-by-side when wide, stacked when narrow */
.ai-cards { display: flex; flex-wrap: wrap; gap: var(--sp-lg); }
/* label sits tight to its input; options separated by the card gap */
.settings-pane .field { display: flex; flex-direction: column; gap: 6px; }
.settings-pane .action-row { margin-top: 0; }
.settings-pane .field-label { font-weight: 700; text-transform: uppercase; letter-spacing: .06em; font-size: var(--fs-micro); color: var(--purple-bright); margin: 0; display: inline-flex; align-items: center; gap: 6px; }
/* inside the AI cards the purple heading is the card title, so field labels go gray */
.ai-cards .field-label { color: var(--text-tertiary); }
.settings-pane .field-step { display: none; }
.settings-pane .field-input, .settings-pane .field-select, .settings-pane .btn-browse { border-radius: 9px; }
/* Info tooltips inside settings: reset the uppercase inherited from the label,
   and anchor at the icon opening down-right so left-edge icons never clip. */
.settings-body .info-dot[data-tip]:hover::after {
  text-transform: none; letter-spacing: 0;
  left: 0; right: auto; transform: none;
  top: calc(100% + 8px); bottom: auto;
  width: 200px;
}

/* ── Settings · Apple-style drill-in ──────────────────
   Root = vertical list (General/AI/Advanced). Tap a row → drill into the
   detail pane; the detail header shows a back button + the section title. */
.settings-head-detail { display: none; }
.settings-panel[data-view="detail"] .settings-head-root   { display: none; }
.settings-panel[data-view="detail"] .settings-head-detail { display: flex; }
.settings-panel[data-view="root"]   .settings-detail      { display: none; }
.settings-panel[data-view="detail"] .settings-list        { display: none; }

/* both headers share the same height/padding so the panel never jumps */
.settings-header { min-height: 58px; }
.settings-head-detail { align-items: center; justify-content: flex-start; gap: 10px; }
.settings-back {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: none; padding: 0;
  background: none; border: none; cursor: pointer;
  color: var(--purple-bright); border-radius: 9px;
  transition: background .15s, color .15s; }
.settings-back svg { width: 22px; height: 22px; }
.settings-back:hover { background: var(--purple-dim); color: var(--purple); }
.settings-detail-title { font-size: var(--fs-title); font-weight: 700; color: var(--text-primary); letter-spacing: .2px; }
.settings-detail-close { margin-left: auto; }

/* Root list rows */
.settings-list { display: flex; flex-direction: column; gap: 8px; }
.snav-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; text-align: left; padding: 14px var(--sp-lg);
  background: rgba(168,85,247,0.04); border: 1px solid var(--line-subtle); border-radius: 12px;
  cursor: pointer; font-family: var(--font); transition: background .15s, border-color .15s; }
.snav-row:hover { background: var(--purple-dim); border-color: var(--line-normal); }
.snav-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.snav-name { font-size: var(--fs-value); font-weight: 700; color: var(--text-primary); }
.snav-sub  { font-size: var(--fs-micro); color: var(--text-tertiary); line-height: 1.45; }
.snav-chev { width: 18px; height: 18px; flex: none; color: var(--text-tertiary); }

/* Detail panes — only the active one renders */
.settings-detail .settings-pane { display: none; }
.settings-detail .settings-pane[data-active="true"] { display: flex; flex-direction: column; gap: var(--sp-lg); }

/* Apple-style item: name (purple bold) + faded description + control */
.set-item { display: flex; flex-direction: column; gap: 6px; }
.set-item-name { font-size: var(--fs-value); font-weight: 700; color: var(--purple-bright); letter-spacing: .2px; }
.set-item-desc { font-size: var(--fs-micro); color: var(--text-tertiary); line-height: 1.5; margin-bottom: 2px; }
.set-group-title { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-secondary); }
.set-group-title-spaced { margin-top: var(--sp-md); }

/* Toggle item: text block on the left, switch on the right, vertically centered */
.set-item-toggle { flex-direction: row; align-items: center; justify-content: space-between; gap: 16px; }
.set-item-toggle .set-item-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.set-item-toggle .set-item-desc { margin-bottom: 0; }

/* (v0.11.11) Icon + text-stack rows (layout.md pattern).
   Icons render at 16px on a shared left axis; color follows the item name. */
.set-item-head { display: flex; align-items: flex-start; gap: 10px; }
.set-ico {
  flex: 0 0 auto; width: 16px; height: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--purple-bright);
  margin-top: 1px;              /* optical align with the name's cap height */
}
.set-ico svg { width: 100%; height: 100%; }
.set-item-head .set-item-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.set-item-head .set-item-desc { margin-bottom: 0; }
/* Toggle rows with an icon: icon pins to the title line, control stays centered */
.set-item-toggle .set-ico { align-self: flex-start; margin-top: 2px; }
.set-item-toggle .set-item-text { flex: 1; }
/* Hairline divider between sibling rows inside a settings card */
.settings-card .set-divider { height: 1px; background: var(--line-subtle); margin: 0; }
/* (v0.11.11) Buttons inside toggle rows: compact pill (Ollama Sign-In style),
   never flex-grow — the row's space-between was stretching .btn { flex:1 }. */
.set-item-toggle .btn {
  flex: 0 0 auto; width: auto; height: 32px;
  padding: 0 22px; border-radius: 9px;
  font-size: var(--fs-micro);
}

/* ── (v0.12.3) Caption · unified corrected preview ─────────────────────── */
/* Legend sits right of the Preview title: green = corrected, red = original */
.cap-preview-head { display: flex; align-items: center; justify-content: space-between; }
.cap-legend { display: inline-flex; align-items: center; gap: 6px; font-size: 10px; color: var(--text-tertiary); letter-spacing: .04em; }
.lg-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.lg-dot + * { margin-right: 2px; }
.lg-green { background: #34d399; }
.lg-red   { background: #ff4d5e; margin-left: 8px; }
/* AI-corrected word: green, hover pops a solid square bubble ABOVE showing
   the original (red, no strikethrough). The bubble overlays lines above —
   solid background, high z-index — and collapses on mouse-out (pure CSS). */
.cap-fix { color: #34d399; font-weight: 600; position: relative; cursor: default; border-radius: 3px; }
.cap-fix:hover { background: rgba(52,211,153,0.12); }
.cap-fix:hover::after {
  content: attr(data-orig);
  position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  background: #16121f;                       /* solid — must cover lines above */
  color: #ff4d5e; font-weight: 600; font-size: var(--fs-micro);
  border: 1px solid rgba(255,77,94,0.35); border-radius: 8px;
  padding: 5px 10px; white-space: nowrap;
  z-index: 40; pointer-events: none;
  box-shadow: 0 8px 22px rgba(0,0,0,0.55);
}
/* Empty data-orig (pure insertion — no original word) → no bubble */
.cap-fix[data-orig=""]:hover::after { display: none; }
/* First-line bubble pops DOWNWARD so the header doesn't clip it (#1) */
.cap-fix-down:hover::after {
  bottom: auto; top: calc(100% + 6px);
  z-index: 60;
}

/* License tier colors + custom colored tooltip (stays inside the card) */
.about-val.tier-free { color: #34d399; }
.about-val.tier-full { color: #f59e0b; }
.about-val.tier-ent  { color: #a855f7; }
.about-val.tier-beta { color: #3b82f6; }

/* ── First-launch email onboarding ─────────────────── */
.welcome-overlay { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; background: rgba(10,7,18,0.86); backdrop-filter: blur(6px); padding: 24px; }
.welcome-overlay.hidden { display: none; }
.welcome-card {
  width: 320px; max-width: 92vw; display: flex; flex-direction: column;
  padding: 28px 24px; text-align: center;
  background: var(--bg-surface, #1a1326); border: 1px solid var(--line-subtle);
  border-radius: var(--r-lg, 16px);
  box-shadow: 0 18px 60px -12px rgba(0,0,0,0.7), 0 0 40px -16px rgba(168,85,247,0.5);
  animation: aboutPop 0.18s ease-out;
}
.welcome-title { font-size: var(--fs-h2, 20px); font-weight: 700; color: var(--text-primary); margin-bottom: 8px; }

/* (C2) Welcome hero — Premiere-style: logo left, wordmark right */
.welcome-hero {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-bottom: 20px;
}
.welcome-logo {
  width: 54px; height: 54px;
  flex-shrink: 0;
  filter: drop-shadow(0 0 9px rgba(168, 85, 247, 0.55));
}
.welcome-hero-text { text-align: left; }
.welcome-hi {
  font-size: var(--fs-small);
  color: var(--text-secondary);
  letter-spacing: 0.02em;
  margin-bottom: 1px;
}
.welcome-wordmark { font-size: 27px; line-height: 1.05; letter-spacing: -0.01em; }
.welcome-sub { font-size: var(--fs-small); color: var(--text-secondary); line-height: 1.5; margin-bottom: 20px; }
.welcome-input {
  width: 100%; box-sizing: border-box; background: var(--bg-input); border: 1px solid var(--line-normal);
  border-radius: 10px; padding: 12px 14px; color: var(--text-primary);
  font-family: var(--font); font-size: var(--fs-small); outline: none; text-align: center; transition: border-color .15s;
}
.welcome-input::placeholder { color: var(--text-tertiary); }
.welcome-input:focus { border-color: var(--purple); }
.welcome-input.invalid { border-color: #ef4444; }
.welcome-error { margin-top: 8px; font-size: var(--fs-micro); color: #f87171; }
.welcome-error.hidden { display: none; }
.welcome-btn {
  margin-top: 16px; width: 100%; height: 46px; border: none; border-radius: 10px; cursor: pointer;
  background: var(--purple); color: #fff; font-family: var(--font); font-size: var(--fs-label); font-weight: 700;
  transition: background .15s, opacity .15s;
}
.welcome-btn:hover:not(:disabled) { background: var(--purple-bright); }
.welcome-btn:disabled { opacity: 0.65; cursor: default; }
.license-tip .lt { font-size: var(--fs-micro); white-space: nowrap; }

/* About card: Zalo link sits at the top-right of the License body */
.about-pane[data-apane="license"] { position: relative; }
.zalo-link {
  position: absolute; top: 0; right: 0; z-index: 5;
  width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--text-tertiary); cursor: pointer; transition: color .15s;
}
.zalo-link svg { width: 20px; height: 20px; }
.zalo-link:hover { color: var(--purple-bright); }
.zalo-tip {
  position: absolute; top: calc(100% + 6px); right: 0; white-space: nowrap;
  padding: 6px 10px; background: var(--bg-card-hi); border: 1px solid var(--line-normal);
  border-radius: 8px; font-size: var(--fs-micro); color: var(--text-secondary);
  box-shadow: 0 8px 24px rgba(0,0,0,0.6);
  opacity: 0; transform: translateY(-4px); pointer-events: none; transition: opacity .15s, transform .15s;
}
.zalo-link:hover .zalo-tip { opacity: 1; transform: translateY(0); }

/* License activation row (shown only when Type is "Free") */
.activate-cluster { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; }
.activate-cluster.hidden { display: none; }
.activate-row { display: flex; gap: 8px; align-items: center; }
.activate-row.hidden { display: none; }
.activate-input {
  flex: 1; background: var(--bg-input); border: 1px solid var(--line-normal); border-radius: 9px;
  padding: 9px 12px; color: var(--text-primary); font-family: var(--font); font-size: var(--fs-small); outline: none;
}
.activate-input:focus { border-color: var(--purple); }
.activate-input::placeholder { color: var(--text-tertiary); }
.activate-btn {
  flex: none; width: 38px; height: 38px; display: flex; align-items: center; justify-content: center;
  background: var(--purple); color: #fff; border: none; border-radius: 9px; cursor: pointer; transition: background .15s;
}
.activate-btn:hover { background: var(--purple-bright); }
.activate-btn svg { width: 18px; height: 18px; }
/* Multi-line tooltip (license tiers) */
.info-dot.info-list[data-tip]:hover::after { white-space: pre-line; width: 230px; }
.about-close { margin: 4px 20px 20px; width: calc(100% - 40px); justify-content: center; padding: 12px 16px; }

/* Cut options inside the transcript review */
.review-options { margin-top: var(--sp-md); margin-bottom: var(--sp-sm); }

/* ── Caption marker palette + per-line marker pin ── */
.marker-palette { display: flex; gap: 10px; margin: 4px 0 10px; align-items: center; }
.mk-swatch {
  width: 20px; height: 20px; border-radius: 50%; cursor: pointer;
  border: 2px solid transparent; box-sizing: border-box; transition: transform .1s;
}
.mk-swatch:hover { transform: scale(1.12); }
.mk-swatch.active { border-color: var(--text-primary, #fff); box-shadow: 0 0 0 2px rgba(255,255,255,0.15); }

/* ── Marker tab: palette labels + word paint ── */
.marker-palette { flex-wrap: wrap; }
.mk-swatch-wrap { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.mk-swatch-label { font-size: 10px; color: var(--text-secondary, #b8b3c4); letter-spacing: .02em; }
/* (v0.18.1) Marker words wear the SAME fixed plate as Hook chips — painting
   only recolours the plate, so nothing reflows while brushing. */
/* (v0.23.3) Marker words RESTORED to the old flowing-text spec (the layout Ryan
   confirmed reads easier). Bare text with a hair of side padding, riding on
   .tr-text's line-height — NOT a chip: no border, no plate, no flex-gap. Words
   are spaced by a trailing space in the token (see marker-ui.js), the way the
   old build did it. Painting adds a background + weight; on this metric the
   weight change is absorbed by the line flow and doesn't shift the row (the
   chip build's jump came from its border+gap plate, now gone). */
.mk-text { font-size: var(--fs-small); color: var(--text-primary); line-height: 1.6; flex: 1; }
.mk-word {
  cursor: pointer; border-radius: 3px; padding: 0 1px;
  transition: background .08s;
  user-select: none; -webkit-user-select: none;
}
.mk-word:hover { background: rgba(255,255,255,0.08); }
.mk-word.painted { color: #15101f; font-weight: 600; }
.mk-line .tr-time { cursor: default; }

/* ── Silence: threshold knob + responsive control cards ── */
.silence-controls { display: flex; flex-direction: column; gap: 12px; margin: 12px 0; }
.ctrl-card {
  background: rgba(255,255,255,0.02); border: 1px solid #2c2340;
  border-radius: 12px; padding: 14px 16px;
}
.knob-card { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.knob-title {
  font-size: 11px; letter-spacing: .02em; color: var(--text-secondary, #b8b3c4);
  display: flex; align-items: center; gap: 6px; align-self: flex-start;
}
.th-knob { width: 118px; height: 118px; display: block; touch-action: none; cursor: ns-resize; user-select: none; }
.sliders-wrap { display: flex; flex-direction: column; gap: 12px; }
.sliders-wrap .ctrl-card .control { margin: 0; }

/* Horizontal only when the panel is wide enough (knob left, sliders right) */
@media (min-width: 640px) {
  .silence-controls { flex-direction: row; align-items: stretch; }
  .knob-card { flex: 0 0 auto; justify-content: center; }
  .sliders-wrap { flex: 1 1 0; min-width: 0; justify-content: center; }
}

/* Empty waveform placeholder */
.wave-placeholder {
  display: flex; align-items: center; gap: 10px; justify-content: center;
  padding: 22px 16px; color: var(--text-secondary, #9a93ad);
  font-size: 12px; text-align: center; border: 1px dashed #34284d; border-radius: 12px;
}
.wave-placeholder b { color: #c9b6f0; }

/* Backup checkbox row (EasyTimeline style) */
.check-row { display: flex; align-items: center; gap: 10px; cursor: pointer; margin: 12px 2px; user-select: none; }
.check-row input { position: absolute; opacity: 0; width: 0; height: 0; }
.check-row input:checked + .check-box { background: #a855f7; border-color: #a855f7; }
.check-row input:checked + .check-box::after {
  content: ''; position: absolute; left: 5px; top: 1px; width: 5px; height: 10px;
  border: solid #15101f; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.btn-run { width: 100%; }

/* ── Analyze button icon + analyzing waveform animation ── */
.btn-analyze { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.btn-analyze svg { flex-shrink: 0; }

.wave-analyzing { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 24px 16px; }
.wave-bars { display: flex; align-items: center; gap: 4px; height: 40px; }
.wave-bars span {
  width: 4px; height: 10px; border-radius: 2px; background: #a855f7;
  animation: waveBar 1s ease-in-out infinite;
}
.wave-bars span:nth-child(1){animation-delay:0s}   .wave-bars span:nth-child(2){animation-delay:.08s}
.wave-bars span:nth-child(3){animation-delay:.16s}  .wave-bars span:nth-child(4){animation-delay:.24s}
.wave-bars span:nth-child(5){animation-delay:.32s}  .wave-bars span:nth-child(6){animation-delay:.4s}
.wave-bars span:nth-child(7){animation-delay:.48s}  .wave-bars span:nth-child(8){animation-delay:.56s}
.wave-bars span:nth-child(9){animation-delay:.64s}  .wave-bars span:nth-child(10){animation-delay:.72s}
.wave-bars span:nth-child(11){animation-delay:.6s}  .wave-bars span:nth-child(12){animation-delay:.5s}
.wave-bars span:nth-child(13){animation-delay:.4s}  .wave-bars span:nth-child(14){animation-delay:.3s}
@keyframes waveBar { 0%,100% { height: 8px; opacity:.55 } 50% { height: 36px; opacity:1 } }
.wave-analyzing-label { font-size: 12px; color: var(--text-secondary, #b8b3c4); letter-spacing: .02em; }
#rep-analyzing-label { transition: opacity .15s ease; }

/* Clickable waveform (seek playhead) */
.silence-canvas { cursor: crosshair; }

/* ── Process / Done modal (EasyTimeline-style ring with % in center) ── */
.proc-overlay {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(10,7,16,0.66); backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
}
.proc-overlay.hidden { display: none; }
.proc-card {
  position: relative; width: 280px; max-width: 84vw;
  background: #1a1326; border: 1px solid #36284f; border-radius: 16px;
  padding: 22px 22px 26px; text-align: center;
  box-shadow: 0 16px 50px rgba(0,0,0,0.5);
}
.proc-close {
  position: absolute; top: 10px; right: 10px; width: 26px; height: 26px;
  border: none; background: rgba(255,255,255,0.06); color: var(--text-secondary,#b8b3c4);
  border-radius: 7px; cursor: pointer; font-size: 13px;
}
.proc-close:hover { background: rgba(255,255,255,0.12); }
.proc-title { font-size: 15px; font-weight: 700; color: #fff; margin-bottom: 4px; }
.proc-sub { font-size: 12px; color: var(--text-secondary,#b8b3c4); min-height: 16px; margin-bottom: 14px; white-space: pre-line; }
.proc-ring-wrap { position: relative; width: 120px; height: 120px; margin: 4px auto 0; }
.proc-ring { transform: rotate(-90deg); }
.proc-ring-bg { fill: none; stroke: #2a2140; stroke-width: 7; }
.proc-ring-fg {
  fill: none; stroke: #a855f7; stroke-width: 7; stroke-linecap: round;
  stroke-dasharray: 263.89; stroke-dashoffset: 263.89;
  transition: stroke-dashoffset .3s ease;
  transform-box: fill-box; transform-origin: center;   /* pivot at the ring's own center — fixes the spin "fly-out" glitch */
}
.proc-ring.spin .proc-ring-fg {
  stroke-dasharray: 66 263.89; stroke-dashoffset: 0;
  animation: procSpin 1s linear infinite; transition: none;
}
@keyframes procSpin { to { transform: rotate(360deg); } }
.proc-pct {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: 'Space Mono', monospace; font-size: 22px; font-weight: 700; color: #fff;
}
.proc-pct.hidden { display: none; }
.proc-check { position: absolute; inset: 0; margin: auto; width: 120px; height: 120px; }
.proc-check.hidden { display: none; }
.proc-check circle { stroke: #34C759; stroke-width: 3.5; }
.proc-check path { stroke: #34C759; stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; }

/* #6: keep slider labels on one line; vertical layout handles narrow widths */
.control-label { white-space: nowrap; }
.control-head { gap: 10px; }
.control-value { white-space: nowrap; flex-shrink: 0; }

/* ── Waveform transport (cut-preview playback) ── */
.wave-transport { display: flex; flex-direction: column; align-items: center; gap: 6px; margin-top: 10px; }
.wave-buttons { display: flex; align-items: center; justify-content: center; gap: 22px; }
.wave-play {
  width: 40px; height: 40px; border-radius: 50%; border: none; cursor: pointer;
  background: #a855f7; color: #15101f; display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; transition: background .12s, transform .08s;
}
.wave-play:hover { background: #b975f9; }
.wave-play:active { transform: scale(0.94); }
.wave-skip {
  position: relative; width: 34px; height: 34px; border: none; background: transparent;
  color: var(--text-secondary, #b9a8d9); cursor: pointer; display: flex; align-items: center;
  justify-content: center; transition: color .12s, transform .08s; flex-shrink: 0;
}
.wave-skip:hover { color: var(--purple-bright, #c9a6ff); }
.wave-skip:active { transform: scale(0.92); }
.wave-skip .skip-n {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: 'Space Mono', monospace; font-size: 8px; font-weight: 700; padding-top: 1px;
}
.ic-play.hidden, .ic-pause.hidden { display: none; }

/* #1: info-dot tooltip BELOW (for panel titles near the top) */
/* Panel-title tips open to the RIGHT of the dot.
   RULE (v0.13.13): never centre a tooltip on an axis where long content can
   overflow the viewport — anchor an EDGE to the trigger instead. Top-aligning
   here means a tall tip only grows DOWNWARD, so it can never escape the top. */
.info-dot.info-below[data-tip]:hover::after {
  bottom: auto; top: -4px;
  left: calc(100% + 10px); right: auto;
  transform: none;
  max-width: min(320px, 58vw); white-space: normal;
}
.panel-title { display: flex; align-items: center; gap: 8px; }
.panel-title .info-dot { width: 16px; height: 16px; }

/* Drag-to-strike: no text selection while painting */
.transcript-list.painting, .transcript-list.painting * { user-select: none; }

/* #8: per-line marker circle (click/drag to bulk-fill a line with the active color) */
.mk-linecheck {
  flex-shrink: 0; width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid var(--line-normal, #3a3550); cursor: pointer;
  margin-top: 3px;
  transition: border-color .1s, background .1s, transform .08s;
}
.mk-linecheck:hover { border-color: var(--purple, #a855f7); transform: scale(1.12); }
.mk-linecheck.filled { border-color: transparent; }
/* (v0.23.2) Circle + timecode + pen stay PINNED TO THE TOP of the card, exactly
   like .hook-row — the old `align-items: center` floated them to the middle of
   a multi-line sentence. Gap and timecode width now match the Hook row too, so
   the text column starts at the same offset and never runs into the pen.
   Scoped to .mk-line: .tr-time is shared with the Repeats tab. */
/* (v0.23.4) column-gap only. .mk-note is a flex-basis:100% child, so it ALWAYS
   opens a second flex line even while collapsed (max-height:0) — and flex `gap`
   applies between lines too, so a shorthand gap parked a permanent row-gap of
   dead space under every card and pushed the cluster visually high. The note
   supplies its own spacing via .mk-note.open { margin-top }. */
.mk-line { align-items: flex-start; column-gap: var(--sp-sm); row-gap: 0; }
.mk-line .tr-time { min-width: 52px; }

/* Marker note — pen toggle + collapsible input inside the line card.
   (v0.23.2) The pen now wears the EXACT .hook-eye box (20x20 button, 12x12
   glyph) instead of 28/16, and the state colour rides on the GLYPH: the old
   sticker artwork carried its own filled frame, so saving turned a green square
   green rather than the pen. Idle grey → editing purple → saved green. */
.mk-line { flex-wrap: wrap; }
.mk-pen {
  flex: none; width: 20px; height: 20px; border: 1px solid transparent;
  border-radius: 6px; cursor: pointer;
  background: var(--bg-card); color: var(--text-tertiary);
  display: inline-flex; align-items: center; justify-content: center; margin-top: 2px;
  transition: color .15s, border-color .15s;
  /* Hidden, NOT removed — the same trick as .hook-eye-spacer. If the pen were
     display:none the text column would widen, then snap narrower the instant a
     line got its first mark: another source of the text jump Ryan reported. */
  visibility: hidden;
}
.mk-line.has-mark .mk-pen { visibility: visible; }
.mk-pen svg { width: 12px; height: 12px; fill: currentColor; }
.mk-pen:hover { color: var(--purple-bright); border-color: var(--purple-glow); }
.mk-pen.is-open { color: var(--purple-bright); border-color: var(--purple-glow); }
.mk-pen.is-saved { color: #34d399; border-color: rgba(52,211,153,.5); }
.mk-note { flex-basis: 100%; max-height: 0; overflow: hidden; opacity: 0;
  transition: max-height .22s ease, opacity .18s, margin-top .22s; }
.mk-note.open { max-height: 140px; opacity: 1; margin-top: 8px; }
.mk-note textarea {
  width: 100%; min-height: 56px; resize: vertical; border-radius: 8px;
  background: var(--bg-input); border: 1px solid var(--line-normal);
  color: var(--text-primary); font: inherit; font-size: 12px; line-height: 1.5; padding: 7px 9px;
}
.mk-note textarea::placeholder { color: var(--text-disabled); }
.mk-note textarea:focus { outline: none; border-color: var(--line-strong); box-shadow: 0 0 0 2px var(--purple-dim); }

/* #2: empty preview placeholder (before transcribe) */
.preview-empty {
  border: 1px dashed var(--line-normal, #3a3550); border-radius: var(--r-md, 12px);
  padding: 16px; margin-top: 14px; background: rgba(255,255,255,0.015);
}
.preview-empty.hidden { display: none; }
.empty-note {
  margin-top: 14px; padding: 18px 14px; text-align: center;
  font-size: 12px; color: var(--text-secondary, #b8b3c4); line-height: 1.5;
  border: 1px dashed var(--line-normal, #3a3550); border-radius: var(--r-sm, 8px);
}
.empty-note b { color: var(--purple-bright, #c084fc); }

/* #2: caption — slider in a card */
.option-card {
  border: 1px solid var(--line-normal, #2a2140); border-radius: var(--r-md, 12px);
  background: rgba(255,255,255,0.02); padding: 14px 16px; margin-top: 6px;
}

/* #4: format action row — Reset (left) + Apply (right) */
/* (v0.13.14) generalized: the 34/66 Reset|Apply split is shared by Reframe AND
   Caption — any .btn-secondary/.btn-primary pair inside a split row gets it. */
.action-row-split { display: flex; gap: 10px; }
.action-row-split .btn-secondary { flex: 0 0 34%; }
.action-row-split .btn-primary { flex: 1; }

/* Caption: Gen + Apply buttons sit in a row below the Words-per-line slider */
.action-row.cap-actions { margin-top: 10px; }
/* Marker target toggle: give it breathing room from the transcript above (#2) */
/* #2: match the Format tab's title→content gap (Caption sat too tight) */
[data-view="caption"] .panel-title + .ctrl-card { margin-top: var(--sp-md); }

/* ── CAPTION CONTROLS (scroll steppers + comma toggle) ───── */
.cap-stepper-row { display: flex; gap: 14px; }
.cap-field { flex: 1; display: flex; flex-direction: column; gap: 8px; }
.cap-field-label {
  justify-content: center;          /* center the label over its box */
  text-align: center;
  text-transform: uppercase;        /* easier to read at a glance */
  letter-spacing: 0.04em;
  font-size: var(--fs-micro);
  color: var(--text-secondary);
}
/* Scroll the box to change the value (no +/- buttons). */
.stepper {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-input); border: 1px solid var(--line-subtle);
  border-radius: var(--r-md); padding: 11px 4px;
  user-select: none; cursor: ns-resize;
  transition: border-color .15s, background .15s;
}
.stepper:hover { border-color: var(--purple); background: var(--purple-dim); }
.stepper { cursor: ns-resize; user-select: none; touch-action: none; }
.stepper.stp-dragging { border-color: var(--purple); background: var(--purple-dim); }
.stp-val { font-size: var(--fs-value); font-weight: 700; color: var(--text-primary); min-width: 2ch; text-align: center; }
.cap-break-group { margin-top: var(--sp-lg); }
[data-view="caption"] .cap-actions { margin-top: var(--sp-lg); }

/* Caption Transcribe button (top): keep the standard title→content gap that the
   other tabs use (.action-row margin-top), plus breathing room before controls. */
.cap-transcribe-row { margin-bottom: var(--sp-lg); }
.cap-transcribe-btn { width: 100%; }

/* Robot/AI icon inside a button (Find repeats) */
.btn .btn-ico { width: 15px; height: 15px; flex: 0 0 auto; }

/* Find repeats locked into manual flow: grayed but still hoverable for its tip.
   NOTE: do NOT use opacity here — it would also fade the ::after tooltip (a child),
   letting the text underneath bleed through. Gray via background + color instead. */
.btn-ai { position: relative; }
.btn-ai.is-locked {
  background: var(--bg-card-hi);
  color: #6f6688;            /* muted label + icon (icon uses currentColor) */
  box-shadow: inset 0 0 0 1px var(--line-subtle);
  cursor: help;
}
.btn-ai.is-locked:hover { transform: none; background: var(--bg-card-hi); }
/* (v0.20.0) AI-disclaimer hover — static data-ai-tip on the AI buttons.
   Separate attribute so the dynamic is-locked data-tip (set/removed by JS)
   keeps working; when a button IS locked, the locked reason wins. */
.btn-ai:not(.is-locked)[data-ai-tip] { position: relative; }
/* (v0.21.0) On hover the btn's transform makes it a stacking context, trapping
   the z-60 tooltip below the later positioned steppers. Elevate the whole button
   on hover so the disclaimer paints OVER the "Lines per caption" box (Ryan: OK to
   overlap the stepper). Covers both the AI-disclaimer and the locked-reason tip. */
.btn-ai[data-ai-tip]:hover, .btn-ai.is-locked[data-tip]:hover { z-index: 300; }
.btn-ai:not(.is-locked)[data-ai-tip]:hover::after {
  content: attr(data-ai-tip);
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: 240px;
  padding: 10px 12px;
  background: #2e2148;
  border: 1px solid var(--line-normal);
  border-radius: var(--r-sm);
  font-family: var(--font);
  font-size: var(--fs-micro);
  font-weight: 400;
  line-height: 1.45;
  color: var(--text-secondary);
  text-transform: none;
  letter-spacing: normal;
  white-space: normal;
  z-index: 60;
  pointer-events: none;
}
.btn-ai.is-locked[data-tip]:hover::after {
  content: attr(data-tip);
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: 240px;
  padding: 10px 12px;
  background: #2e2148;        /* fully opaque */
  border: 1px solid var(--line-normal);
  border-radius: var(--r-sm);
  font-family: var(--font);
  font-size: var(--fs-micro);
  font-weight: 400;
  line-height: 1.45;
  color: var(--text-secondary);
  text-align: left;
  white-space: normal;
  z-index: 50;
  box-shadow: 0 8px 24px rgba(0,0,0,0.6);
  pointer-events: none;
}

/* #3: faded SRT sample inside the empty caption placeholder */
.srt-sample { margin: 10px 0 4px; display: flex; flex-direction: column; gap: 8px; opacity: .5; }

/* #3: faded transcript sample inside the empty marker placeholder */
.mk-sample { margin: 10px 0 4px; display: flex; flex-wrap: wrap; gap: 6px; opacity: .55; }
.mk-w { padding: 2px 7px; border-radius: 6px; font-size: 12px; color: var(--text-secondary,#cfc9da); }

/* Phase 4: Format frame-rate selector */
.fmt-settings-row { display: flex; gap: 12px; margin: 14px 0; }
.fmt-field { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.fmt-field .control-label { font-size: var(--fs-micro); color: var(--text-secondary); }
.fmt-field .fmt-select { width: 100%; }
.fmt-select {
  -webkit-appearance: none; appearance: none;
  background-color: rgba(255,255,255,0.04); color: var(--text-primary,#efeaf6);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M4 6l4 4 4-4' stroke='%23a855f7' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center;
  border: 1px solid var(--line-normal,#2a2140); border-radius: 8px;
  padding: 8px 34px 8px 14px; font-family: 'Space Mono', monospace; font-size: 13px; cursor: pointer;
  min-width: 120px;
}
.fmt-select:focus { outline: none; border-color: var(--purple,#a855f7); }

/* #7: frame-rate dropdown options — dark, on-concept (not white) */
.fmt-select option { background: #1a1326; color: #efeaf6; }
.fmt-select option:checked { background: #a855f7; color: #fff; }

/* #2: transcribe animation framed inside the transcript preview area */
#rep-analyzing { padding: 14px 8px 4px; }
#rep-analyzing.hidden { display: none; }

/* #5: marker placeholder palette — display-only demo */
.mk-palette-demo { margin: 14px 0 6px; pointer-events: none; opacity: .92; }

/* AI Find greyed while offline */
.net-offline { opacity: 0.5; }

/* Audio preview header + legend (legend reuses Repeats .review-legend/.lg) */
.wave-preview-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px 14px; flex-wrap: wrap; margin-bottom: 8px; }
.wave-preview-title { font-size: 13px; font-weight: 700; color: var(--text-primary, #efeaf7); letter-spacing: .2px; }
.wave-preview-head .review-legend { flex-wrap: wrap; margin-left: auto; }

.wave-canvas-wrap { position: relative; }

/* ═══════════════════ HOOK TAB (v0.13.4) ═══════════════════ */

/* Workspace header with legend on the right */
.hook-head { display: flex; align-items: center; justify-content: space-between; }
.hook-legend { display: flex; gap: 5px; flex-wrap: wrap; justify-content: flex-start; row-gap: 3px; }
.hook-legend.is-disabled { opacity: 0.35; pointer-events: none; }
/* (v0.15.0) Compact brushes — dot + type sized down to read like the Repeats
   legend, and the row WRAPS on narrow panels exactly like Repeats does. */
.hook-brush {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 999px; cursor: pointer;
  background: var(--bg-card); border: 1px solid transparent;
  color: var(--text-secondary); font-size: var(--fs-micro); font-family: inherit;
  transition: border-color .15s, color .15s, box-shadow .15s;
}
.hook-brush .hb-dot { width: 6px; height: 6px; border-radius: 50%; }
.hook-brush-main .hb-dot { background: #ffe600; }
.hook-brush-sub  .hb-dot { background: #a855f7; }
/* (v0.14.3) impact/explain are full paint brushes now — same interaction as
   Highlight/Basic. Legend order per Ryan: Impact, Explain, Highlight, Basic. */
.hook-brush-impact  .hb-dot { background: #f43f5e; }
.hook-brush-explain .hb-dot { background: #22c55e; }
.hook-brush-main.is-on { border-color: rgba(255,230,0,.55); color: #ffe600; box-shadow: 0 0 12px -6px rgba(255,230,0,.6); }
.hook-brush-sub.is-on  { border-color: rgba(168,85,247,.6); color: #c9a4f7; box-shadow: 0 0 12px -6px rgba(168,85,247,.7); }
.hook-brush-impact.is-on  { border-color: rgba(244,63,94,.6);  color: #ff9fb0; box-shadow: 0 0 12px -6px rgba(244,63,94,.7); }
.hook-brush-explain.is-on { border-color: rgba(34,197,94,.55); color: #86efac; box-shadow: 0 0 12px -6px rgba(34,197,94,.7); }

.hook-empty-ico { width: 34px; height: 34px; color: var(--text-disabled); margin: 14px auto 8px; display: block; }

/* (v0.18.0) Hook rows unified with the Repeats density: same card row as
   .tr-line (no divider list), same rail + live-timecode playhead language. */
.hook-list { padding-left: 4px; }
.hook-row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: var(--sp-sm) var(--sp-md);
  padding-left: calc(var(--sp-md) + 3px);   /* rail space on BOTH states */
  border-radius: var(--r-md);
  background: rgba(255,255,255,0.02);
  transition: background 0.12s;
}
.hook-row.is-playing {
  background: rgba(var(--play-rgb), 0.08);
  box-shadow: inset 3px 0 0 rgb(var(--play-rgb));
}
.hook-tc {
  flex: none; font-family: 'Space Mono', monospace; font-size: 10px;
  color: var(--tc-idle); padding-top: 4px; cursor: pointer; min-width: 52px;
  transition: color 0.12s;
}
.hook-row.is-playing .hook-tc { color: var(--tc-live); }
.hook-tc:hover { color: var(--purple-bright); }
.hook-words { flex: 1; display: flex; flex-wrap: wrap; gap: 3px; user-select: none; }
/* (v0.18.1) Chips back to the v0.16.3 FIXED-PLATE look, Ryan's call: every
   word wears the same plate metrics at all times (12px, 2×6 padding), painting
   only recolours — zero layout shift, no "words jump when brushing". */
.hook-chip {
  padding: 2px 6px; border-radius: 5px; cursor: pointer;
  background: var(--bg-input); color: var(--text-secondary);
  font-size: 12px; line-height: 1.45; border: 1px solid transparent;
  transition: background .1s, color .1s;
}
.hook-chip:hover { border-color: var(--purple-glow); }
.hook-chip.is-main { background: #ffe600; color: #1a1408; font-weight: 600; }
.hook-chip.is-sub  { background: rgba(168,85,247,.32); color: #e6d5ff; }
/* (v0.14.1) AI-only roles — impact = red, explain = green (Ryan's spec) */
.hook-chip.is-impact  { background: rgba(244,63,94,.34);  color: #ffd6dd; font-weight: 600; }
.hook-chip.is-explain { background: rgba(34,197,94,.30);  color: #d3f7e0; }
/* (v0.14.3) .hook-key removed — impact/explain promoted to real brushes */
/* (v0.18.2) Eye capped BELOW the chip line height (chips ≈23px): its arrival
   no longer inflates the row — the box hugs the sentence the same with or
   without it. Spacer matches so text width never shifts either. */
.hook-eye {
  flex: none; width: 20px; height: 20px; border-radius: 6px; cursor: pointer;
  background: var(--bg-card); border: 1px solid transparent;
  color: var(--text-tertiary); display: flex; align-items: center; justify-content: center;
  margin-top: 2px;
}
.hook-eye svg { width: 12px; height: 12px; fill: currentColor; }   /* (v0.24.0) filled eye */
.hook-eye:hover { color: var(--purple-bright); border-color: var(--purple-glow); }
.hook-eye.is-saved { color: #34d399; border-color: rgba(52,211,153,.5); }
.hook-eye-spacer { flex: none; width: 20px; }
/* (v0.14.0) sizing comes from .action-row-split (34/66) — the old flex:1 on
   every .btn made the pair 50/50 and fought the shared split rule. */
.hook-actions { margin-top: 14px; }
#btn-hook-ai { display: inline-flex; align-items: center; justify-content: center; gap: 7px; }
.hk-ai-ico { display: inline-flex; }
.hk-ai-ico .hk-ico { width: 14px; height: 14px; }
/* Icons injected from HookIcons into existing chrome (Settings rows, buttons) */
.set-ico .hk-ico { width: 17px; height: 17px; }
.btn-ico .hk-ico { width: 15px; height: 15px; }
.btn-ico[data-hkico] { display: inline-flex; align-items: center; }

/* ── Focus Mode — Gameboy layout, backdrop covers the sidebar ── */
.hook-focus {
  position: fixed; inset: 0; z-index: 240;
  background: rgba(11,11,19,.85); backdrop-filter: blur(5px);
  display: flex; align-items: center; justify-content: center; padding: 16px;
  overflow-y: auto;
}
.hook-focus.hidden { display: none; }
.hf-modal {
  position: relative; background: var(--bg-panel); border: 1px solid var(--purple-dim);
  border-radius: 18px;
  /* (v0.18.1) Ryan: the chip row grew the modal. It's absolute now (zero flow
     height, mirrors the absolute ✕): top padding hosts the chip, bottom
     padding + gap shaved so total height lands at/below the v0.16.3 modal. */
  padding: 38px 22px 16px; margin: auto;
  display: flex; flex-direction: column; gap: 10px;
}
/* (v0.18.0→v0.18.1) Status chip — pinned top-left inside the top padding:
   role dot + which MOGRT the selected layer edits ("Highlight - Special Word"). */
.hf-status {
  position: absolute; top: 16px; left: 28px;
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-secondary); letter-spacing: .01em;
}
.hf-status-dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: #ffe600; box-shadow: 0 0 8px -1px currentColor;
}
.hf-status-dot[data-role="main"]    { background: #ffe600; color: #ffe600; }
.hf-status-dot[data-role="sub"]     { background: #a855f7; color: #a855f7; }
.hf-status-dot[data-role="impact"]  { background: #f43f5e; color: #f43f5e; }
.hf-status-dot[data-role="explain"] { background: #22c55e; color: #22c55e; }
.hf-modal-wide { width: 100%; max-width: min(94vw, 780px); }
.hf-x {
  position: absolute; top: 12px; right: 14px; z-index: 2;
  background: transparent; border: none; color: var(--text-tertiary);
  font-size: 16px; cursor: pointer; line-height: 1; padding: 4px;
}
.hf-x:hover { color: var(--text-primary); }

/* Horizontal layout: square preview left, tabs + card right. Everything scales
   with the panel width — CEP panels get resized constantly. */
.hf-main { display: flex; gap: clamp(12px, 2.2vw, 22px); align-items: stretch; }
.hf-right { flex: 1 1 auto; display: flex; flex-direction: column; gap: 10px; min-width: 0; }

/* Square preview box — the sequence frame (portrait or landscape) is centred */
.hf-stagebox {
  flex: 0 0 auto; align-self: stretch;
  /* (v0.23.0) No more square: the purple backdrop now fills the column height
     and the reel shows its TRUE aspect (portrait / landscape / square) centred
     on it — so the layout is unmistakable and the preview is far larger. */
  width: clamp(240px, 34vw, 380px);
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-input); border: 1px solid var(--purple-dim); border-radius: 14px;
  padding: 12px;
}
.hf-stage {
  position: relative; overflow: hidden; border-radius: 6px;
  /* (v0.16.0) No black screen box — show only the source frame. */
  background: transparent; aspect-ratio: 9 / 16; height: 100%; width: auto;
  max-width: 100%; max-height: 100%;
}
/* (v0.14.7) contain, not cover: the backdrop JPEG is grabbed from the SOURCE
   media, whose aspect can differ from the sequence (e.g. 16:9 clip in a 1:1
   reframed sequence). cover crop-zoomed it — no black bars, text looked out of
   proportion vs content. contain shows the whole frame, bars included, exactly
   like the timeline after Set-to-Frame. */
.hf-frame { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; opacity: .8; background: transparent; }
.hf-safe { position: absolute; border: 1px dashed rgba(168,85,247,.28); pointer-events: none; border-radius: 3px; }
.hf-layers { position: absolute; inset: 0; }
.hf-layer {
  position: absolute; max-width: 88%; text-align: center; white-space: pre-line;   /* (v0.19.1) show wrapped hook lines — no more ellipsis clipping */
  color: #fff; font-weight: 700; line-height: 1.1; cursor: pointer;
  border: 1.5px dashed transparent; border-radius: 4px; padding: 1px 4px;
}
.hf-layer:hover { border-color: rgba(168,85,247,.5); }
.hf-layer.is-selected { border-color: var(--purple); }
/* (v0.22.0) Explain preview uses the full frame width and honours ONLY the
   Characters/Line breaks that _wrapAtChars already inserted — no extra soft-wrap
   at 88%, so preview lines match the imported MOGRT line for line. */
.hf-layer.is-explain { max-width: 96%; white-space: pre; }

/* Tab strip — icon over label */
.hf-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--purple-dim); }
.hf-tab {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 9px 2px 8px; cursor: pointer; background: transparent;
  border: none; border-radius: 10px 10px 0 0; position: relative;
  /* (v0.13.14) label size matches Settings' "Model Path" (.set-item-name) */
  color: var(--text-tertiary); font-size: var(--fs-value); font-family: inherit; font-weight: 700;
}
.hf-tab:hover { color: var(--text-secondary); }
.hf-tab.is-on { background: var(--bg-card); color: var(--purple-bright); }
.hf-tab.is-on::after {
  content: ''; position: absolute; left: 14%; right: 14%; bottom: -1px; height: 2px;
  background: var(--purple); border-radius: 2px; box-shadow: 0 0 10px var(--purple-glow);
}
.hf-tab .hk-ico { width: 17px; height: 17px; }
.hf-tab.is-on .hk-ico { color: var(--purple-bright); }
.hf-tab-lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }

/* Text pane: controls take the free space, Navigator keeps its own column so it
   can never overlap the size readout. */
.hf-text-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: start; }
/* (v0.21.6) Explain hides the D-pad → collapse to one column so the controls fill the freed space. */
.hf-text-row.is-explain { grid-template-columns: 1fr; }
.hf-text-ctrls { display: flex; flex-direction: column; gap: 11px; min-width: 0; }
.hf-navwrap {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 9px 11px; background: var(--bg-input); border-radius: 10px;
  border: 1px solid var(--purple-dim);
}
.hf-nav-title { font-size: 9px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-tertiary); }
.hf-dpad { display: grid; grid-template-columns: repeat(3, 22px); grid-template-rows: repeat(3, 22px); gap: 3px; }
.hf-dbtn {
  background: var(--bg-card); border: 1px solid var(--purple-dim); border-radius: 6px;
  color: var(--purple-bright); cursor: pointer;
  display: flex; align-items: center; justify-content: center; padding: 0;
}
.hf-dbtn:hover { border-color: var(--purple); }
.hf-dbtn:active { background: var(--purple-dim); box-shadow: 0 0 10px -3px var(--purple-glow); }
.hf-dbtn .hk-ico { width: 8px; height: 8px; }
.hf-d-up .hk-ico { transform: rotate(0deg); }
.hf-d-down .hk-ico { transform: rotate(180deg); }
.hf-d-left .hk-ico { transform: rotate(180deg); }
.hf-d-right .hk-ico { transform: rotate(0deg); }
.hf-d-center .hk-ico { width: 11px; height: 11px; }
.hf-d-up { grid-column: 2; grid-row: 1; }
.hf-d-left { grid-column: 1; grid-row: 2; }
.hf-d-center { grid-column: 2; grid-row: 2; border-radius: 50%; }
.hf-d-right { grid-column: 3; grid-row: 2; }
.hf-d-down { grid-column: 2; grid-row: 3; }

/* Property card */
.hf-card { background: var(--bg-card); border-radius: 12px; padding: 14px; display: flex; flex-direction: column; gap: 11px; }
/* Every tab reserves the height of the tallest one (Text: 4 rows + navigator)
   so switching tabs never makes the panel jump. */
.hf-pane { min-height: 190px; }
.hf-pane { display: flex; flex-direction: column; gap: 11px; }
.hf-pane.hidden { display: none; }
.hf-ctrl-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
/* (v0.13.14) bumped from --fs-micro — control text follows the Settings type
   scale so the Focus card reads at the same size as the Settings tab. */
.hf-ctrl-row .control-label { font-size: 11.5px; }
.hf-color { width: 30px; height: 22px; padding: 0; border: 1px solid var(--purple-dim); border-radius: 6px; background: transparent; cursor: pointer; }
/* Hex twin next to each swatch (#5) — Ryan works in hex, the native picker
   opens on an RGB pane we cannot configure from HTML. */
.hf-color-wrap { display: inline-flex; align-items: center; gap: 6px; }
.hf-hex {
  width: 62px; padding: 3px 6px; background: var(--bg-input);
  border: 1px solid var(--purple-dim); border-radius: 6px;
  color: var(--text-primary); font-family: 'Space Mono', monospace;
  font-size: 11px; text-transform: uppercase;
}
.hf-hex:focus { outline: none; border-color: var(--purple); }
/* #6: the size readout is now a typable number */
.hf-size-num {
  flex: none; width: 46px; padding: 3px 4px; background: var(--bg-input);
  border: 1px solid var(--purple-dim); border-radius: 6px;
  color: var(--purple-bright); font-family: 'Space Mono', monospace;
  font-size: 11.5px; text-align: right;
}
.hf-size-num:focus { outline: none; border-color: var(--purple); }
.hf-size-num::-webkit-inner-spin-button { display: none; }
.hf-size-wrap { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; }
/* An <input type=range> has an intrinsic width (~129px) and flex items default
   to min-width:auto, so without this the slider refuses to shrink and pushes the
   size readout out of the row. */
.hf-range { flex: 1 1 0; min-width: 0; accent-color: var(--purple); }
.hf-size-val { flex: none; font-family: 'Space Mono', monospace; font-size: 11.5px; color: var(--purple-bright); min-width: 34px; text-align: right; }
.hf-case-row { display: flex; gap: 5px; }
.hf-case { min-width: 38px; padding: 5px 9px; border-radius: 7px; cursor: pointer; background: var(--bg-input); border: 1px solid transparent; color: var(--text-secondary); font-size: 12px; font-family: 'Space Mono', monospace; }
.hf-case.is-on { color: var(--purple-bright); border-color: var(--purple-glow); background: var(--purple-dim); }
/* (v0.13.14) RULE: a dropdown chevron never sits flush against the edge —
   custom SVG arrow inset from the right + matching padding reserve, exactly
   like Reframe's .fmt-select. Native appearance is off so the OS arrow (which
   hugs the border) can't come back. Font bumped 11 → 12px (Settings scale). */
.hf-select {
  -webkit-appearance: none; appearance: none;
  background-color: var(--bg-input); color: var(--text-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M4 6l4 4 4-4' stroke='%23a855f7' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center;
  border: 1px solid var(--purple-dim); border-radius: 7px;
  font-size: 12px; padding: 5px 28px 5px 8px; cursor: pointer;
  max-width: 60%; flex: 1 1 auto; min-width: 0; font-family: inherit;
}
.hf-select:focus { outline: none; border-color: var(--purple); }

/* (v0.20.3) Font picker — trigger button keeps the old .hf-select footprint so
   the row layout ("Font | trigger") is unchanged; popover is CapCut-style.
   rgba only (no color-mix). */
.hf-font-trigger {
  -webkit-appearance: none; appearance: none; text-align: left;
  background-color: var(--bg-input); color: var(--text-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M4 6l4 4 4-4' stroke='%23a855f7' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center;
  border: 1px solid var(--purple-dim); border-radius: 7px;
  font-size: 12px; padding: 5px 28px 5px 8px; cursor: pointer;
  max-width: 60%; flex: 1 1 auto; min-width: 0; font-family: inherit;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hf-font-trigger:hover { border-color: var(--purple); }

.fp-pop {
  z-index: 300;
  background: #1a1326;
  border: 1px solid var(--purple-dim);
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.55);
  padding: 8px; max-height: 240px; display: flex; flex-direction: column;
}
.fp-search { padding: 2px 2px 8px; }
.fp-search-in {
  width: 100%; box-sizing: border-box;
  background: #0f0b18; color: var(--text-primary);
  border: 1px solid var(--purple-dim); border-radius: 8px;
  font-size: 12px; padding: 7px 10px; font-family: inherit;
}
.fp-search-in:focus { outline: none; border-color: var(--purple); }
.fp-list { overflow-y: auto; flex: 1; padding-right: 8px; }
.fp-sec {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-tertiary); padding: 8px 8px 4px;
  border-top: 1px solid rgba(255, 255, 255, 0.08); margin-top: 4px;
}
.fp-sec:first-child { border-top: none; margin-top: 0; }
.fp-sec-click { cursor: pointer; user-select: none; }
/* (v0.21.0) Compact rows, star on the LEFT → more fonts per screen. */
.fp-row {
  display: flex; align-items: center; justify-content: flex-start;
  padding: 4px 8px; min-height: 28px; border-radius: 8px; cursor: pointer; gap: 8px;
}
.fp-row:hover { background: var(--bg-card-hi); }
.fp-row-sel { background: rgba(168, 85, 247, 0.18); }
.fp-name { font-size: 12px; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; }
.fp-star {
  background: none; border: none; cursor: pointer; font-size: 13px;
  color: var(--text-tertiary); line-height: 1; padding: 0; flex: 0 0 auto;
  width: 18px; text-align: center;
}
.fp-star-on { color: #F59E0B; }
.fp-star-slot { visibility: hidden; pointer-events: none; }
.fp-empty { padding: 14px 8px; font-size: 12px; color: var(--text-tertiary); text-align: center; }
.hf-select option { background: #1a1326; color: #efeaf6; }
.hf-check-wrap { display: inline-flex; align-items: center; gap: 7px; font-size: 11px; color: var(--text-secondary); cursor: pointer; }
.hf-check-wrap input { accent-color: var(--purple); }
/* Long Form Mode — option-group above the Apply row */
.hook-longform-group { margin-top: 12px; }
/* Transcript-in-sync state — mirrors Caption's is-locked look: still clickable
   (re-transcribe any time), just visibly "up to date". */
.btn.is-synced { opacity: .62; }
.hf-applyall-row { justify-content: flex-start; gap: 6px; border-top: 1px solid var(--purple-dim); padding-top: 10px; }
.hf-applyall-wrap { display: inline-flex; align-items: center; gap: 7px; font-size: 11px; color: var(--text-secondary); cursor: pointer; }
.hf-applyall-wrap input { accent-color: var(--purple); }
/* (v0.20.2) CapCut footer — Save (purple, left) fills, Cancel (grey, right)
   fixed width. Replaces the single full-width pulsing Save. */
.hf-foot { display: flex; gap: 10px; margin-top: 4px; }
.hf-save {
  flex: 1; padding: 10px; border-radius: 10px;
  font-size: 13px; font-weight: 600;
  animation: hfPulse 2.4s ease-in-out infinite;
}
.hf-cancel-btn {
  flex: 0 0 auto; min-width: 96px; padding: 10px 16px;
  border-radius: 10px; font-size: 13px; font-weight: 600;
}
@keyframes hfPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(168,85,247,0); } 50% { box-shadow: 0 0 18px -2px var(--purple-glow); } }

/* ═══════════ (v0.24.1) ACCORDION GAMEBOY — scroll + presets + footer ═══════════
   The tab strip (.hf-tabs/.hf-tab) and the single .hf-card are retired; their
   old rules above are now dead but harmless. Cards stack in a scroll region;
   footer is pinned. rgba only (no color-mix — banned on CEP 12 Chromium). */
/* (v0.24.1) Bound the modal height so the middle scrolls; nudge the status chip
   off the corner (image-2 "sát lề" note). */
.hf-modal { max-height: min(90vh, 760px); padding: 44px 24px 18px; }
.hf-status { top: 18px; left: 30px; }
.hf-main { flex: 1 1 auto; min-height: 0; }
.hf-right { min-height: 0; }
.hf-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px; padding-right: 6px;
}
.hf-scroll::-webkit-scrollbar { width: 8px; }
.hf-scroll::-webkit-scrollbar-track { background: transparent; }
.hf-scroll::-webkit-scrollbar-thumb { background: var(--purple-dim); border-radius: 8px; }
.hf-scroll::-webkit-scrollbar-thumb:hover { background: var(--purple-glow); }

/* Quick Presets strip — horizontal scroll; More/Add New land in Phase 2. */
.hf-presets { display: flex; flex-direction: column; gap: 8px; }
.hf-presets-head { display: flex; align-items: center; justify-content: space-between; }
.hf-presets-title { font-size: 12px; color: var(--text-secondary); font-weight: 600; letter-spacing: .01em; }
/* (v0.24.3) Bare chevron (no circle). (v0.25.0) Disclosure-triangle pattern
   (like "Recents" in the chat rail): COLLAPSED points RIGHT (▶ — click to open),
   EXPANDED points DOWN (▼ — click to close). The border pair (right+bottom)
   points down at 45deg; -45deg turns it to point right. */
.hf-presets-toggle {
  width: 20px; height: 20px; flex: none; padding: 0;
  background: transparent; border: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.hf-presets-chev {
  width: 8px; height: 8px; margin-top: -3px;
  border-right: 2px solid var(--purple-bright); border-bottom: 2px solid var(--purple-bright);
  transform: rotate(45deg); transition: transform .18s ease;   /* EXPANDED = down */
}
.hf-presets-toggle:hover .hf-presets-chev { border-color: var(--text-primary); }
/* COLLAPSED = right. margin-left nudges the arrowhead back to optical centre. */
.hf-presets.is-collapsed .hf-presets-chev { transform: rotate(-45deg); margin-top: 0; margin-left: -2px; }
/* (v0.24.3) Tiles WRAP — no horizontal scroll. COLLAPSED clips to the first row
   (72px) so the user always sees a row of presets; expanding reveals the rest. */
.hf-presets-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.hf-presets.is-collapsed .hf-presets-grid { max-height: 72px; overflow: hidden; }
.hf-preset-tile {
  flex: 0 0 auto; width: 72px; height: 72px; border-radius: 12px;
  border: 2px solid transparent; background: var(--bg-input);
  overflow: hidden; cursor: pointer; position: relative; padding: 0;
  display: flex; align-items: center; justify-content: center;
}
.hf-preset-tile:hover { border-color: var(--purple-dim); }
.hf-preset-tile.is-on { border-color: var(--purple); box-shadow: 0 0 12px -2px var(--purple-glow); }
.hf-preset-tile img { width: 100%; height: 100%; object-fit: contain; pointer-events: none; display: block; }
/* (v0.24.2) Image-less preset (user-created): show the NAME centred in the tile. */
.hf-preset-label {
  padding: 4px; font-size: 10px; line-height: 1.15; text-align: center;
  color: var(--text-primary); font-weight: 600; word-break: break-word;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
/* (v0.24.3) Add-New "+" tile — purple glyph stacked over a "New" label. */
.hf-preset-add { color: var(--purple); flex-direction: column; gap: 3px; }
.hf-preset-add:hover { border-color: var(--purple); background: var(--purple-dim); }
.hf-preset-add .hk-ico { width: 20px; height: 20px; }
.hf-preset-add-lbl { font-size: 10px; font-weight: 700; color: var(--purple-bright); letter-spacing: .02em; }
/* (v0.24.3) Delete affordance — user presets only; appears on tile hover. */
.hf-preset-del {
  position: absolute; top: 2px; right: 2px; width: 16px; height: 16px; padding: 0;
  border: none; border-radius: 50%; cursor: pointer; z-index: 2;
  background: rgba(10, 8, 18, 0.82); color: var(--text-primary);
  display: none; align-items: center; justify-content: center; line-height: 1;
  font-size: 13px; font-weight: 700;
}
.hf-preset-tile:hover .hf-preset-del { display: inline-flex; }
.hf-preset-del:hover { background: #d64545; color: #fff; }
/* (v0.24.4) Rename affordance — user presets only; pencil, top-left, on hover. */
.hf-preset-ren {
  position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; padding: 0;
  border: none; border-radius: 50%; cursor: pointer; z-index: 2;
  background: rgba(10, 8, 18, 0.82); color: var(--text-primary);
  display: none; align-items: center; justify-content: center;
}
.hf-preset-tile:hover .hf-preset-ren { display: inline-flex; }
.hf-preset-ren:hover { background: var(--purple); color: #fff; }
.hf-preset-ren .hk-ico { width: 10px; height: 10px; }
/* (v0.24.4) Drag-reorder visuals for user presets. */
.hf-preset-tile.is-dragging { opacity: 0.4; }
.hf-preset-tile.is-drop-target { border-color: var(--purple); box-shadow: inset 0 0 0 2px var(--purple-glow); }
.hf-presets-empty { font-size: 11px; color: var(--text-tertiary); padding: 6px 2px; width: 100%; }

/* (v0.24.2) Static sections — no collapse, always open; a hairline divides the
   title from its content (Ryan). Header is a plain label, not clickable. */
.hf-acc { display: flex; flex-direction: column; gap: 10px; }
.hf-acc-card { background: var(--bg-card); border-radius: 12px; border: 1px solid var(--purple-dim); overflow: hidden; }
.hf-acc-card.hidden { display: none; }
.hf-acc-head {
  position: relative; width: 100%; display: flex; align-items: center; gap: 9px;
  padding: 11px 13px; background: transparent;
  color: var(--text-primary); font-size: 12.5px; font-weight: 600;
}
/* (v0.24.3) Divider between title and content — inset ~14px each end, faint,
   not a full-width rule (Ryan). */
.hf-acc-head::after {
  content: ''; position: absolute; left: 14px; right: 14px; bottom: 0; height: 1px;
  background: rgba(168, 85, 247, 0.16);
}
.hf-acc-ico { width: 16px; height: 16px; display: inline-flex; color: var(--purple-bright); flex: none; }
.hf-acc-ico .hk-ico { width: 16px; height: 16px; }
.hf-acc-lbl { flex: 1 1 auto; text-align: left; }
.hf-acc-body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 11px; }

/* Pinned footer — global Apply-to-all + Save/Cancel */
.hf-footer { flex: 0 0 auto; display: flex; flex-direction: column; gap: 10px; padding-top: 4px; }

/* (v0.24.2) Name-a-preset dialog — overlays the gameboy modal. */
.hf-namedlg {
  position: absolute; inset: 0; z-index: 30; border-radius: inherit;
  background: rgba(8, 6, 16, 0.62); display: flex; align-items: center; justify-content: center;
}
.hf-namedlg.hidden { display: none; }
.hf-namedlg-box {
  width: min(320px, 82%); background: var(--bg-card);
  border: 1px solid var(--purple-dim); border-radius: 14px; padding: 18px 18px 16px;
  box-shadow: 0 18px 48px -12px rgba(0,0,0,0.7); display: flex; flex-direction: column; gap: 12px;
}
.hf-namedlg-title { font-size: 14px; font-weight: 700; color: var(--text-primary); }
.hf-namedlg-msg { font-size: 12.5px; line-height: 1.45; color: var(--text-secondary); }
.hf-namedlg-msg.hidden { display: none; }
.hf-namedlg-input {
  width: 100%; box-sizing: border-box; padding: 9px 11px; font-size: 13px; font-family: inherit;
  color: var(--text-primary); background: var(--bg-input);
  border: 1px solid var(--purple-dim); border-radius: 9px; outline: none;
}
.hf-namedlg-input.hidden { display: none; }
.hf-namedlg-input:focus { border-color: var(--purple); }
.hf-namedlg-foot { display: flex; gap: 10px; justify-content: flex-end; }

/* ── (v0.14.6) Settings › Model Setting — model picker list ──────────────
   Registry rows: name + size + desc; radio for installed models, download
   button → 18px determinate progress ring while the file streams down. */
.model-list { display: flex; flex-direction: column; border: 1px solid var(--line-subtle); border-radius: 10px; overflow: hidden; }
.model-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; cursor: default; background: transparent; }
.model-row + .model-row { border-top: 1px solid var(--line-subtle); }
.model-row.is-ready { cursor: pointer; }
.model-row.is-ready:hover { background: rgba(168, 85, 247, 0.06); }
.model-row-text { flex: 1; min-width: 0; }
.model-row-head { display: flex; align-items: baseline; gap: 6px; }
.model-row-name { font-size: 12px; font-weight: 600; color: var(--text-primary); }
.model-row-size { font-size: 11px; color: var(--text-tertiary); }
.model-row-desc { font-size: 11px; line-height: 1.4; color: var(--text-tertiary); margin-top: 2px; }
.model-row-side { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; }
/* Radio dot — filled when the row is the current choice. */
.model-radio { width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid var(--text-tertiary); display: inline-block; }
.model-row.is-selected .model-radio { border-color: var(--purple); box-shadow: 0 0 6px var(--purple-glow); position: relative; }
.model-row.is-selected .model-radio::after { content: ''; position: absolute; inset: 2.5px; border-radius: 50%; background: var(--purple); }
/* Download button */
.model-dl { width: 24px; height: 24px; padding: 4px; border: none; border-radius: 7px; background: transparent; color: var(--text-tertiary); cursor: pointer; display: flex; align-items: center; justify-content: center; }
.model-dl:hover { color: var(--purple-bright); background: var(--purple-dim); }
.model-dl svg { width: 15px; height: 15px; }
/* Determinate ring (JS drives stroke-dashoffset from bytes received) */
.model-ring-svg { width: 18px; height: 18px; transform: rotate(-90deg); }
.model-ring-track { fill: none; stroke: var(--line-subtle); stroke-width: 2; }
.model-ring-arc { fill: none; stroke: var(--purple); stroke-width: 2; stroke-linecap: round; transition: stroke-dashoffset 0.15s linear; }
.model-empty { padding: 10px 12px; font-size: 11px; color: var(--text-tertiary); }

/* (v0.15.0) Model picker — section headers + cloud key input */
.model-section { padding: 8px 12px 4px; font-size: 9.5px; letter-spacing: .12em; color: var(--text-tertiary); font-weight: 600; }
.model-section + .model-row { border-top: none; }
.model-key { padding: 6px 12px 12px 34px; }
.model-key .field-row { margin-bottom: 6px; }
.model-key-eye { display: flex; align-items: center; justify-content: center; }
.model-key-eye svg { width: 14px; height: 14px; }
.model-key-link { display: inline-block; font-size: 10.5px; color: var(--purple-bright); text-decoration: none; }
.model-key-link:hover { text-decoration: underline; }

/* ═══════════ (v0.16.1) Model dropdown · confirm modal · key glow ═══════════ */

/* Sub-label above a key field (AI Setting) */
.field-sublabel {
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .05em;
  color: var(--purple-bright); margin: 10px 0 5px;
}

/* ── Custom dropdown ── */
.mdd { position: relative; }
.mdd-trigger {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 0 12px; height: 40px; border-radius: 9px;
  background: var(--bg-input); border: 1px solid var(--line-normal);
  color: var(--text-primary); font-family: var(--font); font-size: var(--fs-body);
  cursor: pointer; text-align: left;
}
.mdd-trigger:hover { border-color: var(--purple-dim); }
.mdd-trigger[data-open="true"] { border-color: var(--purple); }
.mdd-trigger-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mdd-trigger-text.is-placeholder { color: var(--text-tertiary); }
.mdd-chev { width: 16px; height: 16px; flex: 0 0 auto; color: var(--text-tertiary); transition: transform .18s ease; }
.mdd-trigger[data-open="true"] .mdd-chev { transform: rotate(180deg); color: var(--purple-bright); }

/* Floats OVER the content below — no document reflow. */
.mdd-panel {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0;
  /* (v0.18.1) Ryan: half the old 400px — users scroll the list, the panel
     stops swallowing the pane below. */
  z-index: 999; max-height: 200px; overflow-y: auto;
  background: var(--bg-card); border: 1px solid var(--line-normal);
  border-radius: 11px; padding: 5px; box-shadow: 0 14px 34px rgba(0,0,0,.55);
}
.mdd-panel.hidden { display: none; }
/* (v0.18.0) .mdd-section removed — the model dropdown is one flat list now. */
.mdd-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 9px; border-radius: 8px; cursor: pointer;
}
.mdd-row:hover { background: var(--bg-card-hi); }
/* Active = translucent purple fill ONLY. No dots, no checkmarks (spec). */
.mdd-row.is-active { background: rgba(168,85,247,0.22); }
.mdd-row-text { flex: 1; min-width: 0; }
.mdd-row-name { font-size: var(--fs-body); color: var(--text-primary); }
.mdd-row-desc { font-size: var(--fs-micro); color: var(--text-tertiary); margin-top: 2px; line-height: 1.35; }
/* Square box button, sized to the pane's header icon */
.mdd-side { flex: 0 0 auto; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; }
.mdd-side.is-dl { cursor: pointer; border-radius: 7px; }
.mdd-side.is-dl:hover { background: rgba(255,255,255,.07); }
.mdd-dl-btn {
  width: 28px; height: 28px; padding: 3px; border-radius: 7px;
  border: 1px solid var(--line-normal); background: transparent;
  color: var(--purple-bright); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.mdd-dl-btn:hover { background: var(--purple-dim); border-color: var(--purple); }
.mdd-dl-btn svg { width: 20px; height: 20px; }
.mdd-side .model-ring-svg { width: 26px; height: 26px; }
.model-ring-bg { fill: none; stroke: var(--line-normal); stroke-width: 2; }
.model-ring-stop { fill: var(--purple-bright); }

/* ── Cut Risk Guard modal (v0.21.0) ── */
.cutrisk-overlay {
  position: fixed; inset: 0; z-index: 1250;
  display: flex; align-items: center; justify-content: center; padding: 20px;
  background: rgba(0,0,0,0.78); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.cutrisk-overlay.hidden { display: none; }
.cutrisk-box {
  position: relative; width: min(400px, 100%); background: var(--bg-card);
  border: 1px solid var(--line-normal); border-radius: 14px; padding: 24px 22px 20px;
  text-align: center; box-shadow: 0 18px 50px -12px rgba(0,0,0,0.7);
}
.cutrisk-close {
  position: absolute; top: 12px; right: 12px; width: 26px; height: 26px;
  border: none; background: transparent; color: var(--text-tertiary);
  font-size: 15px; cursor: pointer; border-radius: 6px; line-height: 1;
}
.cutrisk-close:hover { background: rgba(255,255,255,0.06); color: var(--text-secondary); }
.cutrisk-icon { width: 48px; height: 48px; margin: 4px auto 14px; }
.cutrisk-icon svg { width: 48px; height: 48px; display: block; }
.cutrisk-title { font-size: 15px; font-weight: 700; color: #fff; line-height: 1.35; }
.cutrisk-body { font-size: 12.5px; color: var(--text-secondary,#b8b3c4); line-height: 1.5; margin-top: 8px; }
.cutrisk-body.hidden { display: none; }
.cutrisk-list {
  list-style: none; margin: 12px 0 0; padding: 0; text-align: left;
  display: inline-block;
}
.cutrisk-list.hidden { display: none; }
.cutrisk-list li {
  font-size: 12.5px; color: var(--text-secondary,#b8b3c4); line-height: 1.6;
  padding-left: 16px; position: relative;
}
.cutrisk-list li::before { content: '•'; position: absolute; left: 2px; color: var(--text-tertiary); }
.cutrisk-actions { margin-top: 18px; display: flex; justify-content: center; }
.cutrisk-actions .btn.hidden { display: none; }
.cutrisk-continue { height: 40px; min-width: 140px; }

/* Confirm dialog (v0.22.0) — same shell as cutrisk, two actions. */
.confirm-overlay {
  position: fixed; inset: 0; z-index: 1260;
  display: flex; align-items: center; justify-content: center; padding: 20px;
  background: rgba(0,0,0,0.78); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.confirm-overlay.hidden { display: none; }
.confirm-box {
  position: relative; width: min(400px, 100%); background: var(--bg-card);
  border: 1px solid var(--line-normal); border-radius: 14px; padding: 24px 22px 20px;
  text-align: center; box-shadow: 0 18px 50px -12px rgba(0,0,0,0.7);
}
.confirm-close {
  position: absolute; top: 12px; right: 12px; width: 26px; height: 26px;
  border: none; background: transparent; color: var(--text-tertiary);
  font-size: 15px; cursor: pointer; border-radius: 6px; line-height: 1;
}
.confirm-close:hover { background: rgba(255,255,255,0.06); color: var(--text-secondary); }
/* (v0.25.0) Warning variant — amber triangle for dead-end dialogs. */
.confirm-icon {
  display: flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; margin: 0 auto 12px;
  border-radius: 50%; color: #F5B042;
  background: rgba(245,176,66,0.12);
}
.confirm-icon.hidden { display: none; }
.confirm-title { font-size: 15px; font-weight: 700; color: #fff; line-height: 1.35; }
.confirm-body { font-size: 12.5px; color: var(--text-secondary,#b8b3c4); line-height: 1.5; margin-top: 8px; }
.confirm-actions { margin-top: 18px; display: flex; justify-content: center; gap: 10px; }
.confirm-actions .btn { height: 40px; min-width: 120px; }

/* ── Download confirmation modal ── */
.dlconfirm {
  position: absolute; inset: 0; z-index: 1200;
  display: flex; align-items: center; justify-content: center; padding: 20px;
  background: rgba(0,0,0,0.75); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.dlconfirm.hidden { display: none; }
.dlconfirm-box {
  width: min(420px, 100%); background: var(--bg-card);
  border: 1px solid var(--line-normal); border-radius: 14px; padding: 20px;
  box-shadow: 0 20px 50px rgba(0,0,0,.6);
}
.dlconfirm-title { font-size: 14px; font-weight: 700; color: #fff; line-height: 1.4; }
.dlconfirm-desc { font-size: var(--fs-micro); color: var(--text-tertiary); margin-top: 8px; line-height: 1.5; }
.dlconfirm-actions { display: flex; gap: 10px; margin-top: 18px; }
.dlconfirm-actions .btn { height: 40px; }

/* (v0.20.1) GPU downloader progress — sits between desc and actions. rgba only
   (no color-mix); track dark, fill = brand purple, smooth width transition. */
.gpuenv-progress { margin-top: 16px; display: flex; align-items: center; gap: 10px; }
.gpuenv-bar {
  flex: 1; height: 8px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}
.gpuenv-bar-fg {
  height: 100%; width: 0%; border-radius: 999px;
  background: var(--purple);
  transition: width 0.25s ease;
}
.gpuenv-pct {
  font-size: var(--fs-micro); color: var(--text-secondary);
  font-variant-numeric: tabular-nums; min-width: 38px; text-align: right;
}

/* ── Red-glow attention on a missing key field ── */
@keyframes keyGlowPulse {
  0%   { box-shadow: 0 0 0 0 rgba(255,0,0,0); }
  30%  { box-shadow: 0 0 10px 2px rgba(255,0,0,.6); }
  100% { box-shadow: 0 0 0 0 rgba(255,0,0,0); }
}
.key-glow { animation: keyGlowPulse 1.1s ease-in-out 2; border-color: #ff5a5a !important; }
