/* ---------------------------------------------------------------------
   Tokens
   --------------------------------------------------------------------- */
:root {
  --font-display: 'Space Grotesk', sans-serif;
  /* Ends in a broad, explicit fallback (not just the bare "sans-serif"
     generic) because the custom dropdown lists (.csel-option) render
     option text as plain HTML instead of a native <select> popup - a
     native popup's text is drawn by the OS itself and always finds a
     CJK-capable font on its own, but this custom-built list only gets
     that same guarantee if the stack explicitly names fonts that cover
     it. Without this, labels like "Cantonese (\u7ca4\u8a9e)" render as
     tofu/placeholder glyphs on setups where the plain "sans-serif" alias
     resolves to a Latin-only font. system-ui pulls in the OS's own UI
     font (always has locale-appropriate CJK glyphs); the named fonts
     after it cover the common Windows/macOS/Linux CJK defaults for
     browsers that don't resolve system-ui to something with full CJK
     coverage.
  */
  --font-body: 'Inter', system-ui, -apple-system, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans CJK SC', 'Malgun Gothic', sans-serif;
  --radius-s: 8px;
  --radius-m: 12px;
  --radius-l: 18px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

html[data-theme="dark"] {
  color-scheme: dark;
  --bg: #10131a;
  --surface: #191d26;
  --surface-raised: #1f2430;
  --border: #2a2f3b;
  --text: #eceef2;
  --text-dim: #9aa1ac;
  --accent: #52d1c3;
  --accent-2: #7c8cf8;
  --accent-text: #08211d;
  --accent-soft: rgba(82, 209, 195, 0.14);
  --danger: #e2725b;
  --success: #6bd68a;
  --track: #262b36;
  --shadow: 0 18px 45px -18px rgba(0, 0, 0, 0.55);
}

html[data-theme="light"] {
  color-scheme: light;
  --bg: #f6f6f4;
  --surface: #ffffff;
  --surface-raised: #ffffff;
  --border: #e5e5e1;
  --text: #1b1d21;
  --text-dim: #6b6f76;
  --accent: #0f8f80;
  --accent-2: #5b63d6;
  --accent-text: #f6f6f4;
  --accent-soft: rgba(15, 143, 128, 0.10);
  --danger: #c2492f;
  --success: #1f9a53;
  --track: #e6e6e2;
  --shadow: 0 18px 40px -20px rgba(30, 30, 30, 0.18);
}

* { box-sizing: border-box; }

/* Elements toggled via the `hidden` attribute in JS also set an explicit
   display value in this stylesheet (grid/flex) for when they're shown.
   Without this rule, that explicit display value beats the browser's
   default [hidden] { display: none }, so "hidden" elements stay visible. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background:
    radial-gradient(ellipse 900px 600px at 12% -10%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 60%),
    radial-gradient(ellipse 800px 700px at 100% 10%, color-mix(in srgb, var(--accent-2) 9%, transparent), transparent 55%),
    radial-gradient(ellipse 700px 600px at 30% 110%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 55%),
    var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ---------------------------------------------------------------------
   Ambient animated background
   --------------------------------------------------------------------- */
.bg-glow {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.35;
  will-change: transform;
  transition: transform 0.09s linear;
}
html[data-theme="light"] .blob { opacity: 0.22; }
.blob-a {
  width: 480px; height: 480px;
  top: -160px; left: -120px;
  background: var(--accent);
  animation: drift-a 34s ease-in-out infinite;
}
.blob-b {
  width: 420px; height: 420px;
  bottom: -180px; right: -140px;
  background: var(--accent-2);
  animation: drift-b 40s ease-in-out infinite;
}
.blob-c {
  width: 320px; height: 320px;
  top: 40%; left: 60%;
  background: var(--accent);
  opacity: 0.18;
  animation: drift-c 28s ease-in-out infinite;
}
.blob-d {
  width: 260px; height: 260px;
  top: 65%; left: 8%;
  background: var(--accent-2);
  opacity: 0.14;
  animation: drift-d 46s ease-in-out infinite;
}
@keyframes drift-a {
  0%   { transform: translate(0, 0) scale(1); }
  25%  { transform: translate(180px, 120px) scale(1.15); }
  50%  { transform: translate(90px, 260px) scale(0.95); }
  75%  { transform: translate(-80px, 90px) scale(1.08); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes drift-b {
  0%   { transform: translate(0, 0) scale(1); }
  25%  { transform: translate(-160px, -90px) scale(1.1); }
  50%  { transform: translate(-260px, 40px) scale(0.92); }
  75%  { transform: translate(-90px, 130px) scale(1.05); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes drift-c {
  0%   { transform: translate(0, 0) scale(1); }
  33%  { transform: translate(-140px, 100px) scale(1.2); }
  66%  { transform: translate(120px, 160px) scale(0.85); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes drift-d {
  0%   { transform: translate(0, 0) scale(1); }
  30%  { transform: translate(110px, -140px) scale(1.12); }
  60%  { transform: translate(200px, 40px) scale(0.9); }
  100% { transform: translate(0, 0) scale(1); }
}

.app {
  max-width: 720px;
  margin: 0 auto;
  padding: 28px 20px 60px;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;
}

/* ---------------------------------------------------------------------
   Top bar
   --------------------------------------------------------------------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 36px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
}

.brand-mark-wrap {
  display: inline-flex;
  border-radius: 50%;
  filter: drop-shadow(0 4px 14px rgba(82, 209, 195, 0.35));
  transition: transform 0.25s var(--ease);
}
.brand:hover .brand-mark-wrap { transform: rotate(-8deg) scale(1.05); }
.brand-mark { display: block; border-radius: 50%; }

.brand-name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 18px;
  letter-spacing: 0.01em;
}

/* Page nav (Downloader / History) */
.page-nav {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  box-shadow: var(--shadow);
}
.page-nav-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  padding: 8px 14px;
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.15s, background 0.2s var(--ease), transform 0.15s var(--ease);
}
.page-nav-btn svg { flex-shrink: 0; }
.page-nav-btn span { white-space: nowrap; }
.page-nav-btn:hover { color: var(--text); }
.page-nav-btn:active { transform: scale(0.95); }
.page-nav-btn.is-active { background: var(--accent); color: var(--accent-text); }
.page-nav-btn span { display: none; }
@media (min-width: 460px) {
  .page-nav-btn span { display: inline; }
}

.theme-toggle {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-s);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, transform 0.2s var(--ease);
  flex-shrink: 0;
}
.theme-toggle:hover { color: var(--text); border-color: var(--text-dim); transform: rotate(14deg); }
.theme-toggle:active { transform: rotate(14deg) scale(0.9); }
.theme-toggle #iconMoon { display: none; }
html[data-theme="dark"] .theme-toggle #iconSun { display: none; }
html[data-theme="dark"] .theme-toggle #iconMoon { display: block; }

.jobs-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 12px;
  border-radius: var(--radius-s);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  flex-shrink: 0;
  transition: border-color 0.15s, transform 0.15s;
}
.jobs-badge:hover { border-color: var(--accent); transform: translateY(-1px); }
.jobs-badge-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  animation: jobs-badge-pulse 1.4s ease-in-out infinite;
}
@keyframes jobs-badge-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(0.75); }
}

/* ---------------------------------------------------------------------
   Pages
   --------------------------------------------------------------------- */
.page { display: none; }
.page.is-active { display: block; animation: page-in 0.35s var(--ease); }

@keyframes page-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---------------------------------------------------------------------
   Intake
   --------------------------------------------------------------------- */
.eyebrow-free-label {
  margin: 0 0 10px;
  color: var(--text-dim);
  font-size: 14px;
}

.intake-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.intake-header .eyebrow-free-label { margin: 0; }

.batch-textarea {
  width: 100%;
  resize: vertical;
  min-height: 96px;
  margin-top: 12px;
  margin-bottom: 16px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  color: var(--text);
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 1.5;
}
.batch-textarea:focus { outline: none; border-color: var(--accent); }

#batchQueueWrap { margin-top: 16px; }
.queue-row-status {
  flex-shrink: 0;
  font-size: 12px;
  color: var(--text-dim);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 160px;
}
.queue-row.is-done .queue-row-status { color: var(--success); }
.queue-row.is-error .queue-row-status { color: var(--danger); }

.url-row {
  display: flex;
  gap: 10px;
}

.url-row input[type="text"] {
  flex: 1;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 13px 14px;
  color: var(--text);
  font-size: 15px;
  font-family: var(--font-body);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.url-row input[type="text"]:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.url-row input[type="text"]::placeholder { color: var(--text-dim); }

.btn-primary {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: var(--accent-text);
  border: none;
  border-radius: var(--radius-s);
  padding: 13px 20px;
  font-size: 15px;
  font-weight: 600;
  font-family: var(--font-body);
  cursor: pointer;
  white-space: nowrap;
  transition: filter 0.15s, transform 0.05s, box-shadow 0.2s;
  box-shadow: 0 8px 20px -10px rgba(82, 209, 195, 0.55);
}
.btn-primary:hover { filter: brightness(1.06); box-shadow: 0 10px 26px -8px rgba(82, 209, 195, 0.6); }
.btn-primary:active { transform: scale(0.98); }
.btn-primary:disabled { opacity: 0.55; cursor: default; box-shadow: none; filter: none; }
.btn-primary::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(120deg, transparent 30%, rgba(255,255,255,0.35) 50%, transparent 70%);
  transform: translateX(-120%);
}
.btn-primary:not(:disabled):hover::after { transform: translateX(120%); transition: transform 0.6s ease; }

.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 11px 18px;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, transform 0.15s;
}
.btn-secondary:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-1px); }
.btn-secondary:active { transform: translateY(0) scale(0.96); }

.btn-wide { flex-shrink: 0; }

.error-line {
  color: var(--danger);
  font-size: 14px;
  margin: 10px 2px 0;
  animation: shake 0.3s var(--ease);
}
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

/* ---------------------------------------------------------------------
   Workspace
   --------------------------------------------------------------------- */
.workspace { margin-top: 32px; display: flex; flex-direction: column; gap: 28px; animation: rise-in 0.4s var(--ease); }

/* #singleVideoBlock/#playlistBlock are the only wrapper <div>s in the
   workspace tree - everything else (mode-tabs, options-grid, etc.) sits
   directly under .workspace and inherits its 28px gap for free. These
   two need the same rule explicitly, or their own children (preview
   card, timeline/trim block, playlist range picker) end up jammed
   together with zero space between them. */
#singleVideoBlock, #playlistBlock { display: flex; flex-direction: column; gap: 24px; }

@keyframes rise-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}

.preview-meta { padding-top: 2px; min-width: 0; }

.preview-meta-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.preview-meta-head .video-title { margin-bottom: 6px; }

.thumb-dl-btn {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  margin-top: 2px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-dim);
  font-size: 11.5px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease), background 0.15s var(--ease);
}
.thumb-dl-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.thumb-dl-btn svg { flex-shrink: 0; }

.video-title {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  line-height: 1.3;
  margin: 0 0 6px;
  word-break: break-word;
}

.video-sub {
  color: var(--text-dim);
  font-size: 14px;
  margin: 0;
}

/* ---------------------------------------------------------------------
   Timeline / trim scrubber
   --------------------------------------------------------------------- */
.timeline-block {
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 18px 0;
}

.timeline-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}

.switch { display: flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; }
.switch input { display: none; }
.switch-track {
  width: 34px;
  height: 20px;
  border-radius: 10px;
  background: var(--track);
  border: 1px solid var(--border);
  position: relative;
  transition: background 0.15s;
  flex-shrink: 0;
}
.switch-thumb {
  position: absolute;
  top: 1px;
  left: 1px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--text-dim);
  transition: transform 0.2s var(--ease), background 0.15s;
}
.switch input:checked + .switch-track { background: var(--accent-soft); border-color: var(--accent); }
.switch input:checked + .switch-track .switch-thumb { transform: translateX(14px); background: var(--accent); }
.switch-label { font-size: 14px; color: var(--text); }

.time-readout {
  font-family: var(--font-display);
  font-size: 13px;
  color: var(--text-dim);
}

.scrub-wrap { padding-top: 16px; animation: rise-in 0.25s var(--ease); }

.scrub-track {
  position: relative;
  height: 6px;
  background: var(--track);
  border-radius: 3px;
  margin: 10px 6px 22px;
}

.scrub-fill {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0%;
  right: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  border-radius: 3px;
}

.scrub-handle {
  position: absolute;
  top: 50%;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--accent);
  transform: translate(-50%, -50%);
  cursor: grab;
  touch-action: none;
  transition: box-shadow 0.15s;
}
.scrub-handle:hover { box-shadow: 0 0 0 6px var(--accent-soft); }
.scrub-handle:active { cursor: grabbing; }
.scrub-handle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.scrub-inputs {
  display: flex;
  gap: 16px;
  font-size: 13px;
  color: var(--text-dim);
}
.scrub-inputs label { display: flex; align-items: center; gap: 6px; }
.scrub-inputs input {
  width: 70px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 6px 8px;
  color: var(--text);
  font-family: var(--font-display);
  font-size: 13px;
}
.scrub-inputs input:focus { outline: none; border-color: var(--accent); }

/* ---------------------------------------------------------------------
   Segmented pill toggles - Single/Batch, Video/Audio/GIF, source tabs,
   method tabs, the Enhance page's tool switcher, etc. All share this one
   look: a floating gradient glow slides behind whichever option is
   active (handled generically in JS - see initGlowTabs) instead of a
   flat background swap, so every toggle in the app gets the same feel.
   --------------------------------------------------------------------- */
.mode-tabs, .tool-tabs {
  position: relative;
  display: flex;
  gap: 4px;
  padding: 5px;
  width: fit-content;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  box-shadow: var(--shadow);
}
.field-wide .mode-tabs { width: 100%; }
.tool-tabs { margin-bottom: 22px; width: 100%; }
.tool-tabs > .tool-tab { flex: 1; }
.source-tabs { margin-bottom: 14px; }
.mode-tab, .tool-tab {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 18px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.25s var(--ease), transform 0.15s var(--ease);
}
.field-wide .mode-tab { flex: 1; }
.mode-tab svg, .tool-tab svg { flex-shrink: 0; transition: transform 0.3s var(--ease); }
.mode-tab:hover, .tool-tab:hover { color: var(--text); }
.mode-tab:active, .tool-tab:active { transform: scale(0.97); }
.mode-tab.is-active, .tool-tab.is-active { color: var(--accent-text); }
.mode-tab.is-active svg, .tool-tab.is-active svg { transform: scale(1.08) rotate(-4deg); }
.mode-tab:disabled, .tool-tab:disabled { opacity: 0.45; cursor: not-allowed; }
.mode-tab:disabled:active, .tool-tab:disabled:active { transform: none; }

.mode-tab-stacked, .tool-tab-stacked {
  flex-direction: column;
  gap: 2px;
  padding: 10px 20px;
}
.method-sub { font-size: 11px; font-weight: 400; color: var(--text-dim); }
.mode-tab-stacked.is-active .method-sub, .tool-tab-stacked.is-active .method-sub { color: var(--accent-text); opacity: 0.85; }

.tab-glow {
  position: absolute;
  z-index: 0;
  top: 5px; bottom: 5px; left: 5px;
  width: 0;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 8px 20px -8px var(--accent-soft);
  transition: transform 0.35s var(--ease), width 0.35s var(--ease);
  pointer-events: none;
  opacity: 0;
}
.tab-glow.is-ready { opacity: 1; }

.tool-section { display: none; }
.tool-section.is-active { display: block; animation: page-in 0.3s var(--ease); }

/* ---------------------------------------------------------------------
   Upscale page - optional enhancements (denoise/sharpen, color, etc.)
   --------------------------------------------------------------------- */
.enh-block { margin-bottom: 16px; }
.enh-heading {
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.enh-heading-sub { margin-left: 6px; font-size: 11.5px; font-weight: 400; color: var(--text-dim); }
.enh-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.enh-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  background: var(--surface);
  cursor: pointer;
  user-select: none;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease), transform 0.15s var(--ease);
}
.enh-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.enh-card:active { transform: translateY(0) scale(0.99); }
.enh-card input { position: absolute; opacity: 0; pointer-events: none; }
.enh-card-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-s);
  background: var(--surface-raised);
  color: var(--text-dim);
  transition: color 0.2s var(--ease), background 0.2s var(--ease);
}
.enh-card-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.enh-card-title { font-size: 13px; font-weight: 600; color: var(--text); }
.enh-card-sub { font-size: 11px; color: var(--text-dim); }
.enh-card:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 6px 18px -10px var(--accent-soft);
}
.enh-card:has(input:checked) .enh-card-icon { background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: var(--accent-text); }
.enh-card:has(input:disabled) { opacity: 0.5; cursor: not-allowed; }
.enh-card:has(input:disabled):hover { border-color: var(--border); transform: none; }

/* ---------------------------------------------------------------------
   Subtitles page - audio track picker (only shown when a source has
   more than one audio track worth choosing between)
   --------------------------------------------------------------------- */
.tracks-block {
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  background: var(--surface);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  animation: rise-in 0.25s var(--ease);
}
.tracks-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.tracks-hint { margin: 0; font-size: 12px; color: var(--text-dim); line-height: 1.5; }
.tracks-list { display: flex; flex-direction: column; gap: 6px; }
.track-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  background: var(--surface-raised);
  font-size: 13px;
  cursor: pointer;
  user-select: none;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.track-row:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.track-row input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }
.track-row .track-meta { margin-left: auto; color: var(--text-dim); font-size: 11.5px; font-weight: 500; }
.track-row:has(input:checked) .track-meta { color: var(--accent); opacity: 0.85; }

/* ---------------------------------------------------------------------
   Stems page - "what to extract" checkbox group
   --------------------------------------------------------------------- */
.stem-checks {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.stem-check {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  background: var(--surface);
  cursor: pointer;
  font-size: 14px;
  color: var(--text);
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
  user-select: none;
}
.stem-check:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.stem-check input {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

/* ---------------------------------------------------------------------
   Stems page - results panel: per-stem downloads, "download all", and
   the stem-mixing queue
   --------------------------------------------------------------------- */
.stems-results {
  margin-top: 24px;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: 16px;
  animation: rise-in 0.3s var(--ease);
}
.stems-results-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.stems-results-header h3 { margin: 0; font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.bpm-badge {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 3px 9px;
  font-family: var(--font-display);
  letter-spacing: 0.01em;
}
.stems-results-header .btn-secondary.btn-small { margin: 0; }

.reburn-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  border-radius: var(--radius-s);
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  font-size: 13px;
  color: var(--text);
}
.reburn-banner .btn-secondary.btn-small { margin: 0; flex-shrink: 0; }

.stems-parts-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.stems-part-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  background: var(--surface-raised);
}
.stems-part-label { font-weight: 600; font-size: 13.5px; }
.stems-part-size { color: var(--text-dim); font-size: 12px; margin-left: auto; }
.stems-part-preview {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.stems-part-preview:hover { color: var(--accent); border-color: var(--accent); }
.stems-part-row.is-previewing .stems-part-preview { color: var(--accent-text); background: linear-gradient(135deg, var(--accent), var(--accent-2)); border-color: transparent; }
.stems-part-row.is-mix { border-color: var(--accent); background: var(--accent-soft); }
.stems-part-row .audio-player { flex-basis: 100%; width: 100%; margin-top: 4px; }

/* ---------------------------------------------------------------------
   Subtitles page - preview playback, chapters and transcript viewer
   --------------------------------------------------------------------- */


.transcript-block-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}
.transcript-block-header h4 { margin: 0; font-size: 13px; font-weight: 600; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.03em; }
.transcript-block-header .btn-secondary.btn-small { margin: 0; }
#subTranscriptSearch {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 6px 10px;
  color: var(--text);
  font-size: 12.5px;
  width: 180px;
}
#subTranscriptSearch:focus { outline: none; border-color: var(--accent); }

.transcript-replace-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.transcript-replace-row input[type="text"] {
  flex: 1;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 6px 10px;
  color: var(--text);
  font-size: 12.5px;
}
.transcript-replace-row input[type="text"]:focus { outline: none; border-color: var(--accent); }
.transcript-replace-arrow { flex-shrink: 0; color: var(--text-dim); }
.transcript-replace-row .btn-secondary.btn-small { flex-shrink: 0; margin: 0; }
.transcript-replace-status { font-size: 12px; color: var(--text-dim); margin: -2px 0 8px; }
.transcript-replace-status.is-success { color: var(--accent); }
.transcript-replace-status.is-error { color: var(--danger); }

.transcript-shift-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.transcript-shift-row label { font-size: 12.5px; color: var(--text-dim); flex-shrink: 0; }
.transcript-shift-row input[type="text"] {
  width: 84px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 6px 10px;
  color: var(--text);
  font-size: 12.5px;
}
.transcript-shift-row input[type="text"]:focus { outline: none; border-color: var(--accent); }
.transcript-shift-hint { font-size: 11.5px; color: var(--text-dim); flex: 1; min-width: 140px; }
.transcript-shift-row .btn-secondary.btn-small { flex-shrink: 0; margin: 0; }

.chapters-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 220px;
  overflow-y: auto;
}
.chapter-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 6px 8px;
  border-radius: var(--radius-s);
  cursor: pointer;
  font-size: 13px;
  transition: background 0.15s;
}
.chapter-row:hover { background: var(--surface-raised); }
.chapter-row .c-time { font-family: var(--font-display); color: var(--accent); flex-shrink: 0; }
.chapter-row .c-label { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.transcript-list {
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  padding: 6px;
}
.transcript-line {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 6px 8px;
  border-radius: var(--radius-s);
  cursor: pointer;
  font-size: 13px;
  line-height: 1.5;
  transition: background 0.15s;
}
.transcript-line:hover { background: var(--surface-raised); }
.transcript-line.is-active { background: var(--accent-soft); }
.transcript-line .t-time { font-family: var(--font-display); color: var(--text-dim); flex-shrink: 0; font-size: 11.5px; }
.transcript-line.is-active .t-time { color: var(--accent); }
.transcript-line .t-text { color: var(--text); flex: 1; min-width: 0; }
.transcript-line.is-hidden { display: none; }
.transcript-line.is-editing { cursor: default; background: var(--surface-raised); }
.t-edit-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: var(--radius-s);
  color: var(--text-dim);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s, background 0.15s;
}
.transcript-line:hover .t-edit-btn, .transcript-line.is-editing .t-edit-btn { opacity: 1; }
.t-edit-btn:hover { color: var(--accent); background: var(--surface); }
.t-edit-input {
  flex: 1;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: var(--radius-s);
  padding: 3px 8px;
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
}
.t-edit-input:focus { outline: none; }

.stems-part-dl {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--radius-s);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease), transform 0.15s var(--ease);
}
.stems-part-dl:hover { border-color: var(--accent); color: var(--accent); }
.stems-part-dl:active { transform: scale(0.96); }
.stems-part-dl svg { flex-shrink: 0; }
.stems-part-dl[data-state="done"] { border-color: var(--accent); color: var(--accent); }

.stems-mix-block { border-top: 1px solid var(--border); padding-top: 16px; }
.stems-mix-block h3 { margin: 0; font-size: 15px; font-weight: 600; }
.stems-mix-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  color: inherit;
  font: inherit;
  text-align: left;
}
.stems-mix-chevron { flex-shrink: 0; color: var(--text-dim); transition: transform 0.2s var(--ease); }
.stems-mix-toggle[aria-expanded="true"] .stems-mix-chevron { transform: rotate(180deg); }
.stems-mix-toggle:hover .stems-mix-chevron { color: var(--accent); }
.stems-mix-body { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
.stems-mix-hint { margin: 0; font-size: 12.5px; color: var(--text-dim); line-height: 1.5; }

.mix-shift-row {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  flex-wrap: wrap;
}
.mix-shift-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 13px;
  color: var(--text-dim);
  flex: 1;
  min-width: 160px;
}
.mix-shift-field span { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.mix-shift-field em { font-style: normal; color: var(--accent); font-family: var(--font-display); font-weight: 600; }
.mix-shift-field input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
  height: 4px;
}
.mix-shift-row .btn-secondary.btn-small { margin: 0 0 1px; flex-shrink: 0; }
.mix-shift-row .mix-shift-reverb { flex: 0 0 auto; margin-bottom: 1px; }
.mix-shift-row .mix-shift-reverb .extra-toggle-title { font-size: 13px; }

.stems-mix-results { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.stems-mix-results:empty { display: none; }
.stems-mix-result-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  background: var(--surface-raised);
  font-size: 13px;
  animation: rise-in 0.25s var(--ease);
}
.stems-mix-result-item .mri-label { font-weight: 600; }
.stems-mix-result-item .mri-label .mri-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 99px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  vertical-align: middle;
}
.stems-mix-result-item .mri-size { color: var(--text-dim); font-size: 12px; margin-left: auto; }
.stems-mix-result-item.is-error .mri-size { color: var(--danger); }
.stems-mix-result-item .mri-dl {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: var(--radius-s);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--accent);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.stems-mix-result-item .mri-dl:hover { border-color: var(--accent); }

/* Quick preset chips (stem picker shortcuts) */
.stem-presets { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  padding: 4px 11px;
  border-radius: 99px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease), background 0.15s var(--ease);
}
.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip:active { transform: scale(0.96); }

/* "Split into" model picker */
.field-wide { grid-column: 1 / -1; }
.segmented { display: flex; gap: 8px; flex-wrap: wrap; }
.segmented-btn {
  flex: 1 1 200px;
  padding: 10px 12px;
  border-radius: var(--radius-s);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.segmented-btn em { display: block; margin-top: 2px; font-style: normal; font-weight: 500; font-size: 11px; color: var(--text-dim); }
.segmented-btn:hover { border-color: var(--accent); }
.segmented-btn.is-active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.segmented-btn.is-active em { color: var(--accent); opacity: 0.8; }

#extensionBtn.theme-toggle:hover { transform: scale(1.08); }
#extensionBtn.theme-toggle:active { transform: scale(0.94); }

/* ---------------------------------------------------------------------
   Upscale page - source dropzone, AI note, fallback thumbnail
   --------------------------------------------------------------------- */
.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 32px 20px;
  border: 1.5px dashed var(--border);
  border-radius: var(--radius-m);
  color: var(--text-dim);
  text-align: center;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease), color 0.2s;
}
.dropzone:hover { border-color: var(--accent); color: var(--text); }
.dropzone.is-dragover { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.dropzone svg { color: var(--text-dim); }
.dropzone:hover svg, .dropzone.is-dragover svg { color: var(--accent); }

/* ---------------------------------------------------------------------
   "Use a recent file" tab - shared by every tool page's third source tab
   --------------------------------------------------------------------- */
.recent-files-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 280px;
  overflow-y: auto;
}
.recent-file-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  font-size: 13.5px;
  transition: border-color 0.15s, transform 0.15s var(--ease);
}
.recent-file-row:hover { border-color: var(--accent); transform: translateY(-1px); }
.recent-file-row img {
  width: 56px;
  height: 32px;
  object-fit: cover;
  border-radius: 6px;
  background: var(--track);
  flex-shrink: 0;
}
.recent-file-row-fallback {
  width: 56px;
  height: 32px;
  border-radius: 6px;
  background: var(--track);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  flex-shrink: 0;
}
.recent-file-row-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.recent-files-empty {
  margin: 0;
  padding: 18px 4px;
  color: var(--text-dim);
  font-size: 13px;
  text-align: center;
}

.ai-note {
  margin: 10px 0 0;
  font-size: 12.5px;
  color: var(--text-dim);
  line-height: 1.5;
}
.ai-note.is-warning { color: var(--danger, #e0654f); }
.ai-note a { color: var(--accent); }

/* ---------------------------------------------------------------------
   Subtitles page - caption style preview + custom style editor. The
   preview frame stands in for a video frame (dark gradient, 16:9) with
   the caption text rendered using plain CSS approximations of the ASS
   style fields (font/colour/outline/bold/shadow) burn-in actually uses,
   so picking a built-in preset or tweaking a custom one shows roughly
   what'll end up baked into the video before spending minutes rendering
   it to find out.
   --------------------------------------------------------------------- */
.preview-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
  flex-wrap: wrap;
}
.preview-aspect-hint {
  font-size: 11px;
  color: var(--text-dim, rgba(255,255,255,0.55));
  font-style: italic;
}
.custom-style-preview {
  position: relative;
  margin-top: 12px;
  margin-left: auto;
  margin-right: auto;
  /* Actual width/height get set inline by JS (see applyPreviewBoxSize)
     so a 9:16 or 1:1 source shows at its true shape - this aspect-ratio
     is only a fallback for the instant before that JS runs. A fixed
     max-height here (as this used to have) caps the box's height but
     not its width, so for anything taller than 16:9 the browser kept the
     full width and just clipped the height short instead of shrinking
     the box down to the right shape - it quietly worked for 16:9 (where
     the cap and the natural height happened to roughly match) and
     silently squished every other ratio. */
  width: 100%;
  max-width: 460px;
  aspect-ratio: var(--preview-ar, 16 / 9);
  border-radius: var(--radius-m);
  border: 1px solid var(--border);
  background:
    radial-gradient(120% 140% at 20% 15%, rgba(255,255,255,0.06), transparent 55%),
    linear-gradient(155deg, #2a2f3a, #14161c 70%);
  overflow: hidden;
}
.custom-style-preview-langs {
  position: absolute;
  z-index: 2;
  top: 8px;
  left: 8px;
  right: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.custom-style-preview-langs:empty { display: none; }
.preview-lang-chip {
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.2);
  background: rgba(0,0,0,0.45);
  color: rgba(255,255,255,0.75);
  font-size: 11px;
  cursor: pointer;
}
.preview-lang-chip.is-active { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast, #101014); font-weight: 600; }
#subCustomStylePreviewText {
  position: absolute;
  display: inline-block;
  max-width: 92%;
  left: 50%;
  top: 90%;
  transform: translate(-50%, -50%);
  text-align: center;
  line-height: 1.35;
  font-size: 20px;
  word-break: break-word;
  transition: color 0.15s, text-shadow 0.15s, font-family 0.15s, font-weight 0.15s, left 0.15s, top 0.15s, font-size 0.15s;
}
#subCustomStylePreviewText.is-kinetic-preview { animation: kinetic-pop-preview 1.6s var(--ease) infinite; }
@keyframes kinetic-pop-preview {
  /* Every step keeps translate(-50%, -50%) so the text stays centered on
     its pos_x/pos_y anchor point while scaling - dropping it (as this
     used to do, animating a bare `scale(...)`) replaces the centering
     offset instead of combining with it, so the text visibly jumped to
     being positioned by its top-left corner the instant the animation
     started instead of staying anchored like the real burned-in \pos+\an5
     text does. */
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.7); }
  12% { opacity: 1; transform: translate(-50%, -50%) scale(1.12); }
  22% { transform: translate(-50%, -50%) scale(1); }
  78% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1); }
}

.custom-style-panel {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed var(--border);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.custom-style-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
}
.custom-style-control {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 12px;
  color: var(--text-dim);
  flex: 1;
  min-width: 100px;
}
.custom-style-control-wide { flex-basis: 100%; }
.custom-style-control select {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 8px 10px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 13px;
}
.custom-style-control input[type="color"] {
  width: 100%;
  height: 34px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  background: var(--surface);
  cursor: pointer;
}
.custom-style-control input[type="range"] { accent-color: var(--accent); width: 100%; }
.custom-style-check {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.custom-style-check input { accent-color: var(--accent); width: 16px; height: 16px; cursor: pointer; }

.custom-style-save-row { gap: 8px; }
.custom-style-save-row input[type="text"] {
  flex: 1;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 9px 12px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 13px;
}
.custom-style-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.custom-style-list:empty { display: none; }
.custom-style-list li {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: 12.5px;
  cursor: pointer;
}
.custom-style-list li:hover { border-color: var(--accent); color: var(--accent); }
.custom-style-list li .style-chip-delete { color: var(--text-dim); cursor: pointer; display: flex; }
.custom-style-list li .style-chip-delete:hover { color: var(--danger, #e0654f); }
.style-chip-swatch {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--border);
  flex-shrink: 0;
}
.style-chip-name { max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.no-cc-hint {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 14px;
  margin-top: 4px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  background: var(--surface-raised);
  font-size: 12.5px;
  color: var(--text-dim);
  line-height: 1.5;
}
.no-cc-hint .btn-secondary.btn-small { margin: 0; flex-shrink: 0; }

.capability-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.capability-row .ai-note { flex: 1; }
.btn-secondary.btn-small { padding: 6px 12px; font-size: 12px; flex-shrink: 0; margin-top: 10px; margin-left: auto; }
.btn-secondary.btn-small.is-checking svg { animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.btn-secondary:disabled { opacity: 0.4; cursor: not-allowed; border-color: var(--border); color: var(--text-dim); transform: none; }

.thumb-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  background: var(--surface);
}

/* ---------------------------------------------------------------------
   Options
   --------------------------------------------------------------------- */
.options-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  animation: rise-in 0.25s var(--ease);
}

.field { display: flex; flex-direction: column; gap: 7px; font-size: 13px; color: var(--text-dim); }

.field select {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 11px 12px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 14px;
  transition: border-color 0.15s;
}
.field select:focus { outline: none; border-color: var(--accent); }

.field select.multi-select {
  padding: 4px;
  height: auto;
}
.field select.multi-select option {
  padding: 7px 8px;
  border-radius: 4px;
}
/* Native <select multiple> selection highlighting reads very faint in a
   dark theme by default - this makes a Ctrl/Cmd-clicked option obviously
   picked instead of just barely-tinted. */
.field select.multi-select option:checked {
  background: var(--accent);
  color: var(--accent-contrast, #101014);
  font-weight: 600;
}

/* ---------------------------------------------------------------------
   Extra feature toggles (metadata / thumbnail / subtitles)
   --------------------------------------------------------------------- */
.extras-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  padding: 6px 16px;
}

.extra-toggle {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  cursor: pointer;
  user-select: none;
}
.extra-toggle + .extra-toggle { border-top: 1px solid var(--border); }
.extra-toggle input { display: none; }

.extra-toggle-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.extra-toggle-title { font-size: 14px; font-weight: 600; color: var(--text); }
.extra-toggle-sub { font-size: 12px; color: var(--text-dim); }

#subtitleLangField { padding: 4px 0 12px; animation: rise-in 0.2s var(--ease); }
#subTranslateLangField { padding: 4px 0 14px; animation: rise-in 0.2s var(--ease); }
#subTranslateLangField select { margin-top: 2px; }
#subTranslateArgosNote { margin: 8px 0 0; }

/* ---------------------------------------------------------------------
   Custom select (replaces the native <select> box everywhere)
   --------------------------------------------------------------------- */
.csel { position: relative; }
.csel-native {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
}

.csel-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 11px 12px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.csel-trigger:hover { border-color: var(--text-dim); }
.csel-trigger:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.csel.is-open .csel-trigger { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }

.csel-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.csel-chevron { flex-shrink: 0; color: var(--text-dim); transition: transform 0.2s var(--ease); }
.csel.is-open .csel-chevron { transform: rotate(180deg); color: var(--accent); }

.csel-menu {
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  max-height: 260px;
  overflow-y: auto;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  box-shadow: var(--shadow);
  padding: 4px;
  display: none;
  flex-direction: column;
  gap: 1px;
}
.csel.is-open .csel-menu { display: flex; animation: menu-in 0.15s var(--ease); }

@keyframes menu-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.csel-option {
  all: unset;
  /* Without this, a long menu (e.g. the 20-language translate-target
     list) has more combined row height than .csel-menu's 260px
     max-height. Because .csel-menu is a column flexbox, flex's default
     flex-shrink:1 then does exactly what its name says - it shrinks
     every row's box short enough for all of them to fit in 260px
     *instead of* just scrolling, and this row's own overflow:hidden
     (below, needed for the ellipsis) then clips the now-too-tall text
     against that shrunk box. That's the "tops of every letter sliced
     off" glitch - not a missing-glyph/font issue, since it happened to
     plain English rows too. flex-shrink: 0 keeps each row at its real
     content height so the menu scrolls instead of squeezing rows. */
  flex-shrink: 0;
  box-sizing: border-box;
  display: block;
  width: 100%;
  padding: 9px 10px;
  border-radius: 6px;
  font-family: var(--font-body);
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.12s;
}
.csel-option:hover,
.csel-option:focus-visible { background: var(--accent-soft); color: var(--accent); }
.csel-option.is-selected { color: var(--accent); font-weight: 600; background: var(--accent-soft); }

/* Multi-select variant - checkbox rows that keep the menu open across
   picks, in the same trigger+menu shell as every single-select above. */
.csel-multi .csel-menu-checks { gap: 2px; }
.csel-check {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 9px;
  box-sizing: border-box;
  width: 100%;
  padding: 8px 10px;
  border-radius: 6px;
  font-family: var(--font-body);
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
  transition: background 0.12s;
}
.csel-check:hover { background: var(--accent-soft); }
.csel-check.is-selected { color: var(--accent); font-weight: 600; }
.csel-check input {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
}
.csel-check.is-disabled { opacity: 0.4; cursor: not-allowed; }
.csel-check.is-disabled input { cursor: not-allowed; }

/* ---------------------------------------------------------------------
   Estimate + download
   --------------------------------------------------------------------- */
.estimate-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  padding: 16px 18px;
  box-shadow: var(--shadow);
}

.estimate { display: flex; flex-direction: column; gap: 4px; }
.estimate-label { font-size: 12px; color: var(--text-dim); }
.estimate-value { font-family: var(--font-display); font-size: 22px; font-weight: 600; display: inline-block; }
.value-pulse { animation: value-pop 0.35s var(--ease); }
@keyframes value-pop {
  0% { transform: scale(1); }
  35% { transform: scale(1.08); color: var(--accent); }
  100% { transform: scale(1); }
}

/* ---------------------------------------------------------------------
   Progress
   --------------------------------------------------------------------- */
.progress-block { display: flex; flex-direction: column; gap: 10px; animation: rise-in 0.25s var(--ease); }

.progress-track {
  height: 8px;
  background: var(--track);
  border-radius: 4px;
  overflow: hidden;
  position: relative;
}
.progress-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  background-size: 200% 100%;
  animation: shimmer 1.6s linear infinite;
  transition: width 0.25s ease;
}
.progress-fill.is-done { animation-play-state: paused; }
@keyframes shimmer {
  0% { background-position: 0% 0; }
  100% { background-position: -200% 0; }
}

.progress-status { font-size: 13px; color: var(--text-dim); }

.progress-status-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.progress-status-row .progress-status { flex: 1; min-width: 0; }
.btn-stop {
  flex-shrink: 0;
  background: none;
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: var(--radius-s);
  padding: 5px 12px;
  font-size: 12.5px;
  font-family: var(--font-body);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.btn-stop:hover:not(:disabled) { border-color: var(--danger); color: var(--danger); }
.btn-stop:disabled { opacity: 0.5; cursor: default; }

/* ---------------------------------------------------------------------
   Footer
   --------------------------------------------------------------------- */
.footer {
  margin-top: auto;
  padding-top: 40px;
  font-size: 12.5px;
  color: var(--text-dim);
  border-top: 1px solid var(--border);
}

/* ---------------------------------------------------------------------
   Video preview (facade -> embedded player)
   --------------------------------------------------------------------- */
.preview-card { display: flex; flex-direction: column; gap: 14px; }
/* A brief visual "this is about to change" cue while a newly-pasted link
   is being fetched, so the still-showing previous video's title doesn't
   read as if it belongs to whatever's about to load. */
.preview-card.is-stale .video-title,
.preview-card.is-stale .video-sub { color: var(--text-dim); transition: color 0.2s var(--ease); }
.preview-card.is-stale .preview-media { filter: saturate(0.4) brightness(0.75); transition: filter 0.2s var(--ease); }

.preview-media {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-m);
  overflow: hidden;
  background: var(--track);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
}
.preview-media iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.preview-facade {
  all: unset;
  position: absolute;
  inset: 0;
  cursor: pointer;
  display: block;
}
.preview-facade .thumb,
.preview-media > .thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: transform 0.4s var(--ease), opacity 0.45s ease;
}
.thumb.is-loaded { opacity: 1; }
.preview-facade:hover .thumb { transform: scale(1.03); }
.play-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, transform 0.15s var(--ease);
  animation: badge-pulse 2.6s ease-in-out infinite;
}
.preview-facade:hover .play-badge { animation-play-state: paused; }
@keyframes badge-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(82, 209, 195, 0); }
  50% { box-shadow: 0 0 0 10px rgba(82, 209, 195, 0.14); }
}
.preview-facade:hover .play-badge { background: var(--accent); color: var(--accent-text); transform: translate(-50%, -50%) scale(1.08); }

/* ---------------------------------------------------------------------
   Playlist range picker + entry list
   --------------------------------------------------------------------- */
.range-row {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--text-dim);
  margin: 14px 0;
}
.range-row label { display: flex; align-items: center; gap: 6px; }
.range-row input[type="number"] {
  width: 64px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 7px 8px;
  color: var(--text);
  font-family: var(--font-display);
  font-size: 13px;
}
.range-row input[type="number"]:focus { outline: none; border-color: var(--accent); }
.range-hint { color: var(--text-dim); }

.playlist-list {
  max-height: 340px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow);
}
.playlist-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px 8px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  transition: background 0.15s;
  opacity: 0;
  animation: row-in 0.35s var(--ease) forwards;
}
.playlist-row:last-child { border-bottom: none; }
.playlist-row.in-range { background: var(--accent-soft); }
.playlist-row.is-unavailable { opacity: 0.5; animation: row-in-dim 0.35s var(--ease) forwards; }
.playlist-row .p-index { width: 22px; flex-shrink: 0; color: var(--text-dim); font-family: var(--font-display); text-align: right; }
.playlist-row .p-thumb {
  width: 56px; height: 32px; object-fit: cover; border-radius: 4px; background: var(--track); flex-shrink: 0;
  opacity: 0; transition: opacity 0.35s ease;
}
.playlist-row .p-thumb.is-loaded { opacity: 1; }
@keyframes row-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
@keyframes row-in-dim { from { opacity: 0; transform: translateY(6px); } to { opacity: 0.5; transform: translateY(0); } }
.playlist-row .p-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.playlist-row.is-unavailable .p-title { text-decoration: line-through; }
.playlist-row .p-duration { color: var(--text-dim); font-family: var(--font-display); font-size: 12px; flex-shrink: 0; }
.playlist-row .p-tag { color: var(--danger); font-size: 11px; flex-shrink: 0; }

/* per-row download button */
.p-dl-btn {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  transition: color 0.15s, border-color 0.15s, transform 0.15s var(--ease), background 0.15s;
}
.p-dl-btn:hover:not(:disabled) { color: var(--accent); border-color: var(--accent); transform: scale(1.08); }
.p-dl-btn:disabled { cursor: default; }
.p-dl-btn svg { pointer-events: none; }
.p-dl-btn .p-dl-icon-idle,
.p-dl-btn .p-dl-icon-done,
.p-dl-btn .p-dl-icon-error { display: flex; }
.p-dl-btn .p-dl-icon-done,
.p-dl-btn .p-dl-icon-error,
.p-dl-btn .p-dl-spinner { display: none; }
.p-dl-btn[data-state="working"] .p-dl-icon-idle { display: none; }
.p-dl-btn[data-state="working"] .p-dl-spinner { display: block; animation: spin 0.8s linear infinite; }
.p-dl-btn[data-state="done"] .p-dl-icon-idle { display: none; }
.p-dl-btn[data-state="done"] .p-dl-icon-done { display: flex; color: var(--success); animation: pop-in 0.3s var(--ease); }
.p-dl-btn[data-state="error"] .p-dl-icon-idle { display: none; }
.p-dl-btn[data-state="error"] .p-dl-icon-error { display: flex; color: var(--danger); }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pop-in { from { transform: scale(0.5); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* generic inline spinner used inside buttons while an async action runs */
.inline-spinner {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  flex-shrink: 0;
  animation: spin 0.7s linear infinite;
}

/* ---------------------------------------------------------------------
   Manual save fallback link
   --------------------------------------------------------------------- */
.manual-save-link {
  font-size: 12px;
  color: var(--text-dim);
  text-decoration: underline;
  align-self: flex-start;
}
.manual-save-link:hover { color: var(--accent); }

/* ---------------------------------------------------------------------
   Footer LAN address styling
   --------------------------------------------------------------------- */
.footer code {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 2px 6px;
  font-family: var(--font-display);
  color: var(--text);
}

/* ---------------------------------------------------------------------
   History page
   --------------------------------------------------------------------- */
.history-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 22px;
  flex-wrap: wrap;
}
.history-head .video-sub strong { color: var(--text); }

.history-filters {
  display: flex;
  gap: 10px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}
.history-filters #historySearchInput {
  flex: 1;
  min-width: 180px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 9px 12px;
  color: var(--text);
  font-size: 13px;
  font-family: var(--font-body);
}
.history-filters #historySearchInput:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
/* The three history filters are enhanced into .csel dropdowns (see
   enhanceSelect() in app.js) so they match the styled selects used
   everywhere else instead of the browser's native dropdown chrome. They
   sit in this flex row rather than a full-width field, so give the
   wrapper a sane shrink-to-fit width instead of the 100%-wide default
   the other .csel usages rely on. */
.history-filters .csel {
  flex: 0 1 auto;
  min-width: 150px;
}
.history-filters .csel-trigger { white-space: nowrap; }

.history-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 60px 20px;
  color: var(--text-dim);
  text-align: center;
}
.history-empty svg { opacity: 0.5; }

.history-list { display: flex; flex-direction: column; gap: 10px; }

.history-card {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  gap: 12px;
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-m);
  padding: 10px 14px;
  box-shadow: var(--shadow);
  opacity: 0;
  cursor: pointer;
  animation: rise-in 0.3s var(--ease) forwards;
  transition: border-color 0.15s, transform 0.15s var(--ease), opacity 0.2s var(--ease);
}
.history-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.history-card.is-expired,
.history-card.is-error { animation-name: rise-in-dim; }
.history-card.is-removing { opacity: 0 !important; transform: translateX(14px) scale(0.97); pointer-events: none; }
@keyframes rise-in-dim { from { opacity: 0; transform: translateY(14px); } to { opacity: 0.55; transform: translateY(0); } }

/* Same link, same hour, multiple files - collapsed to one summary card
   that expands to the individual ones (see groupHistoryJobs/renderHistory). */
.history-group {
  opacity: 0;
  animation: rise-in 0.3s var(--ease) forwards;
}
.history-group-header {
  animation: none;
  opacity: 1;
  margin: 0;
}
.h-group-toggle svg,
.h-chevron { transition: transform 0.2s var(--ease); }
.history-group.is-expanded .h-chevron { transform: rotate(180deg); }
.history-group-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 8px 0 0 20px;
  padding-left: 14px;
  border-left: 2px solid var(--border);
}
.history-group-list .history-card { animation: none; opacity: 1; }

.h-thumb {
  width: 64px;
  height: 36px;
  object-fit: cover;
  border-radius: 6px;
  background: var(--track);
  flex-shrink: 0;
  opacity: 0;
  transition: opacity 0.35s ease;
}
.h-thumb.is-loaded { opacity: 1; }
.h-thumb-fallback {
  width: 64px;
  height: 36px;
  border-radius: 6px;
  background: var(--track);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  flex-shrink: 0;
}

.h-info { min-width: 0; }
.h-title {
  font-family: var(--font-display);
  font-size: 14.5px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0 0 3px;
}
.h-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  font-size: 12px;
  color: var(--text-dim);
}
.h-kind { display: inline-flex; align-items: center; gap: 4px; }
.h-kind .platform-icon { flex-shrink: 0; opacity: 0.8; }
.h-tag {
  display: inline-flex;
  align-items: center;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--track);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.h-tag.is-ready { background: var(--accent-soft); color: var(--accent); }
.h-tag.is-expired { color: var(--danger); }
.h-tag.is-error { color: var(--danger); }
.h-tag.is-progress { color: var(--accent-2); }

.h-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.h-btn {
  width: 34px;
  height: 34px;
  border-radius: var(--radius-s);
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, transform 0.15s var(--ease);
}
.h-btn:hover { transform: translateY(-1px); }
.h-btn:active:not(:disabled) { transform: translateY(0) scale(0.92); }
.h-btn.h-save:hover { color: var(--accent); border-color: var(--accent); }
.h-btn.h-redownload:hover { color: var(--accent); border-color: var(--accent); }
.h-btn.h-delete:hover { color: var(--danger); border-color: var(--danger); }
.h-btn.h-preview:hover { color: var(--accent); border-color: var(--accent); }
.history-card.is-previewing .h-btn.h-preview { color: var(--accent-text); background: linear-gradient(135deg, var(--accent), var(--accent-2)); border-color: transparent; }
.h-btn:disabled { opacity: 0.4; cursor: default; transform: none; }

/* Custom mp3-style preview player (replaces the native <audio controls>
   bar, which rendered with the browser's own chrome and never matched
   the rest of the UI) - shared by the History page's file preview and
   the Stems page's per-stem preview. The real <audio> element stays in
   the DOM with no controls attribute - it's just the playback engine -
   while this themed bar drives it (see audioPlayerHtml()/wireAudioPlayer()
   in app.js).
   --------------------------------------------------------------------- */
.audio-player {
  display: none;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 10px;
  margin-top: 8px;
  padding: 8px 10px;
  background: var(--track);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
}
.history-card.is-previewing .audio-player,
.stems-part-row.is-previewing .audio-player { display: flex; }
.audio-player audio { display: none; }

.audio-player-toggle {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: var(--accent-text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.15s var(--ease);
}
.audio-player-toggle:hover { transform: scale(1.08); }
.audio-player-toggle:active { transform: scale(0.9); }
.audio-player-toggle .ico-pause { display: none; }
.audio-player.is-playing .audio-player-toggle .ico-play { display: none; }
.audio-player.is-playing .audio-player-toggle .ico-pause { display: block; }

/* Waveform track - a SoundCloud-style bar chart instead of a flat
   progress line, drawn in the app's own accent gradient (played) against
   a dim, muted color (not-yet-played) rather than SoundCloud's orange. */
.audio-player-track {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 40px;
  display: flex;
  align-items: center;
  cursor: pointer;
  touch-action: none;
  overflow: hidden;
  border-radius: 4px;
}
.audio-player-wave {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 0.25s var(--ease);
}
.audio-player-wave.is-ready { opacity: 1; }
.audio-player-wave.is-ready ~ .audio-player-fill { display: none; }

/* Flat fallback bar - visible only until the waveform finishes decoding,
   or permanently on a browser without Web Audio support. */
.audio-player-fill {
  position: absolute;
  left: 0;
  top: 50%;
  width: 0%;
  height: 4px;
  transform: translateY(-50%);
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  border-radius: 2px;
  pointer-events: none;
}
.audio-player-track:not(:has(.audio-player-wave.is-ready))::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 4px;
  transform: translateY(-50%);
  background: var(--border);
  border-radius: 2px;
}

.audio-player-badge {
  flex-shrink: 0;
  min-width: 76px;
  text-align: right;
  padding: 2px 0;
  color: var(--text-dim);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
  pointer-events: none;
  white-space: nowrap;
}

.audio-player-volume {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--text-dim);
}
.audio-player-volume svg { flex-shrink: 0; }
.audio-player-volume-range {
  width: 56px;
  accent-color: var(--accent);
  height: 3px;
}

/* The Subtitles page's preview isn't inside a history card or stems row,
   so it needs its own opt-in for the player to actually be visible -
   .audio-player defaults to hidden above since most instances only show
   once a row is toggled into "previewing" mode. */
.audio-player-slot .audio-player { display: flex; margin-top: 0; }

/* Video variant of the same styled player - the video frame stands in
   for the waveform, stacked above the same play/seek/volume bar instead
   of beside it, and used instead of a bare native <video controls> so a
   subtitle burn-in preview looks and behaves like every other preview in
   the app (one volume control, not a native one plus a separate custom
   one fighting for the same job). */
.video-player {
  flex-direction: column;
  align-items: stretch;
  padding: 0;
  overflow: hidden;
  background: #000;
}
.video-player video {
  width: 100%;
  max-height: 360px;
  display: block;
  background: #000;
}
.video-player-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 10px;
  padding: 8px 10px;
  background: var(--track);
}

.video-player-fullscreen {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border: none;
  background: none;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-s);
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.video-player-fullscreen:hover { color: var(--text); background: var(--surface); }
.video-player-fullscreen .ico-collapse { display: none; }
.video-player.is-fullscreen .video-player-fullscreen .ico-expand { display: none; }
.video-player.is-fullscreen .video-player-fullscreen .ico-collapse { display: block; }

/* In fullscreen the container itself (not just the <video>) is what's
   fullscreened, so the themed control bar stays visible/usable instead
   of being replaced by the browser's own native fullscreen video chrome. */
.video-player:fullscreen { background: #000; }
.video-player:fullscreen video { max-height: none; flex: 1; min-height: 0; }
.video-player.is-fullscreen { height: 100%; display: flex; }

/* ---------------------------------------------------------------------
   Music-detected hint
   --------------------------------------------------------------------- */
.music-hint {
  margin: 6px 0 0;
  font-size: 12.5px;
  color: var(--accent);
}

/* ---------------------------------------------------------------------
   Flying-file send-to-browser animation
   --------------------------------------------------------------------- */
.flying-file {
  position: fixed;
  z-index: 2000;
  color: var(--accent);
  pointer-events: none;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.35));
  transform: translate(-50%, -50%);
}

.landing-pulse {
  position: fixed;
  z-index: 1999;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: var(--accent);
  pointer-events: none;
  animation: landing-pulse-anim 0.5s var(--ease) forwards;
}
@keyframes landing-pulse-anim {
  0%   { transform: scale(0.4); opacity: 0.9; }
  70%  { transform: scale(2.6); opacity: 0.25; }
  100% { transform: scale(3.4); opacity: 0; }
}

/* ---------------------------------------------------------------------
   History detail overlay
   --------------------------------------------------------------------- */
.hd-overlay {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.5);
  opacity: 0;
  transition: opacity 0.2s var(--ease);
}
.hd-overlay.is-open { opacity: 1; }

.hd-panel {
  position: relative;
  width: 100%;
  max-width: 420px;
  max-height: 86vh;
  overflow-y: auto;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow);
  padding: 22px;
  transform: translateY(10px) scale(0.98);
  opacity: 0;
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease);
}
.hd-overlay.is-open .hd-panel { transform: translateY(0) scale(1); opacity: 1; }

.hd-close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.hd-close:hover { color: var(--text); border-color: var(--text-dim); }

.hd-thumb {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--radius-m);
  background: var(--track);
  margin-bottom: 14px;
}
.hd-thumb[src=""] { display: none; }

.hd-title {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  margin: 0 0 14px;
  padding-right: 26px;
  line-height: 1.35;
}

.hd-rows { display: flex; flex-direction: column; gap: 2px; margin-bottom: 18px; }
.hd-row {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13.5px;
}
.hd-row:last-child { border-bottom: none; }
.hd-label { color: var(--text-dim); flex-shrink: 0; }
.hd-value { color: var(--text); text-align: right; overflow-wrap: anywhere; }
.hd-value-icon { display: inline-flex; align-items: center; gap: 5px; justify-content: flex-end; }
.hd-value-icon .platform-icon { flex-shrink: 0; opacity: 0.8; }

.hd-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.hd-actions .btn-primary,
.hd-actions .btn-secondary { flex: 1; justify-content: center; }

/* ---------------------------------------------------------------------
   Responsive
   --------------------------------------------------------------------- */
@media (max-width: 520px) {
  .options-grid { grid-template-columns: 1fr; }
  .estimate-row { flex-direction: column; align-items: stretch; }
  .btn-wide { width: 100%; }
  .history-card { grid-template-columns: 48px 1fr; }
  .h-thumb, .h-thumb-fallback { width: 48px; height: 30px; }
  .h-actions { grid-column: 1 / -1; justify-content: flex-end; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
/* ---------------------------------------------------------------------
   Auth + home pages (login.html / home.html)

   These render standalone, outside the app shell, so they carry their own
   layout. They reuse the app's existing custom properties (--accent,
   --surface, --border, ...) so the theme stays consistent.
   --------------------------------------------------------------------- */
.auth-body {
  min-height: 100dvh;
  margin: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  overflow-x: hidden;
}

/* Animated background: three slowly drifting colour orbs behind a faint
   grid. Uses transform only (compositor-friendly), and stops entirely
   under prefers-reduced-motion via the global rule further up. */
.auth-bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.auth-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.5;
  will-change: transform;
}
.auth-orb-1 {
  width: 46vmax; height: 46vmax;
  left: -12vmax; top: -14vmax;
  background: radial-gradient(circle at 30% 30%, var(--accent), transparent 68%);
  animation: orb-drift-1 26s ease-in-out infinite;
}
.auth-orb-2 {
  width: 40vmax; height: 40vmax;
  right: -12vmax; top: 8vmax;
  background: radial-gradient(circle at 60% 40%, var(--accent-2, #6f7bf7), transparent 68%);
  animation: orb-drift-2 32s ease-in-out infinite;
}
.auth-orb-3 {
  width: 36vmax; height: 36vmax;
  left: 28vmax; bottom: -18vmax;
  background: radial-gradient(circle at 50% 50%, #8b5cf6, transparent 70%);
  animation: orb-drift-3 38s ease-in-out infinite;
  opacity: 0.35;
}
@keyframes orb-drift-1 {
  0%, 100% { transform: translate3d(0,0,0) scale(1); }
  50%      { transform: translate3d(6vmax, 5vmax, 0) scale(1.12); }
}
@keyframes orb-drift-2 {
  0%, 100% { transform: translate3d(0,0,0) scale(1.05); }
  50%      { transform: translate3d(-7vmax, 6vmax, 0) scale(0.92); }
}
@keyframes orb-drift-3 {
  0%, 100% { transform: translate3d(0,0,0) scale(0.95); }
  50%      { transform: translate3d(5vmax, -6vmax, 0) scale(1.1); }
}
.auth-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, rgba(255,255,255,0.035) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,0.035) 1px, transparent 1px);
  background-size: 54px 54px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, #000 30%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, #000 30%, transparent 78%);
}

/* ---- login card ---- */
.auth-shell {
  position: relative;
  z-index: 1;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.auth-card {
  width: 100%;
  max-width: 400px;
  padding: 38px 32px 32px;
  text-align: center;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--radius-l, 20px);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 24px 70px -24px rgba(0,0,0,0.65);
  animation: auth-card-in 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes auth-card-in {
  from { opacity: 0; transform: translateY(18px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.auth-logo {
  width: 68px; height: 68px;
  margin: 0 auto 18px;
  display: grid;
  place-items: center;
  border-radius: 20px;
  background: linear-gradient(140deg, color-mix(in srgb, var(--accent) 26%, transparent), transparent);
  border: 1px solid var(--border);
}
.auth-title { margin: 0 0 6px; font-size: 27px; font-weight: 700; letter-spacing: -0.02em; }
.auth-sub { margin: 0 0 26px; color: var(--text-dim); font-size: 14px; line-height: 1.55; }

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-align: left;
}
.auth-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-dim);
}
.auth-field input {
  padding: 12px 14px;
  border-radius: var(--radius-m, 12px);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 15px;
  font-family: inherit;
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.auth-field input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.auth-submit-btn {
  margin-top: 4px;
  width: 100%;
  padding: 13px 18px;
  border: none;
  border-radius: var(--radius-m, 12px);
  background: var(--accent);
  color: #06201c;
  font-size: 15px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease), filter 0.18s;
}
.auth-submit-btn:hover { transform: translateY(-2px); box-shadow: 0 14px 30px -12px rgba(0,0,0,0.5); filter: brightness(1.04); }
.auth-submit-btn:active { transform: translateY(0) scale(0.985); }
.auth-submit-btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; box-shadow: none; filter: none; }

.auth-note { margin: 15px 0 0; font-size: 12.5px; color: var(--text-dim); }
.auth-alert {
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: left;
  padding: 14px 16px;
  border-radius: var(--radius-m, 12px);
  background: color-mix(in srgb, var(--danger, #e0654f) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger, #e0654f) 40%, transparent);
  font-size: 13px;
  line-height: 1.5;
}
.auth-alert code {
  background: rgba(0,0,0,0.3);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 12px;
}
.auth-error {
  margin: 16px 0 0;
  padding: 11px 14px;
  border-radius: var(--radius-m, 12px);
  background: color-mix(in srgb, var(--danger, #e0654f) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger, #e0654f) 38%, transparent);
  color: var(--text);
  font-size: 13px;
  line-height: 1.5;
  animation: auth-card-in 0.35s var(--ease) both;
}

/* ---- home / landing ---- */
.home-nav {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 26px;
  max-width: 1100px;
  margin: 0 auto;
  width: 100%;
  box-sizing: border-box;
}
.home-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  text-decoration: none;
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.01em;
}
.home-nav-actions { display: flex; align-items: center; gap: 10px; }
.btn-compact { padding: 9px 17px !important; font-size: 14px !important; }
.btn-lg { padding: 14px 30px !important; font-size: 15.5px !important; }
.btn-ghost {
  padding: 9px 15px;
  border: none;
  border-radius: var(--radius-s, 9px);
  background: none;
  color: var(--text-dim);
  text-decoration: none;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.btn-ghost:hover { color: var(--text); background: var(--surface-raised); }

.home-shell {
  position: relative;
  z-index: 1;
  flex: 1;
  max-width: 1100px;
  margin: 0 auto;
  padding: 40px 26px 60px;
  width: 100%;
  box-sizing: border-box;
}
.home-hero { text-align: center; padding: 42px 0 56px; }
.home-badge {
  display: inline-block;
  padding: 6px 15px;
  border-radius: 999px;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent);
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  animation: auth-card-in 0.5s var(--ease) both;
}
.home-title {
  margin: 22px 0 18px;
  font-size: clamp(32px, 6.2vw, 58px);
  line-height: 1.1;
  letter-spacing: -0.03em;
  font-weight: 750;
  animation: auth-card-in 0.6s cubic-bezier(0.22,1,0.36,1) 0.06s both;
}
.home-title-accent {
  background: linear-gradient(100deg, var(--accent), var(--accent-2, #6f7bf7) 70%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.home-lede {
  margin: 0 auto;
  max-width: 580px;
  color: var(--text-dim);
  font-size: clamp(14.5px, 1.7vw, 17px);
  line-height: 1.65;
  animation: auth-card-in 0.6s cubic-bezier(0.22,1,0.36,1) 0.12s both;
}
.home-cta { margin-top: 32px; animation: auth-card-in 0.6s cubic-bezier(0.22,1,0.36,1) 0.18s both; }

/* Scroll cue under the hero — bounces gently to invite scrolling. */
.scroll-cue {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin-top: 56px;
  color: var(--text-dim);
  text-decoration: none;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  opacity: 0.75;
  transition: opacity 0.2s, color 0.2s;
  animation: auth-card-in 0.6s cubic-bezier(0.22,1,0.36,1) 0.3s both;
}
.scroll-cue:hover { opacity: 1; color: var(--text); }
.scroll-cue svg { animation: scroll-cue-bob 1.8s ease-in-out infinite; }
@keyframes scroll-cue-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(5px); }
}
.story-anchor { scroll-margin-top: 20px; }

/* ---- generic reveal-on-scroll primitive ----
   Elements start hidden only once JS has confirmed it can drive the
   reveal (`.has-js` on <html>); without JS everything is visible
   immediately, and prefers-reduced-motion short-circuits it in the
   global rule near the top of this file. */
.has-js .reveal {
  opacity: 0;
  transform: translateY(36px);
  transition: opacity 0.8s var(--ease), transform 0.8s var(--ease);
}
.has-js .reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* ---- oversized intro statement ---- */
.home-intro {
  max-width: 760px;
  margin: 0 auto;
  padding: 96px 8px;
  text-align: center;
}
.home-intro-text {
  margin: 0;
  font-size: clamp(22px, 4vw, 36px);
  line-height: 1.45;
  font-weight: 650;
  letter-spacing: -0.015em;
  color: var(--text);
}

/* ---- alternating feature story rows ---- */
.feature-story {
  display: flex;
  flex-direction: column;
  gap: 26px;
  padding: 10px 0 70px;
}
.feature-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: 48px;
  padding: 40px;
  border-radius: var(--radius-l, 20px);
  background: color-mix(in srgb, var(--surface) 55%, transparent);
  border: 1px solid var(--border);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.feature-row.is-reverse .feature-copy { order: 2; }
.feature-row.is-reverse .feature-visual { order: 1; }

.feature-kicker {
  display: inline-block;
  margin-bottom: 14px;
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.feature-copy h2 {
  margin: 0 0 14px;
  font-size: clamp(21px, 2.6vw, 29px);
  line-height: 1.25;
  letter-spacing: -0.015em;
  font-weight: 700;
}
.feature-copy p {
  margin: 0 0 18px;
  color: var(--text-dim);
  font-size: 15px;
  line-height: 1.65;
  max-width: 46ch;
}
.feature-points {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.feature-points li {
  position: relative;
  padding-left: 22px;
  color: var(--text-dim);
  font-size: 13.5px;
  line-height: 1.5;
}
.feature-points li::before {
  content: "";
  position: absolute;
  left: 0; top: 6px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2, #6f7bf7));
}

/* ---- feature illustration panel ----
   Abstract, self-drawn (no external images): a soft gradient glow, the
   feature's own line icon, and two concentric rings that spin slowly.
   `--parallax` is set from JS as the row crosses the viewport, and
   translateY(var(--parallax, 0px)) is a no-op without JS. */
.feature-visual {
  position: relative;
  aspect-ratio: 1 / 1;
  max-width: 320px;
  margin: 0 auto;
  width: 100%;
  display: grid;
  place-items: center;
  border-radius: var(--radius-l, 22px);
  background: var(--surface-raised);
  border: 1px solid var(--border);
  color: var(--accent);
  overflow: hidden;
  transform: translateY(var(--parallax, 0px));
  transition: transform 0.15s linear;
}
.feature-visual-glow {
  position: absolute;
  inset: -30%;
  background: radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--accent) 30%, transparent), transparent 68%);
  opacity: 0.8;
}
.feature-visual svg { position: relative; z-index: 1; }
.feature-visual-ring {
  position: absolute;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.feature-visual-ring-1 { width: 62%; height: 62%; animation: ring-spin 22s linear infinite; }
.feature-visual-ring-2 { width: 84%; height: 84%; border-style: dashed; animation: ring-spin 34s linear infinite reverse; }
@keyframes ring-spin { to { transform: rotate(360deg); } }

.visual-enhance { color: var(--accent-2, #6f7bf7); }
.visual-enhance .feature-visual-glow { background: radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--accent-2, #6f7bf7) 30%, transparent), transparent 68%); }
.visual-enhance .feature-visual-ring { border-color: color-mix(in srgb, var(--accent-2, #6f7bf7) 30%, transparent); }

.visual-subtitles { color: #8b5cf6; }
.visual-subtitles .feature-visual-glow { background: radial-gradient(circle at 50% 45%, rgba(139, 92, 246, 0.3), transparent 68%); }
.visual-subtitles .feature-visual-ring { border-color: rgba(139, 92, 246, 0.32); }

.visual-audio { color: var(--accent); }

/* ---- stat strip ---- */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 20px;
  padding: 20px 36px;
  margin: 10px 0 80px;
  border-radius: var(--radius-l, 20px);
  background: color-mix(in srgb, var(--surface) 55%, transparent);
  border: 1px solid var(--border);
  text-align: center;
}
.stat-item { padding: 22px 8px; display: flex; flex-direction: column; gap: 6px; }
.stat-number {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.4vw, 40px);
  font-weight: 700;
  background: linear-gradient(100deg, var(--accent), var(--accent-2, #6f7bf7) 70%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.stat-label { color: var(--text-dim); font-size: 13px; line-height: 1.5; }

/* ---- closing CTA ---- */
.home-final-cta {
  text-align: center;
  padding: 76px 24px;
  margin-bottom: 30px;
  border-radius: var(--radius-l, 24px);
  background:
    radial-gradient(ellipse 600px 300px at 50% 0%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 70%),
    color-mix(in srgb, var(--surface) 60%, transparent);
  border: 1px solid var(--border);
}
.home-final-cta h2 { margin: 0 0 10px; font-size: clamp(24px, 3.4vw, 34px); letter-spacing: -0.02em; }
.home-final-cta p { margin: 0 0 28px; color: var(--text-dim); font-size: 14.5px; }
.home-final-cta .auth-note { margin: 16px 0 0; }

/* Inline text-button, styled like a link, for actions that aren't
   navigation (e.g. opening the request-access modal). */
.link-btn {
  padding: 0;
  border: none;
  background: none;
  color: var(--accent);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.link-btn:hover { color: var(--text); }

/* ---------------------------------------------------------------------
   Request-access modal
   --------------------------------------------------------------------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(6, 8, 12, 0.6);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: modal-fade-in 0.2s var(--ease) both;
}
.modal-overlay:not([hidden]) { display: flex; }
@keyframes modal-fade-in { from { opacity: 0; } to { opacity: 1; } }

.modal-card {
  position: relative;
  max-width: 420px;
  max-height: calc(100dvh - 40px);
  overflow-y: auto;
  animation: auth-card-in 0.3s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.modal-close {
  position: absolute;
  top: 14px; right: 14px;
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.modal-close:hover { color: var(--text); border-color: var(--text-dim); }

.pw-field { position: relative; }
.pw-field input { width: 100%; box-sizing: border-box; padding-right: 42px; }
.pw-toggle {
  position: absolute;
  top: 50%; right: 6px;
  transform: translateY(-50%);
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  border: none;
  background: none;
  border-radius: var(--radius-s, 8px);
  color: var(--text-dim);
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.pw-toggle:hover { color: var(--text); background: var(--surface-raised); }

.request-note {
  margin: -4px 0 0;
  color: var(--text-dim);
  font-size: 12px;
  line-height: 1.55;
  font-weight: 400;
}
.request-accept {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-dim);
  cursor: pointer;
}
.request-accept input { margin-top: 2px; accent-color: var(--accent); flex-shrink: 0; }

.request-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px;
  margin-bottom: 20px;
  border-radius: var(--radius-m, 12px);
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 13.5px;
  color: var(--text-dim);
}
.request-summary strong { color: var(--text); font-family: var(--font-display); }
#requestStepDone .btn-lg { width: 100%; box-sizing: border-box; text-align: center; text-decoration: none; display: block; }

.home-footer {
  position: relative;
  z-index: 1;
  padding: 26px;
  text-align: center;
  color: var(--text-dim);
  font-size: 12.5px;
}

@media (max-width: 860px) {
  .feature-row {
    grid-template-columns: 1fr;
    gap: 28px;
    padding: 30px 26px;
  }
  .feature-row.is-reverse .feature-copy,
  .feature-row.is-reverse .feature-visual { order: initial; }
  .feature-visual { max-width: 240px; }
  .feature-copy p { max-width: none; }
}

@media (max-width: 560px) {
  .home-hero { padding: 26px 0 40px; }
  .auth-card { padding: 30px 22px 26px; }
  .home-intro { padding: 64px 4px; }
  .scroll-cue { margin-top: 40px; }
  .stat-strip { padding: 20px; }
}

/* ---- signed-in user chip (app header) ---- */
.user-chip { position: relative; flex-shrink: 0; }
.user-chip-btn {
  width: 34px; height: 34px;
  padding: 0;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.18s, transform 0.18s var(--ease);
}
.user-chip-btn:hover { border-color: var(--accent); transform: scale(1.06); }
.user-chip-btn img { width: 100%; height: 100%; object-fit: cover; display: block; }
.user-chip-initial { font-weight: 700; font-size: 14px; color: var(--accent); }
.user-menu {
  position: absolute;
  right: 0; top: calc(100% + 8px);
  min-width: 212px;
  z-index: 60;
  padding: 6px;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-m, 12px);
  box-shadow: 0 18px 44px -18px rgba(0,0,0,0.75);
  animation: menu-in 0.16s var(--ease);
}
.user-menu-head {
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 11px 11px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 5px;
}
.user-menu-head strong { font-size: 13.5px; }
.user-menu-head span { font-size: 11.5px; color: var(--text-dim); word-break: break-all; }
.user-admin-badge {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 20%, transparent);
  color: var(--accent);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  vertical-align: middle;
}
.user-menu-item {
  display: block;
  padding: 9px 11px;
  border-radius: var(--radius-s, 8px);
  color: var(--text);
  text-decoration: none;
  font-size: 13.5px;
  transition: background 0.14s, color 0.14s;
}
.user-menu-item:hover { background: var(--surface); color: var(--accent); }
.user-menu-item.is-danger:hover { color: var(--danger, #e0654f); }