* {
  box-sizing: border-box;
}

/* Control radii alias the canonical design-system scale (foundation.css
   --radius-*) so changing the scale propagates everywhere. Snapped on-scale:
   small=8, control=12, large=16, header=pill. See /design-system.
   These MUST live on :root (not .mv-app): modals/popovers are rendered OUTSIDE
   .mv-app, so if scoped to .mv-app, var(--mv-control-radius*) is undefined there
   and border-radius collapses to 0 → square cards. */
:root {
  --mv-control-radius: var(--radius-3);
  --mv-control-radius-lg: var(--radius-4);
  --mv-control-radius-sm: var(--radius-2);
  --mv-header-control-radius: var(--radius-pill);
}

.mv-app {
  --mv-header-control-height: 46px;
  /* svh (not dvh): mobile browser chrome show/hide changes dvh while scrolling
     the left controls and resizes the sticky preview shell mid-scroll. Small
     viewport units keep the preview size stable. */
  --mv-preview-max-height: min(72svh, calc(100svh - 240px));
}

body {
  margin: 0;
  min-height: 100vh;
  background: linear-gradient(180deg, #f5f5f3 0%, #efefe9 100%);
  overflow-x: hidden;
}

html.dark body {
  background: linear-gradient(180deg, #10100f 0%, #151512 100%);
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
}

[hidden] {
  display: none !important;
}

input,
select,
textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  background: var(--surface);
  color: var(--ink);
  padding: 12px 14px;
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}

input:focus,
select:focus,
textarea:focus,
button:focus-visible {
  outline: none;
  border-color: var(--ink-3);
  box-shadow: var(--shadow-focus);
}

textarea {
  min-height: 110px;
  resize: vertical;
}

input::file-selector-button {
  display: none;
}

input[type="range"] {
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
}

input[type="color"] {
  min-height: 48px;
  padding: 6px;
}

input[type="checkbox"] {
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: var(--radius-1);
  accent-color: var(--ink);
  box-shadow: none;
}

/* Radios (Branding choice) size like checkboxes; they sit in flex
   .mv-check-row rows that center-align. */
input[type="radio"] {
  width: 18px;
  height: 18px;
  flex: none;
  padding: 0;
  accent-color: var(--ink);
  box-shadow: none;
}

audio {
  width: 100%;
}

.mv-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(245, 245, 243, 0.92);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  animation: mv-fade 220ms var(--ease-out);
}

/* Dark mode: the near-white backdrop above would flash a bright sheet over the
   dark editor (notably on Reset, which opens this modal). Use a dark scrim. */
html.dark .mv-modal {
  background: rgba(16, 16, 15, 0.92);
}

@keyframes mv-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

.mv-modal-card {
  width: min(560px, 100%);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-4);
  padding: 32px;
  box-shadow: 0 30px 80px rgba(17, 17, 17, 0.12);
  text-align: center;
}

.mv-modal-card h2 {
  margin: 6px 0 4px;
  font-size: var(--text-2xl);
  letter-spacing: var(--tracking-snug);
}

.mv-modal-sub {
  margin: 0 0 24px;
  color: var(--ink-3);
  font-size: var(--text-sm);
}

.mv-modal-foot {
  margin: 22px 0 0;
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-4);
}

.mv-preview-modal-card {
  width: min(960px, calc(100vw - 40px));
  padding: 22px;
  text-align: left;
}
.mv-preview-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 14px;
}
.mv-preview-modal-head h2 {
  margin: 4px 0 0;
}
.mv-preview-modal-video {
  width: 100%;
  max-height: min(70vh, 680px);
  display: block;
  border-radius: var(--radius-3);
  background: #000;
}
.mv-preview-modal-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 14px;
}

/* Pre-render confirmation summary (render-confirm-modal) */
.mv-render-summary {
  text-align: left;
  border: 1px solid var(--line);
  border-radius: var(--radius-2, 10px);
  overflow: hidden;
}

.mv-render-summary-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  font-size: var(--text-sm);
}

.mv-render-summary-row + .mv-render-summary-row {
  border-top: 1px solid var(--line);
}

.mv-render-summary-label {
  flex: 0 0 108px;
  color: var(--ink-4);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.mv-render-summary-value {
  flex: 1;
  color: var(--ink);
  min-width: 0;
  overflow-wrap: anywhere;
}

.mv-render-summary-value small {
  color: var(--ink-3);
}

.mv-render-summary-thumb {
  flex: 0 0 auto;
  width: 64px;
  height: 36px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: #000;
}

/* Portrait (9:16) renders get a portrait thumb so the capture isn't squashed. */
.mv-render-summary-thumb.is-portrait {
  width: 36px;
  height: 64px;
}

/* Square (1:1) renders get a square thumb. */
.mv-render-summary-thumb.is-square {
  width: 48px;
  height: 48px;
}

.mv-render-warnings {
  margin-top: 14px;
  text-align: left;
  border: 1px solid #e8c46a;
  background: #fdf6e3;
  color: #7a5a00;
  border-radius: var(--radius-2, 10px);
  padding: 10px 14px;
  font-size: var(--text-sm);
}

.mv-render-warnings p {
  margin: 0;
}

.mv-render-warnings p + p {
  margin-top: 6px;
}

/* Background-video loop style toggle (Crossfade / Ping-pong) */
.mv-loop-toggle {
  display: flex;
  gap: 6px;
  margin-top: 6px;
}

.mv-loop-option {
  flex: 1;
  padding: 7px 10px;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--ink-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 120ms, color 120ms;
}

.mv-loop-option:hover {
  border-color: var(--ink-3);
}

.mv-loop-option.is-active {
  color: var(--ink);
  border-color: var(--ink);
  font-weight: 600;
}

.mv-aspect-options {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}

.mv-aspect-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 22px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-4);
  background: #fbfbf9;
  transition: transform var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}

.mv-aspect-card:hover {
  border-color: var(--ink);
  background: #fff;
  transform: translateY(-2px);
}

html.dark .mv-aspect-card {
  background: #1f1f1c;
}

html.dark .mv-aspect-card:hover {
  background: #252521;
}

.mv-aspect-frame {
  display: block;
  background: linear-gradient(135deg, #1a1a1a 0%, #3a3a3a 100%);
  border-radius: var(--radius-2);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.mv-aspect-frame-landscape {
  width: 96px;
  height: 54px;
}

.mv-aspect-frame-portrait {
  width: 54px;
  height: 96px;
}

.mv-aspect-frame-square {
  width: 72px;
  height: 72px;
}

.mv-aspect-label {
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
}

.mv-aspect-meta {
  font-size: var(--text-xs);
  color: var(--ink-3);
  letter-spacing: 0.04em;
}

.mv-app {
  min-height: 100vh;
  padding: 32px;
  max-width: 100vw;
  overflow-x: clip;
}

.mv-header {
  width: min(1200px, 100%);
  margin: 0 auto 24px;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  align-items: flex-start;
}

.mv-header h1 {
  margin-top: 0;
  font-size: 22px;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.mv-beta-label {
  display: inline-block;
  margin-left: 7px;
  color: var(--ink);
  opacity: 0.5;
  font-size: 0.5em;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  vertical-align: 0.25em;
}

.mv-light {
  font-weight: 400;
}

.mv-preview-aspect {
  display: inline-flex;
  align-self: center;
  align-items: center;
  /* Snug around the 26px pills with equal top/bottom spacing (was 46px, too tall). */
  height: 38px;
  padding: 4px;
  border-radius: var(--mv-header-control-radius);
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(17, 17, 17, 0.03);
  margin-left: 8px;
  flex: 0 0 auto;
}

.mv-aspect-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  padding: 0 16px;
  border-radius: var(--mv-header-control-radius);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink-2);
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}

.mv-aspect-pill.is-active {
  background: var(--ink);
  color: #fff;
}

html.dark .mv-aspect-pill.is-active {
  color: #111;
}

.mv-header-tools {
  display: inline-flex;
  align-items: center;
  align-self: center;
  gap: 12px;
}

.mv-theme-toggle {
  width: var(--mv-header-control-height);
  height: var(--mv-header-control-height);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--mv-header-control-radius);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.7);
  color: var(--ink-2);
  box-shadow: 0 1px 2px rgba(17, 17, 17, 0.03);
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}

html.dark .mv-theme-toggle,
html.dark .mv-credit-pill,
html.dark .mv-preview-aspect {
  background: rgba(28, 28, 26, 0.78);
}

.mv-theme-toggle:hover {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.95);
  border-color: var(--ink-3);
}

html.dark .mv-theme-toggle:hover,
html.dark .mv-credit-pill:hover {
  background: rgba(34, 34, 31, 0.98);
}

.mv-theme-icon-sun,
html.dark .mv-theme-icon-moon {
  display: none;
}

html.dark .mv-theme-icon-sun {
  display: block;
}

.mv-credit-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--mv-header-control-height);
  padding: 0 16px;
  border-radius: var(--mv-header-control-radius);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.7);
  color: var(--ink-2);
  font-size: var(--text-sm);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  box-shadow: 0 1px 2px rgba(17, 17, 17, 0.03);
  cursor: pointer;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}

.mv-credit-pill:hover {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.95);
  border-color: var(--ink-3);
}

.mv-credit-pill:focus-visible {
  outline: none;
  color: var(--ink);
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(17, 17, 17, 0.12);
}

.mv-credit-pill:active {
  border-color: var(--ink);
  background: rgba(255, 255, 255, 1);
}

html.dark .mv-credit-pill:active {
  background: rgba(34, 34, 31, 1);
}

.mv-layout {
  width: min(1200px, 100%);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 360px minmax(0, 1fr);
  gap: 24px;
  align-items: start;
  min-width: 0;
}

.mv-sidebar {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

.mv-panel,
.mv-stage-panel {
  background: rgba(255, 255, 255, 0.82);
  border: 1px solid rgba(229, 229, 224, 0.9);
  border-radius: var(--radius-4);
  box-shadow: 0 18px 50px rgba(17, 17, 17, 0.06);
  backdrop-filter: blur(12px);
  contain: layout style;
}

html.dark .mv-panel,
html.dark .mv-stage-panel {
  background: rgba(24, 24, 22, 0.94);
  border-color: rgba(51, 51, 47, 0.9);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.2);
}

.mv-panel {
  padding: 18px;
}

.mv-panel-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: center;
  min-height: 50px;
  margin-bottom: 14px;
  cursor: pointer;
}

.mv-panel-head > div {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.mv-panel-body {
  display: block;
}

.mv-panel.is-collapsed .mv-panel-head {
  margin-bottom: 0;
}

.mv-panel-toggle {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  color: var(--ink-2);
  line-height: 1;
  transition: color var(--dur-1) var(--ease-out);
  flex: 0 0 auto;
}

.mv-panel-toggle-icon {
  width: 16px;
  height: 16px;
  transition: transform var(--dur-1) var(--ease-out);
}

.mv-panel-toggle[aria-expanded="true"] .mv-panel-toggle-icon {
  transform: rotate(180deg);
}

.mv-panel-toggle:hover {
  color: var(--ink);
}

.mv-field,
.mv-upload-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.mv-field + .mv-field,
.mv-upload-group + .mv-field,
.mv-preset-grid + .mv-upload-group,
.mv-field + .mv-upload-group,
.mv-check-row + .mv-field,
.mv-field + .mv-check-row {
  margin-top: 14px;
}

.mv-field + .mv-slider,
.mv-slider + .mv-slider,
.mv-slider + .mv-field {
  margin-top: 6px;
}

/* Normalise all form label/value text to match Track info */
input:not([type="range"]):not([type="color"]):not([type="checkbox"]),
select {
  font-weight: 500;
  color: var(--ink);
}

/* Clean Tailwind-style select (custom chevron, bordered box) */
.mv-select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  width: 100%;
  height: 40px;
  padding: 0 36px 0 12px;
  background-color: var(--surface);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  border: 1px solid var(--line);
  border-radius: var(--radius-2);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out);
}
.mv-select:hover { border-color: var(--ink-3); }
.mv-select:focus { outline: none; border-color: var(--ink); }

/* Background "Source" select should read the same size/shape as the "Style"
   dropdown (.mv-spectrum-trigger: min-height 40, radius var(--mv-control-radius))
   directly below it, so the two stacked controls match. */
#background-source.mv-select {
  height: auto;
  min-height: 40px;
  border-radius: var(--mv-control-radius);
}

/* Space between the Source dropdown and the image/video upload area */
#image-upload-group,
#video-upload-group {
  margin-top: 14px;
}

/* Cost badge on checkbox rows (e.g. Remove watermark · 5 cr) */
.mv-check-cost {
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-3);
}

.mv-field span:first-child {
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 500;
}

.mv-field[hidden] {
  display: none !important;
}

/* Small inline hint under a field (e.g. portrait 4K unavailable note) */
.mv-field-note {
  font-size: 11px;
  font-weight: 500;
  color: var(--ink-3);
}

.mv-field-note[hidden] {
  display: none !important;
}

/* Browser sample lives inside the Quality dropdown as a peer option, marked by a
   small green "Free" tag in place of a credit cost — no card, minimal footprint. */
.mv-free-tag {
  color: var(--accent-green, #2fae66) !important;
  font-weight: 700;
}
.mv-quality-free[hidden] { display: none !important; }
#free-export-status { margin-top: 8px; }
#free-export-status.is-free-note {
  color: var(--accent-green, #2fae66);
  font-weight: 600;
}

/* Muted hint/status/error under the branding + logo upload controls (sign-in
   prompt, brand-kit "Saved —" status, logo upload errors). Previously unstyled,
   so it rendered at full 14px body ink and read like a paragraph; this snaps it
   onto the same small-hint scale as .mv-field-note. Error states set an inline
   red color in JS (brandKitStatus), which still wins over this. */
.mv-upload-hint {
  margin: 0;
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 1.45;
  color: var(--ink-3);
}
.mv-upload-hint[hidden] {
  display: none !important;
}

.mv-check-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 500;
}

.mv-upload {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 48px;
  border-radius: var(--mv-control-radius);
  border: 1px dashed var(--line-2);
  background: var(--paper);
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 500;
  position: relative;
  overflow: hidden;
  transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}

.mv-upload:hover {
  border-color: var(--ink-3);
  background: #f2f2ee;
}

html.dark .mv-upload {
  background: #181816;
  border-color: #34342f;
  color: var(--ink);
}

html.dark .mv-upload:hover {
  background: #20201d;
  border-color: var(--ink-3);
}

.mv-upload input {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

.mv-inline-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 12px;
}

.mv-inline-label {
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-3);
}

.mv-inline-value {
  font-size: var(--text-sm);
  color: var(--ink);
  word-break: break-word;
}

/* ── Audio current-file block ── */
.mv-audio-current {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 2px;
}

.mv-audio-file-row {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #f5f5f3;
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  padding: 9px 10px 9px 14px;
}

.mv-audio-file-name {
  flex: 1;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink);
  word-break: break-all;
  line-height: 1.3;
}

.mv-audio-clear {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-2);
  color: var(--ink-3);
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}

.mv-audio-clear:hover {
  background: rgba(17, 17, 17, 0.07);
  color: var(--ink);
}

.mv-range-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 52px;
  gap: 10px;
  align-items: center;
}

.mv-range-row output {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  min-height: 40px;
  border-radius: var(--mv-control-radius);
  border: 1px solid var(--line);
  background: #fbfbf9;
  color: var(--ink-2);
  font-size: var(--text-sm);
}

.mv-color-input {
  background: var(--surface);
}

/* Track info — compact card */
.mv-track-card {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.mv-track-card .mv-field + .mv-field,
.mv-track-card .mv-field + .mv-slider,
.mv-track-card .mv-slider + .mv-slider,
.mv-track-card .mv-slider + .mv-field,
.mv-track-card .mv-field + .mv-field-row,
.mv-track-card .mv-field-row + .mv-slider {
  margin-top: 0;
}

.mv-field-row {
  display: block;
  gap: 12px;
  align-items: end;
}

.mv-track-tools-row {
  grid-template-columns: minmax(0, 1fr) minmax(132px, 0.48fr);
}

.mv-cover-tools,
.mv-extra-text-tools {
  display: grid;
  gap: 0;
}

.mv-extra-inline {
  display: grid;
  gap: 12px;
  padding-top: 2px;
}

.mv-extra-inline-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.mv-inline-add-btn,
.mv-inline-remove-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 38px;
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 500;
  transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}

.mv-inline-add-btn {
  width: 100%;
}

.mv-inline-remove-btn {
  width: 34px;
  min-height: 34px;
  color: var(--ink-2);
}

.mv-inline-add-btn:hover,
.mv-inline-remove-btn:hover {
  border-color: var(--ink-3);
  background: var(--paper);
  color: var(--ink);
}

.mv-font-select {
  font-size: var(--text-sm);
}

.mv-field-color {
  min-width: 0;
}

.mv-color-compact {
  width: 64px;
  min-height: 40px;
  padding: 4px;
}

/* Compact sliders: label + value on one row, slider below */
.mv-slider {
  display: grid;
  grid-template-columns: 30% 1fr;
  align-items: center;
  column-gap: 10px;
}

.mv-slider-top {
  display: flex;
  align-items: center;
  gap: 5px;
}

.mv-slider-top span {
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 500;
}

.mv-slider-icon {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  opacity: 0.35;
  color: var(--ink-2);
}

.mv-slider-val {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 46px;
  padding: 3px 9px;
  border-radius: var(--radius-2);
  border: 1px solid var(--line);
  background: #fbfbf9;
  color: var(--ink-2);
  font-size: var(--text-xs);
  white-space: nowrap;
}

/* ── Combined sidebar card ── */
.mv-sidebar-card {
  background: rgba(255, 255, 255, 0.82);
  border: 1px solid rgba(229, 229, 224, 0.9);
  border-radius: var(--radius-4);
  box-shadow: 0 18px 50px rgba(17, 17, 17, 0.06);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  /* overflow:visible — lets the font dropdown menus overflow the card.
     (overflow:hidden was clipping the dropdown and contain:layout was
     making position:fixed children treat the card as their viewport,
     which broke the color-picker popover entirely.) */
  overflow: visible;
  background-clip: padding-box;
  isolation: isolate;
}

html.dark .mv-sidebar-card {
  background: rgba(24, 24, 22, 0.94);
  border-color: rgba(51, 51, 47, 0.9);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.2);
}

/* Strip individual panel borders/backgrounds inside the combined card.
   backdrop-filter:none is critical — the base .mv-panel rule inherits
   backdrop-filter:blur which creates a stacking context per panel,
   scoping .mv-font-menu z-index to within that panel and making it
   unable to overlay the next panel. */
.mv-sidebar-card .mv-panel {
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  contain: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.mv-sidebar-card .mv-panel:first-child,
.mv-sidebar-card .mv-panel:first-child .mv-panel-head {
  border-top-left-radius: inherit;
  border-top-right-radius: inherit;
}

.mv-sidebar-card .mv-panel:last-child,
.mv-sidebar-card .mv-panel:last-child .mv-panel-body {
  border-bottom-left-radius: inherit;
  border-bottom-right-radius: inherit;
}

.mv-sidebar-card .mv-panel + .mv-panel {
  border-top: 1px solid var(--line);
}

.mv-sidebar-card .mv-panel-head {
  padding: 6px 18px;
  margin-bottom: 0;
}

.mv-sidebar-card .mv-panel-body {
  padding: 0 18px 16px;
}

/* ── Custom font dropdown ── */
.mv-field-label {
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 500;
}

.mv-font-dropdown {
  position: relative;
}

.mv-font-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 6px 8px;
  min-height: 40px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  color: var(--ink);
  font-size: var(--text-sm);
  transition: border-color var(--dur-1) var(--ease-out);
  cursor: pointer;
}

.mv-font-trigger:hover {
  border-color: var(--ink-3);
}

.mv-font-trigger:focus-visible {
  outline: none;
  border-color: var(--ink-3);
  box-shadow: var(--shadow-focus);
}

.mv-font-chevron {
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  color: var(--ink-3);
  transition: transform var(--dur-1) var(--ease-out);
}

.mv-font-dropdown[data-open] .mv-font-chevron {
  transform: rotate(180deg);
}

.mv-font-menu {
  position: absolute;
  z-index: 1000;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  box-shadow: 0 8px 28px rgba(17, 17, 17, 0.11);
  overflow: hidden;
  padding: 4px;
}

.mv-font-option {
  display: block;
  width: 100%;
  padding: 9px 12px;
  text-align: left;
  font-size: 15px;
  line-height: 1.3;
  color: var(--ink);
  border-radius: calc(var(--mv-control-radius) - 2px);
  transition: background var(--dur-1) var(--ease-out);
  cursor: pointer;
}

.mv-font-option:hover {
  background: var(--paper);
}

.mv-font-option.is-selected {
  background: var(--paper-2);
  color: var(--ink);
}

.mv-trim {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 14px;
}

.mv-trim-track {
  position: relative;
  height: 6px;
  border-radius: var(--radius-pill);
  background: rgba(17, 17, 17, 0.08);
}

.mv-trim-fill {
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--mv-accent);
  border-radius: inherit;
  left: 0%;
  right: 0%;
}

.mv-trim-inputs {
  position: relative;
  height: 18px;
  /* Overlay the thumbs onto the track bar above so it reads as one slider */
  margin-top: -20px;
}

.mv-trim-inputs input {
  position: absolute;
  inset: 0;
  width: 100%;
  background: transparent;
  border: 0;
  padding: 0;
  pointer-events: none;
  -webkit-appearance: none;
  appearance: none;
}

.mv-trim-inputs input::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--ink);
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(17, 17, 17, 0.25);
  pointer-events: auto;
  cursor: grab;
}

.mv-trim-inputs input::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--ink);
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(17, 17, 17, 0.25);
  pointer-events: auto;
  cursor: grab;
}

/* The two overlaid trim inputs otherwise inherit the global blue panel-slider
   track (an extra line). Force their native tracks transparent so only the
   single custom .mv-trim-fill range bar shows. */
.mv-trim-inputs input::-webkit-slider-runnable-track,
.mv-trim-inputs input::-moz-range-track,
.mv-trim-inputs input::-moz-range-progress {
  background: transparent !important;
}

.mv-trim-meta {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: var(--text-xs);
  color: var(--ink-3);
  letter-spacing: 0.02em;
}

.mv-trim-meta strong {
  font-weight: 500;
  color: var(--ink);
  font-feature-settings: "tnum" 1;
  margin: 0 4px;
}

.mv-trim-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ink);
  margin-right: 6px;
  vertical-align: middle;
}

.mv-trim-dot-end {
  margin-right: 0;
  margin-left: 6px;
}

.mv-preset-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

.mv-preset {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px;
  border-radius: var(--radius-3);
  border: 1px solid var(--line);
  background: var(--surface);
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}

.mv-preset:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-2);
}

.mv-preset.is-active {
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
}

.mv-preset span:last-child {
  font-size: var(--text-xs);
  font-weight: 500;
  text-align: left;
}

.mv-preset-swatch {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-3);
  position: relative;
  overflow: hidden;
}

.mv-preset-mesh {
  background:
    radial-gradient(circle at 20% 20%, #ff8da1 0%, transparent 38%),
    radial-gradient(circle at 80% 30%, #8ab4ff 0%, transparent 42%),
    radial-gradient(circle at 60% 80%, #f9c46b 0%, transparent 38%),
    linear-gradient(135deg, #f6e8ff 0%, #eaf6ff 100%);
}

.mv-preset-noir {
  background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
}

.mv-preset-noir::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 100%, rgba(255, 255, 255, 0.08) 0%, transparent 65%);
}

.mv-preset-pastel {
  background:
    radial-gradient(circle at 30% 30%, #ffc8d3 0%, transparent 45%),
    radial-gradient(circle at 75% 65%, #c8d8ff 0%, transparent 45%),
    linear-gradient(135deg, #fff3ef 0%, #f0eaff 100%);
}

.mv-preset-chrome {
  background: linear-gradient(135deg, #d8d8df 0%, #f4f4f6 25%, #b8c4d6 50%, #ecdef3 75%, #c8d8e8 100%);
}

.mv-preset-sage {
  background: linear-gradient(160deg, #e8f0e6 0%, #c8d6c0 100%);
}

.mv-preset-sage::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 70% 25%, rgba(255, 255, 255, 0.6) 0%, transparent 40%);
}

.mv-preset-dusk {
  background: linear-gradient(160deg, #2a1a3a 0%, #6a3a5a 55%, #ee9b7a 100%);
}

.mv-preset-onyx {
  background: linear-gradient(135deg, #000000 0%, #1a1a1c 50%, #000000 100%);
  position: relative;
}

.mv-preset-onyx::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.06) 0%, transparent 70%);
}

.mv-preset-gold {
  background: linear-gradient(160deg, #2a1f10 0%, #b08036 45%, #f5d589 80%, #fef0b8 100%);
  position: relative;
}

.mv-preset-gold::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 70% 25%, rgba(255, 240, 200, 0.45) 0%, transparent 50%);
}

.mv-preset-silver {
  background: linear-gradient(160deg, #2a2d33 0%, #8a929c 40%, #e0e4ea 70%, #c4cad2 100%);
  position: relative;
}

.mv-preset-silver::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(110deg, transparent 35%, rgba(255, 255, 255, 0.55) 50%, transparent 65%);
}

.mv-preset-vapor {
  background: linear-gradient(160deg, #2a1840 0%, #7a2a8a 40%, #e85aae 70%, #ffb37a 100%);
}

.mv-preset-ocean {
  background: linear-gradient(160deg, #021024 0%, #052a52 45%, #0a5680 80%, #6ec6df 100%);
}

.mv-preset-crimson {
  background: linear-gradient(160deg, #1a0408 0%, #560a16 45%, #a8202e 80%, #e84a5a 100%);
}

.mv-actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  margin: 14px 0 12px;
}

.mv-button {
  width: 100%;
  min-height: 48px;
  border-radius: var(--mv-control-radius);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 600;
  transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}

.mv-button:disabled {
  cursor: default;
  opacity: 0.72;
}

.mv-button-icon {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
}

.mv-button-icon-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.mv-button-icon-mark svg {
  width: 22px;
  height: 22px;
}

.mv-button:hover {
  border-color: var(--ink-3);
  background: #fbfbf8;
}

html.dark .mv-button:hover {
  background: #20201d;
}

/* Dark render button keeps its dark hover instead of going light. */
.mv-button-dark:hover { background: #2a2a28; border-color: #2a2a28; }
.mv-button-dark:disabled:hover { background: var(--ink); border-color: var(--ink); }

/* In-button loading spinner shown while a render is in progress. */
.mv-button-spinner {
  width: 18px;
  height: 18px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #ffffff;
  border-radius: 50%;
  animation: mv-btn-spin 0.7s linear infinite;
}

@keyframes mv-btn-spin { to { transform: rotate(360deg); } }

/* Live render cost + credit/login message under the Render button. */
.mv-render-cost {
  margin: 0;
  font-size: var(--text-xs);
  color: var(--ink-3);
  text-align: center;
}

.mv-render-message {
  margin: 2px 0 0;
  font-size: var(--text-xs);
  color: #dc2626;
  text-align: center;
  line-height: 1.5;
}

.mv-render-message a {
  color: #dc2626;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.mv-progress {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}

.mv-progress-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: center;
}

.mv-progress-track {
  height: 10px;
  overflow: hidden;
  border-radius: var(--radius-pill);
  background: rgba(17, 17, 17, 0.08);
}

.mv-progress-fill {
  width: 0%;
  height: 100%;
  border-radius: inherit;
  background: var(--ink);
  transition: width 120ms linear;
}

.mv-button-cancel {
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  padding: 5px 14px;
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-3);
  cursor: pointer;
  font-family: inherit;
}
.mv-button-cancel:hover { background: #fef2f2; border-color: #fca5a5; color: #dc2626; }

html.dark .mv-button.is-loading,
html.dark .mv-button.is-rendering,
html.dark .mv-button:disabled {
  background: #f4f4f0;
  color: #111111;
  border-color: #f4f4f0;
}

html.dark .mv-button.is-loading .mv-button-spinner,
html.dark .mv-button.is-rendering .mv-button-spinner {
  border-color: rgba(17, 17, 17, 0.18);
  border-top-color: #111111;
}

.mv-button-ghost {
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  padding: 10px 0;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink-3);
  cursor: pointer;
  font-family: inherit;
  width: 100%;
}
.mv-button-ghost:hover { background: var(--surface); color: var(--ink); }

.mv-render-preset-panel {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.mv-render-result-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Small visual gap from the Save-as-preset action shown above. */
  margin-top: 8px;
}
.mv-render-result-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.mv-render-result-row .mv-button {
  min-width: 0;
  justify-content: center;
}

/* Brand-kit apply/save buttons. Restyled from the old purple (#6d28d9) to the
   neutral ink system so they match the rest of the Export panel (Render CTA,
   corner picker, dropdowns are all ink/black — purple appeared nowhere else).
   Token-based, so dark mode adapts via the same overrides as the rest of the
   sidebar. Reads as a secondary/ghost action beneath the solid black Render. */
.mv-preset-inline-btn {
  width: 100%;
  min-height: 40px;
  padding: 9px 0;
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--mv-control-radius);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  font-family: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}
.mv-preset-inline-btn:hover { background: var(--paper); border-color: var(--ink-3); }
.mv-preset-inline-btn:disabled { opacity: 0.5; cursor: default; }

/* Muted neutral credit pill (used for "N cr" chips in CTAs). No bright purple —
   light gray fill, soft border, dark text. Reads as a light chip on the dark
   Save-as-preset button and matches the top-right credit badge identity. */
/* Plain inline cost (matches the "Remove watermark +10 cr" style), not a pill.
   Muted white so it reads as secondary on the dark Save-as-preset button. */
.mv-preset-cost {
  font-size: 11px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
  margin-left: 2px;
}

html.dark .mv-button-dark .mv-preset-cost {
  color: rgba(17, 17, 17, 0.62);
}

.mv-preset-inline-link {
  display: block;
  text-align: center;
  font-size: 12px;
  color: var(--ink-3);
  text-decoration: none;
  padding: 8px 0;
}
.mv-preset-inline-link:hover { color: var(--ink); text-decoration: underline; }

.mv-preset-modified-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: #faf5ff;
  border: 1px solid #e9d5ff;
  border-radius: var(--radius-3);
  padding: 8px 12px;
  margin-top: 8px;
}
.mv-preset-modified-bar > span {
  font-size: 12px;
  color: #6d28d9;
}
.mv-preset-modified-bar .mv-preset-inline-btn {
  width: auto;
  padding: 5px 14px;
  font-size: 12px;
}

.mv-button-dark {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}

html.dark .mv-button-dark {
  color: #111;
}

/* Anchor styled as a primary button (e.g. buy-credits preset action). */
a.mv-button { text-decoration: none; }
a.mv-button:hover { color: #fff; }

.mv-button-dark:hover {
  background: #2a2a2a;
  border-color: #2a2a2a;
}

html.dark .mv-button-dark:hover {
  background: #f7f7f2;
  border-color: #f7f7f2;
  color: #111;
}

.mv-stage-panel {
  padding: 20px;
  position: sticky;
  top: 24px;
  --mv-preview-max-height-local: var(--mv-preview-max-height);
  /* Sticky preview must NOT use layout containment — contain:layout (from the
     shared .mv-panel/.mv-stage-panel rule) fights compositor sticky updates and
     can make the right preview jump/flicker while the left sidebar scrolls. */
  contain: none;
  /* No backdrop-filter here (overrides the shared .mv-panel rule): a
     backdrop-filter on this STICKY, canvas-animating panel forces the browser
     to re-sample the blurred backdrop on every recomposite (scroll, or any
     repaint triggered by editing the left tools), which visibly tears/"flips"
     the preview on some GPUs. Same reason it was dropped for the mobile fixed
     preview (see the media query below). Use a flat, opaque background instead
     — visually near-identical since the panel was already ~82% opaque. */
  background: #f7f7f4;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html.dark .mv-stage-panel {
  background: #191917;
}

.mv-stage-head {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: center;
  margin-bottom: 16px;
}

.mv-stage-previews {
  display: flex;
  justify-content: center;
  align-items: center;
  min-width: 0;
  overflow: hidden;
}

.mv-stage-shell {
  border-radius: var(--mv-control-radius-lg);
  overflow: hidden;
  background: #080808;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
  width: min(100%, calc(var(--mv-preview-max-height-local) * 16 / 9));
  max-height: var(--mv-preview-max-height-local);
  /* No permanent will-change:transform — a sticky compositor layer here
     flickered/jumped while scrolling the left controls on some GPUs. */
  margin: 0 auto;
}

.mv-stage-previews[data-aspect="portrait"] {
  display: flex;
  justify-content: center;
}

.mv-stage-previews[data-aspect="portrait"] .mv-stage-shell {
  width: min(100%, calc(var(--mv-preview-max-height-local) * 9 / 16));
  max-height: var(--mv-preview-max-height-local);
  aspect-ratio: 9 / 16;
  margin: 0 auto;
}

.mv-stage-previews[data-aspect="square"] {
  display: flex;
  justify-content: center;
}

.mv-stage-previews[data-aspect="square"] .mv-stage-shell {
  width: min(100%, var(--mv-preview-max-height-local));
  max-height: var(--mv-preview-max-height-local);
  aspect-ratio: 1 / 1;
  margin: 0 auto;
}

#visualizer-canvas {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
}

.mv-stage-previews[data-aspect="portrait"] #visualizer-canvas {
  aspect-ratio: 9 / 16;
}

.mv-stage-previews[data-aspect="square"] #visualizer-canvas {
  aspect-ratio: 1 / 1;
}

.mv-stage-footer {
  display: none;
}

/* ── LRC timeline editor (under the preview) ───────────────── */
.mv-lyric-timeline {
  margin-top: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-3, 14px);
  background: rgba(255, 255, 255, 0.7);
  padding: 12px;
}

html.dark .mv-lyric-timeline {
  background: rgba(24, 24, 22, 0.94);
  border-color: #34342f;
}

.mv-lyric-timeline-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}

.mv-lyric-timeline-title {
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
}

.mv-lyric-timeline-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* Thin divider between icon groups in the timeline header. */
.mv-lyric-tl-sep {
  width: 1px;
  align-self: stretch;
  margin: 2px 2px;
  background: var(--line);
}

.mv-lyric-tl-btn {
  font-size: var(--text-xs);
  padding: 6px 12px;
  border-radius: var(--radius-2);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}

html.dark .mv-lyric-tl-btn,
html.dark .mv-lyric-icon-btn {
  background: #20201d;
  border-color: #44443e;
  color: var(--ink-2);
}

html.dark .mv-lyric-tl-btn:hover,
html.dark .mv-lyric-icon-btn:hover {
  background: #262622;
  border-color: var(--ink-3);
  color: var(--ink);
}

.mv-lyric-tl-btn:hover {
  border-color: var(--ink-3);
  color: var(--ink);
}
.mv-lyric-tl-btn.is-primary {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}
.mv-lyric-tl-btn.is-primary:hover {
  opacity: 0.9;
  color: #fff;
}

html.dark .mv-lyric-tl-btn.is-primary {
  background: #f7f7f2;
  border-color: #f7f7f2;
  color: #111;
}

html.dark .mv-lyric-tl-btn.is-primary:hover {
  color: #111;
}

.mv-lyric-timeline-scroll {
  overflow-x: auto;
  overflow-y: hidden;
  border-radius: var(--radius-2);
  background: rgba(0, 0, 0, 0.03);
}

html.dark .mv-lyric-timeline-scroll {
  background: #10100f;
}

.mv-lyric-timeline-track {
  position: relative;
  height: 56px;
  min-width: 100%;
  cursor: text; /* empty areas click-to-seek the playhead */
}

.mv-lyric-block {
  position: absolute;
  top: 8px;
  height: 40px;
  box-sizing: border-box;
  border-radius: var(--radius-2);
  border: 1px solid rgba(59, 130, 246, 0.45);
  background: rgba(59, 130, 246, 0.14);
  color: var(--ink);
  font-size: 12px;
  line-height: 38px;
  padding: 0 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: grab;
  user-select: none;
  touch-action: none;
  transition: background 0.1s, border-color 0.1s, box-shadow 0.1s;
}
.mv-lyric-block:hover {
  background: rgba(59, 130, 246, 0.2);
}
.mv-lyric-block.is-active {
  background: rgba(59, 130, 246, 0.28);
  border-color: rgba(59, 130, 246, 0.85);
}
.mv-lyric-block.is-selected {
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.55);
  z-index: 3;
}
.mv-lyric-block.is-dragging {
  cursor: grabbing;
  z-index: 4;
}

/* Resize handles at the left/right edges. */
.mv-lyric-handle {
  position: absolute;
  top: 0;
  width: 9px;
  height: 100%;
  cursor: ew-resize;
}
.mv-lyric-handle-left { left: 0; }
.mv-lyric-handle-right { right: 0; }

.mv-lyric-playhead {
  position: absolute;
  top: 0;
  left: 0;
  width: 2px;
  height: 100%;
  background: #ef4444;
  transform: translateX(-1px);
  pointer-events: auto;
  cursor: ew-resize;
  z-index: 5;
}
/* Wider invisible grab zone so the thin playhead is easy to drag. */
.mv-lyric-playhead::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -5px;
  right: -5px;
}

.mv-lyric-line-editor {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  margin-top: 10px;
  flex-wrap: wrap;
}
.mv-lyric-edit-text {
  flex: 1 1 200px;
  min-width: 0;
  height: 40px;
  padding: 0 10px;
  font-size: var(--text-sm);
  line-height: 40px;
}
.mv-lyric-edit-num {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 11px;
  color: var(--ink-3);
}
.mv-lyric-edit-num span {
  line-height: 14px;
}
.mv-lyric-edit-num input {
  width: 84px;
  height: 40px;
  padding: 0 8px;
  font-size: var(--text-xs);
  line-height: 40px;
}

.mv-lyric-line-editor .mv-lyric-tl-btn,
.mv-lyric-line-editor .mv-lyric-icon-btn {
  height: 40px;
  min-height: 40px;
}

.mv-lyric-line-editor .mv-lyric-tl-btn {
  padding: 0 14px;
}

.mv-lyric-line-editor .mv-lyric-icon-btn {
  width: 40px;
  flex: 0 0 40px;
}

html.dark .mv-lyric-edit-text,
html.dark .mv-lyric-edit-num input {
  background: #10100f;
  border-color: #44443e;
  color: var(--ink);
}

/* ── Preview playback controls ─────────────────────────────── */
.mv-preview-controls {
  display: flex;
  align-items: center;
  gap: 6px;
}

.mv-preview-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-2);
  border: 1px solid transparent;
  color: var(--ink-3);
  background: transparent;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
  cursor: pointer;
  flex-shrink: 0;
}

.mv-preview-btn:hover {
  background: rgba(0, 0, 0, 0.05);
  color: var(--ink);
}

.mv-preview-btn.is-active {
  color: var(--mv-accent);
  background: rgba(59, 130, 246, 0.08);
  border-color: rgba(59, 130, 246, 0.2);
}

.mv-preview-btn:disabled {
  opacity: 0.35;
  cursor: default;
  pointer-events: none;
}

/* Let the controls (and the scrubber inside) grow across the preview head. */
.mv-preview-controls {
  flex: 1 1 auto;
  min-width: 0;
  justify-content: flex-end;
}

.mv-preview-scrub {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
  margin: 0 4px;
  height: 34px;
}

.mv-preview-time {
  font-size: var(--text-xs);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  line-height: 34px;
}

.mv-preview-seek {
  --fill: 0%;
  flex: 1 1 auto;
  min-width: 60px;
  -webkit-appearance: none;
  appearance: none;
  height: 34px;
  background: transparent;
  cursor: pointer;
  padding: 0;
  border: none;
  box-shadow: none;
}
.mv-preview-seek::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: var(--radius-pill);
  background: linear-gradient(to right, var(--mv-accent) var(--fill), var(--line) var(--fill));
}
.mv-preview-seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--mv-accent);
  border: none;
  margin-top: -4.5px;
  box-shadow: 0 1px 4px rgba(59, 130, 246, 0.45);
}
.mv-preview-seek::-moz-range-track {
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--line);
}
.mv-preview-seek::-moz-range-progress {
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--mv-accent);
}
.mv-preview-seek::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border: none;
  border-radius: 50%;
  background: var(--mv-accent);
}
.mv-preview-seek:disabled {
  opacity: 0.4;
}

/* Track-change markers on the scrubber (mix only). The wrap positions the tick
   overlay exactly over the seek track; ticks are contrast notches at each
   track boundary. */
.mv-preview-seek-wrap {
  position: relative;
  flex: 1 1 auto;
  min-width: 60px;
  display: flex;
  align-items: center;
}
.mv-preview-seek-wrap .mv-preview-seek {
  flex: 1 1 auto;
  min-width: 0;
}
.mv-preview-marks {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(50% + 6px);
  height: 0;
  pointer-events: none;
}
.mv-preview-marks span {
  position: absolute;
  top: 0;
  margin-left: -1px;
  width: 2px;
  height: 4px;
  border-radius: 1px;
  background: var(--ink-4);
}

/* Fullscreen preview: letterbox the canvas to fill the screen. */
.mv-stage-shell:fullscreen {
  width: 100vw;
  height: 100vh;
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
}
.mv-stage-shell:fullscreen #visualizer-canvas {
  width: 100vw;
  height: 100vh;
  aspect-ratio: auto;
  object-fit: contain;
}

.mv-footer {
  width: min(1200px, 100%);
  margin: 24px auto 0;
  padding-bottom: 12px;
}

.mv-footer-inner {
  border-top: 1px solid var(--line);
  padding-top: 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
}

.mv-footer-links {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 24px;
}

.mv-footer-links a {
  color: var(--ink-2);
  text-decoration: none !important;
  border-bottom: 0 !important;
  font-size: 13px;
  font-weight: 500;
}

.mv-footer-links a:hover {
  color: var(--ink);
}

.mv-footer-powered {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ink-3);
  font-size: 12px;
  font-weight: 500;
  text-decoration: none !important;
  border-bottom: 0 !important;
  white-space: nowrap;
}

.mv-footer-powered:hover {
  color: var(--ink-2);
}

.mv-footer-powered-logo {
  position: relative;
  display: inline-block;
  width: 112px;
  height: 24px;
  flex: 0 0 auto;
}

.mv-footer-logo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: #111;
}

html.dark .mv-footer-logo {
  color: #fff;
}

.mv-footer-left {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.mv-footer-left p {
  margin: 0;
}

.mv-footer-sponsor {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--ink);
}

.mv-footer-sponsor a,
.mv-footer-coffee {
  color: inherit;
  text-decoration: none;
  border-bottom: 0;
}

.mv-footer-processing {
  font-size: 11px;
  color: var(--ink-3);
}

.mv-footer-coffee {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  font-size: 12px;
  color: var(--ink-2);
}

.mv-footer-coffee:hover {
  color: var(--ink);
}

.mv-footer-coffee svg {
  width: 13px;
  height: 13px;
}

.mv-footer-right {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 4px;
  color: var(--ink-2);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  white-space: nowrap;
}

.mv-footer-sep {
  color: var(--ink-4);
}

@media (max-width: 1040px) {
  .mv-app {
    padding: 20px;
  }

  .mv-layout {
    grid-template-columns: 1fr;
  }

  .mv-sidebar {
    position: static;
  }

  .mv-stage-panel {
    position: static;
  }
}

@media (max-width: 720px) {
  /* One fixed preview budget on phones for EVERY aspect: never more than 40%
     of the viewport. Portrait (9:16) used to take 52svh — capped here so the
     preview stays a small, consistent band and the controls get the screen. */
  .mv-app,
  .mv-app[data-aspect="portrait"],
  .mv-app[data-aspect="square"] {
    --mv-preview-max-height: min(40svh, 340px);
  }

  /* While a text field is focused (keyboard up), hide the preview so the
     field + keyboard own the screen (initMobilePreviewKeyboardHide). */
  .mv-app.mv-editing .mv-stage-panel {
    display: none;
  }

  html,
  body {
    width: 100%;
    max-width: 100%;
  }

  .mv-header,
  .mv-footer-inner {
    flex-direction: column;
    align-items: flex-start;
  }

  .mv-app {
    padding: 14px;
  }

  .mv-stage-panel {
    padding: 14px;
  }

  .mv-header,
  .mv-layout,
  .mv-stage-panel,
  .mv-sidebar,
  .mv-sidebar-card,
  .mv-stage-previews,
  .mv-stage-shell {
    width: 100%;
    max-width: 100%;
    min-width: 0;
  }

  .mv-header {
    gap: 14px;
  }

  .mv-layout {
    display: flex;
    flex-direction: column;
    gap: 14px;
  }

  .mv-header h1 {
    font-size: 22px;
    overflow-wrap: anywhere;
  }

  .mv-header-tools {
    width: 100%;
    justify-content: space-between;
    flex-wrap: nowrap;
  }

  .mv-sidebar-card .mv-panel-head {
    padding: 13px 14px;
  }

  .mv-sidebar-card .mv-panel-body {
    padding: 0 14px 14px;
  }

  .mv-stage-head {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    margin-bottom: 12px;
  }

  .mv-preview-controls {
    width: 100%;
    min-width: 0;
    flex-wrap: wrap;
  }

  .mv-preview-scrub {
    order: 3;
    flex-basis: 100%;
  }

  .mv-preview-aspect {
    margin-left: auto;
  }

  .mv-stage-panel {
    order: -1;
    position: sticky;
    top: 10px;
    z-index: 12;
    padding: 12px;
    /* Own compositor layer for the mobile sticky preview: URL-bar
       collapse/expand re-rasterizes non-promoted sticky content on every
       viewport tick, which reads as flicker while scrolling. (Desktop stays
       unpromoted — the will-change regression noted on .mv-stage-shell was
       desktop-sticky/GPU specific.) */
    transform: translateZ(0);
  }

  .mv-stage-shell {
    max-width: 100%;
  }

  .mv-stage-previews[data-aspect="portrait"] .mv-stage-shell {
    width: min(100%, calc(var(--mv-preview-max-height-local) * 9 / 16));
  }

  .mv-stage-previews[data-aspect="square"] .mv-stage-shell {
    width: min(100%, var(--mv-preview-max-height-local));
  }

  .mv-track-tools-row,
  .mv-field-row {
    grid-template-columns: 1fr;
  }

  .mv-footer-right {
    white-space: normal;
    flex-wrap: wrap;
    padding-top: 0;
  }

  .mv-preset-grid {
    grid-template-columns: 1fr 1fr;
  }
  /* Render button stays full-width on mobile (same as desktop), with the cost /
     message text under it — not a half-width button in a 2-column grid. */
  .mv-actions {
    grid-template-columns: minmax(0, 1fr);
  }

  .mv-aspect-options {
    grid-template-columns: 1fr;
  }
}

/* ══════════════════════════════════════════════════════════
   MINIMAL UI OVERRIDES
   ══════════════════════════════════════════════════════════ */

/* ── All text inside the sidebar card → calm gray ────────── */
.mv-sidebar-card {
  color: var(--ink-3);
}

/* ── Form labels — normal case, calm gray, small weight ─── */
/* Use > so we only target direct label spans, not nested control text */
.mv-sidebar-card .mv-field > span:first-child,
.mv-sidebar-card .mv-field-label,
.mv-sidebar-card .mv-slider-top > span,
.mv-sidebar-card .mv-branding .mv-check-row > span:not(.mv-check-cost),
.mv-sidebar-card .mv-inline-label {
  font-size: var(--text-xs);
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink-3);
  font-weight: 500;
  line-height: 1.2;
}

/* ── Compact sizing for all inputs & selects in the card (not upload/range) */
.mv-sidebar-card input:not([type="range"]):not([type="color"]):not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="file"]),
.mv-sidebar-card select {
  padding: 6px 8px;
  min-height: 40px;
  color: var(--ink-2);
  font-weight: 500;
}


.mv-sidebar-card input::placeholder {
  color: var(--ink-4);
}

/* ── Slim borderless range slider ────────────────────────── */
.mv-panel-body input[type="range"] {
  --fill: 50%;
  -webkit-appearance: none;
  appearance: none;
  /* 20px height gives the thumb room to be vertically centered */
  height: 20px;
  background: transparent;
  cursor: pointer;
  padding: 0;
  border: none;
  box-shadow: none;
}

/* Webkit: gradient lives on the track, not the input background */
.mv-panel-body input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: var(--radius-pill);
  border: none;
  background: linear-gradient(
    to right,
    var(--mv-accent) var(--fill),
    var(--line) var(--fill)
  );
}

.mv-panel-body input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--mv-accent);
  border: none;
  box-shadow: 0 1px 5px rgba(59, 130, 246, 0.45);
  cursor: pointer;
  margin-top: -5px; /* vertically center thumb over 4px track */
  transition: box-shadow var(--dur-1) var(--ease-out);
}

.mv-panel-body input[type="range"]::-webkit-slider-thumb:hover {
  box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.18),
    0 1px 5px rgba(59, 130, 246, 0.45);
}

.mv-panel-body input[type="range"]::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--mv-accent);
  border: none;
  box-shadow: 0 1px 5px rgba(59, 130, 246, 0.45);
  cursor: pointer;
}

.mv-panel-body input[type="range"]::-moz-range-track {
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--line);
  border: none;
}

.mv-panel-body input[type="range"]::-moz-range-progress {
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--mv-accent);
}

/* ── Hide always-visible value pills (tooltip replaces them) */
.mv-slider-val {
  display: none !important;
}

/* icon + label always left-aligned */
.mv-slider-top {
  align-items: center;
}

/* ── Floating slider tooltip ─────────────────────────────── */
.mv-slider-tooltip {
  position: fixed;
  z-index: 9999;
  padding: 3px 8px;
  border-radius: var(--radius-1);
  background: rgba(17, 17, 17, 0.86);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.02em;
  pointer-events: none;
  white-space: nowrap;
  transform: translateX(-50%);
}

/* ── Zero marker on position sliders ─────────────────────── */
.mv-slider-wrap {
  position: relative;
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding-bottom: 6px;
}

/* The wrapped position slider must span the exact same full width as
   unwrapped sliders in the same panel. */
.mv-slider-wrap input[type="range"] {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin: 0;
}

.mv-slider-zero-mark {
  position: absolute;
  left: calc(50% - 1px);
  bottom: 0;
  width: 2px;
  height: 4px;
  background: var(--ink-4);
  border-radius: 1px;
  pointer-events: none;
}

/* ── Multi-color (gradient) controls ─────────────────────────── */
.mv-color-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}

.mv-color-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.mv-color-row-label {
  flex: 1;
  font-size: var(--text-sm);
  color: var(--ink-2);
}

/* Small square +/- buttons for adding/removing colors. */
.mv-color-add,
.mv-color-remove {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-2);
  background: var(--surface);
  color: var(--ink-2);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}

.mv-color-add:hover:not(:disabled),
.mv-color-remove:hover:not(:disabled) {
  border-color: var(--ink-3);
  color: var(--ink);
  background: #fbfbf8;
}
/* Dark mode: the light hover fill above turned the icon (--ink, light) into
   white-on-white. Use a dark hover fill so the +/− stay visible. */
html.dark .mv-color-add:hover:not(:disabled),
html.dark .mv-color-remove:hover:not(:disabled) {
  background: #26261f;
}
/* The +/− glyphs sat slightly high; a 1px optical nudge centers them in the box. */
.mv-color-add,
.mv-color-remove {
  line-height: 24px;
  padding: 0;
}

/* Free in-browser export hint under Quality — removed per product: no extra
   helper text under the quality picker. */
#free-export-status { display: none !important; }

/* "Current image / Current video" rows removed entirely — the Loop scene chip
   is the single place the background file is shown, so these are redundant. */
#image-file-info,
#video-file-info { display: none !important; }

/* Unified track list is the only audio input now: the Single/Mix toggle, the
   separate "Upload music" button and the classic current-file row are gone from
   the UI (kept in the DOM so loadAudio/clearAudio's .hidden writes stay safe). */
#audio-mode-group,
#audio-mode-hint,
#audio-upload-label,
#audio-file-info { display: none !important; }

.mv-color-add:focus-visible,
.mv-color-remove:focus-visible {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(17, 17, 17, 0.12);
}

/* Lighter disabled state (e.g. + at 5 colors, − at 1 color). */
.mv-color-add:disabled,
.mv-color-remove:disabled {
  opacity: 0.4;
  cursor: default;
}

/* ── react-colorful picker ───────────────────────────────── */
.mv-cpicker {
  position: relative;
  width: 100%;
}

.mv-cpicker-swatch {
  display: block;
  width: 100%;
  min-height: 40px;
  border-radius: var(--radius-2);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}

.mv-cpicker-swatch:hover {
  border-color: var(--ink-3);
  box-shadow: 0 0 0 2px rgba(17, 17, 17, 0.06);
}

.mv-cpicker-popover {
  /* position:fixed + coordinates are set inline by color-picker.js */
  z-index: 9999;
  width: 200px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-3);
  box-shadow: 0 8px 32px rgba(17, 17, 17, 0.12),
    0 0 0 1px rgba(17, 17, 17, 0.03);
  padding: 12px;
}

html.dark .mv-audio-file-row {
  background: var(--surface);
  border-color: var(--line);
}

html.dark .mv-audio-file-name {
  color: var(--ink);
}

html.dark .mv-audio-clear:hover {
  background: rgba(255, 255, 255, 0.08);
}

html.dark .mv-slider:has(.mv-toggle-pill) .mv-slider-top span {
  color: var(--ink);
}

html.dark .mv-slider-val,
html.dark .mv-range-row output,
html.dark .mv-cpicker-hex-row {
  background: var(--surface);
  color: var(--ink-2);
}

/* Make the picker fill its container */
.mv-cpicker-popover .react-colorful {
  width: 100%;
  height: 140px;
}

.mv-cpicker-popover .react-colorful__saturation {
  border-radius: var(--radius-2) var(--radius-2) 0 0;
}

.mv-cpicker-popover .react-colorful__hue {
  height: 12px;
  border-radius: var(--radius-pill);
  margin-top: 10px;
}

.mv-cpicker-popover .react-colorful__pointer {
  width: 18px;
  height: 18px;
  border-width: 2px;
}

/* Hex input row below the picker */
.mv-cpicker-hex-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  background: #f5f5f3;
  border: 1px solid var(--line);
  border-radius: var(--radius-2);
  padding: 6px 10px;
}

.mv-cpicker-hash {
  color: var(--ink-3);
  font-size: var(--text-sm);
  font-weight: 500;
  flex-shrink: 0;
  user-select: none;
}

.mv-cpicker-hex {
  flex: 1;
  background: transparent !important;
  border: none !important;
  padding: 0 !important;
  margin: 0 !important;
  min-height: unset !important;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink) !important;
  font-family: var(--font-mono);
  letter-spacing: 0.08em;
  min-width: 0;
  text-transform: uppercase;
}

.mv-cpicker-hex:focus {
  outline: none;
  box-shadow: none !important;
  border: none !important;
}

.mv-cpicker-mount {
  display: block;
}

.mv-field-color-compact {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
}

.mv-field-color-compact .mv-cpicker-mount,
.mv-field-color-compact .mv-cpicker {
  width: auto;
}

.mv-field-color-compact .mv-cpicker-swatch {
  width: 44px;
  min-height: 24px;
  border-radius: var(--radius-pill);
}

/* Compact circular swatch for spectrum slider color controls */
.mv-slider-cpicker.mv-cpicker-mount {
  display: flex;
  align-items: center;
}
/* Toggle / color-picker rows put their control inside .mv-slider-top, which
   otherwise lands in the narrow 30% grid column. Make those rows full-width
   flex so the control right-aligns to the panel edge like a normal row. */
.mv-slider:has(.mv-toggle-pill),
.mv-slider:has(.mv-slider-cpicker) {
  display: flex;
  align-items: center;
}
.mv-slider:has(.mv-toggle-pill) .mv-slider-top,
.mv-slider:has(.mv-slider-cpicker) .mv-slider-top {
  flex: 1 1 auto;
  min-width: 0;
}
.mv-slider-top .mv-toggle-pill,
.mv-slider-top .mv-slider-cpicker.mv-cpicker-mount {
  margin-left: auto;
}

.mv-slider:has(.mv-toggle-pill) {
  min-height: 34px;
  cursor: pointer;
}

.mv-slider:has(.mv-toggle-pill) .mv-slider-top {
  padding: 4px 0;
}

.mv-slider-cpicker .mv-cpicker {
  width: auto;
}
.mv-slider-cpicker .mv-cpicker-swatch {
  width: 26px;
  min-height: 26px;
  border-radius: 50%;
}

/* ── Text alignment button group ─────────────────────────── */
.mv-align-group {
  display: flex;
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  overflow: hidden;
  min-height: 40px;
  width: 100%;
}

.mv-align-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px 7px;
  min-height: 40px;
  background: var(--surface);
  border: none;
  cursor: pointer;
  color: var(--ink-3);
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}

.mv-align-btn + .mv-align-btn {
  border-left: 1px solid var(--line);
}

.mv-align-btn:hover {
  background: var(--surface-2, #f5f5f3);
  color: var(--ink);
}

/* Dark mode: the light hover fill above made the (light) ink text vanish.
   Use a subtle light overlay on the dark surface so hover text stays readable. */
html.dark .mv-align-btn:hover {
  background: rgba(255, 255, 255, 0.07);
  color: var(--ink);
}

.mv-align-btn.is-active {
  background: var(--ink);
  color: #fff;
}

html.dark .mv-align-btn.is-active {
  color: #111;
}

#spectrum-dynamic-controls,
#particle-dynamic-controls,
#lyric-dynamic-controls,
#background-dynamic-controls {
  display: grid;
  gap: 8px;
}

#spectrum-dynamic-controls:not(:empty),
#particle-dynamic-controls:not(:empty),
#lyric-dynamic-controls:not(:empty),
#background-dynamic-controls:not(:empty) {
  margin-top: 10px;
}

#spectrum-dynamic-controls > *,
#particle-dynamic-controls > *,
#lyric-dynamic-controls > *,
#background-dynamic-controls > * {
  margin-top: 0;
}

/* ── Spectrum picker trigger */
.mv-spectrum-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 8px;
  min-height: 40px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out);
  text-align: left;
}

.mv-spectrum-trigger:hover { border-color: var(--ink-3); }

.mv-spectrum-trigger-dot {
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,0.08);
}

/* ── Lyrics source (upload / generate) */
.mv-lyric-source {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  margin-bottom: 8px;
}

.mv-lyric-source-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 40px;
  padding: 6px 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}

.mv-lyric-source-btn:hover { border-color: var(--ink-3); }
.mv-lyric-source-btn svg { flex-shrink: 0; opacity: 0.7; }

.mv-lyric-source-btn.is-generate {
  gap: 8px;
}

/* Generate button loading state */
.mv-lyric-spinner {
  display: none;
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  opacity: 0.8;
  animation: mv-lyric-spin 0.7s linear infinite;
}
@keyframes mv-lyric-spin { to { transform: rotate(360deg); } }
.mv-lyric-source-btn.is-loading { cursor: progress; }
.mv-lyric-source-btn.is-loading .mv-lyric-spinner { display: inline-block; }
.mv-lyric-source-btn.is-loading .mv-lyric-gen-icon,
.mv-lyric-source-btn.is-loading .mv-lyric-cost { display: none; }

.mv-lyric-cost {
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-3);
}

/* ── Upload .lrc row ──────────────────────────────────────── */
.mv-lyric-upload-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.mv-lyric-source-btn.is-upload {
  flex: 1;
  margin: 0;
}

/* Manual-entry / sample row under the upload button. */
.mv-lyric-manual-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 8px;
}
.mv-lyric-textlink {
  background: none;
  border: none;
  padding: 0;
  font-size: var(--text-xs);
  color: var(--ink-3);
  cursor: pointer;
  text-decoration: none;
}
.mv-lyric-textlink:hover { color: var(--ink); text-decoration: underline; }

/* "Add lyrics manually" CTA shown under the preview when no lyrics exist. */
.mv-lyric-manual-cta {
  margin-top: 16px;
  display: flex;
  justify-content: center;
}
.mv-lyric-manual-cta-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  padding: 9px 16px;
  border-radius: var(--mv-control-radius);
  border: 1px dashed var(--line);
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.mv-lyric-manual-cta-btn:hover {
  border-color: var(--ink-3);
  color: var(--ink);
}
.mv-lyric-manual-cta-btn svg { opacity: 0.75; }

.mv-lyric-upload-help {
  position: relative;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  color: var(--ink-3);
  cursor: help;
}
.mv-lyric-upload-help svg { opacity: 0.8; }

.mv-lyric-upload-tip {
  position: absolute;
  bottom: calc(100% + 8px);
  right: 0;
  width: 220px;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink-2);
  opacity: 0;
  visibility: hidden;
  transform: translateY(4px);
  transition: opacity var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out), visibility var(--dur-1);
  z-index: 20;
}
.mv-lyric-upload-tip code {
  font-size: 11px;
  background: var(--ink-7, rgba(255, 255, 255, 0.06));
  padding: 1px 4px;
  border-radius: var(--radius-1);
}
.mv-lyric-upload-tip a {
  display: inline-block;
  margin-top: 6px;
  color: var(--accent, #6ea8fe);
  text-decoration: underline;
  cursor: pointer;
}
.mv-lyric-upload-help:hover .mv-lyric-upload-tip,
.mv-lyric-upload-help:focus-within .mv-lyric-upload-tip,
.mv-lyric-upload-help:focus .mv-lyric-upload-tip {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}


.mv-lyric-status {
  margin: 0 0 10px;
  font-size: var(--text-sm);
  color: var(--ink-3);
  line-height: 1.4;
}

/* Panel-head title with inline info tooltip */
.mv-panel-head > .mv-panel-head-title {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
}
.mv-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-3);
  cursor: help;
  opacity: 0.7;
  transition: opacity var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.mv-info:hover, .mv-info:focus-visible { opacity: 1; color: var(--ink); outline: none; }

/* Post-generate result row: filename + actions */
.mv-lyric-result {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 40px;
  padding: 6px 10px;
  margin-bottom: 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
}
.mv-lyric-result-file {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink);
}
.mv-lyric-result-file svg { flex-shrink: 0; opacity: 0.7; }
.mv-lyric-result-file > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mv-lyric-result-actions { display: flex; gap: 4px; flex-shrink: 0; }
.mv-lyric-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius-1);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.mv-lyric-icon-btn:hover { border-color: var(--ink-3); color: var(--ink); }
.mv-lyric-icon-btn.is-danger:hover { border-color: var(--danger); color: var(--danger); }

html.dark .mv-lyric-icon-btn {
  background: #20201d;
  border-color: #44443e;
  color: var(--ink-2);
}

html.dark .mv-lyric-icon-btn:hover {
  background: #262622;
  border-color: var(--ink-3);
  color: var(--ink);
}

.mv-lyric-fontsel {
  width: 100%;
  height: 34px;
  padding: 0 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius-sm);
  color: var(--ink);
  font-size: var(--text-sm);
  cursor: pointer;
}
.mv-lyric-fontsel:focus { outline: none; border-color: var(--ink-3); }

/* ── Spectrum picker modal */
.mv-spectrum-modal {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: flex-end;
}

@media (min-width: 480px) {
  .mv-spectrum-modal { align-items: center; justify-content: center; }
}

.mv-spectrum-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(17,17,17,0.5);
}

.mv-spectrum-modal-box {
  position: relative;
  width: 100%;
  max-width: 440px;
  background: var(--surface);
  border-radius: var(--radius-4) var(--radius-4) 0 0;
  padding: 20px 20px 28px;
  max-height: 80vh;
  overflow-y: auto;
}

@media (min-width: 480px) {
  .mv-spectrum-modal-box {
    border-radius: var(--radius-4);
    max-height: 70vh;
  }
}

.mv-spectrum-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}

.mv-spectrum-modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-2);
  color: var(--ink-3);
  transition: background var(--dur-1) var(--ease-out);
}

.mv-spectrum-modal-close:hover { background: var(--paper); color: var(--ink); }

.mv-spectrum-modal-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  /* 2 columns × ~3 rows, then scroll inside the modal */
  max-height: 340px;
  overflow-y: auto;
}

.mv-spectrum-card {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 0 0 8px;
  border: 1.5px solid var(--line);
  border-radius: var(--mv-control-radius-lg);
  background: var(--surface);
  cursor: pointer;
  overflow: hidden;
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
  text-align: left;
}

.mv-spectrum-card:hover {
  border-color: var(--ink-3);
  box-shadow: var(--shadow-1);
}

.mv-spectrum-card.is-selected {
  border-color: var(--mv-accent);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.25);
}

.mv-spectrum-card-canvas {
  width: 100%;
  height: 64px;
  display: block;
  border-radius: var(--mv-control-radius-lg) var(--mv-control-radius-lg) 0 0;
  background: #0f172a;
}

.mv-spectrum-card-name {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--ink);
  line-height: 1.2;
  padding: 6px 8px 0;
}

.mv-spectrum-card-credit {
  font-size: 10px;
  font-weight: 400;
  color: var(--ink-3);
  padding: 2px 8px 0;
  line-height: 1.2;
}

/* ── Particle picker modal grid */
.mv-particle-modal-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  /* 2 columns × ~3 rows, then scroll inside the modal */
  max-height: 340px;
  overflow-y: auto;
}

/* ── Particle card — same shell as spectrum card */
.mv-particle-card {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 0 0 8px;
  border: 1.5px solid var(--line);
  border-radius: var(--mv-control-radius-lg);
  background: var(--surface);
  cursor: pointer;
  overflow: hidden;
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
  text-align: left;
}

.mv-particle-card:hover {
  border-color: var(--ink-3);
  box-shadow: var(--shadow-1);
}

.mv-particle-card.is-selected {
  border-color: var(--mv-accent);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.25);
}

/* Gradient preview area inside particle card */
.mv-particle-card-preview {
  width: 100%;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--mv-control-radius-lg) var(--mv-control-radius-lg) 0 0;
}

/* Color dot in preview */
.mv-particle-card-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,0.25);
  display: block;
}

/* ── Toggle pill for audio-reactive and other boolean controls ─────────── */
.mv-toggle-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  border: 1.5px solid var(--border, #e2e8f0);
  background: transparent;
  color: var(--ink-2, #64748b);
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  white-space: nowrap;
  line-height: 1.6;
  pointer-events: none;
}
.mv-toggle-pill.is-on {
  background: var(--ink, #0f172a);
  color: #fff;
  border-color: var(--ink, #0f172a);
}
html.dark .mv-toggle-pill.is-on {
  background: #f4f4f0;
  color: #111111;
  border-color: #f4f4f0;
}
.mv-slider-top .mv-toggle-pill {
  margin-left: auto;
}

/* ── Preset modal ───────────────────────────────────────────────────────── */
.mv-preset-modal-box {
  max-width: 480px;
  width: 100%;
}
.mv-preset-save-box {
  max-width: 380px;
  width: 100%;
}
.mv-preset-tabs {
  display: flex;
  gap: 4px;
  padding: 0 16px 12px;
  border-bottom: 1px solid var(--line);
}
.mv-preset-tab {
  padding: 5px 14px;
  border-radius: var(--mv-header-control-radius);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  cursor: pointer;
  border: 1.5px solid var(--line);
  background: transparent;
  color: var(--ink-2);
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  font-family: inherit;
}
.mv-preset-tab.is-active {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}

html.dark .mv-preset-tab.is-active {
  background: #f7f7f2;
  border-color: #f7f7f2;
  color: #111111;
}
.mv-preset-panel {
  padding: 16px;
  min-height: 120px;
}
.mv-preset-grid {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* Preset cards mirror the spectrum picker: animated thumbnail + footer. */
.mv-preset-modal-box .mv-preset-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  /* 2 columns × ~3 rows, then scroll inside the modal */
  max-height: 340px;
  overflow-y: auto;
}
.mv-preset-card {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 0 0 8px;
  border: 1.5px solid var(--line);
  border-radius: var(--mv-control-radius-lg);
  background: var(--surface);
  cursor: pointer;
  overflow: hidden;
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
  text-align: left;
  width: 100%;
  font-family: inherit;
}
.mv-preset-card:hover {
  border-color: var(--ink-3);
  box-shadow: var(--shadow-1);
}
.mv-preset-card.is-selected {
  border-color: var(--mv-accent);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.25);
}
.mv-preset-card-canvas {
  width: 100%;
  height: 64px;
  display: block;
  /* Match the card's radius (--mv-control-radius-lg) so the thumbnail's top
     corners follow the card instead of reading as square inside it. */
  border-radius: var(--mv-control-radius-lg) var(--mv-control-radius-lg) 0 0;
  background: #0f172a;
}
.mv-preset-card-footer {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px 0;
}
.mv-preset-card-name {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--ink);
  line-height: 1.2;
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mv-preset-card-meta {
  font-size: 10px;
  color: var(--ink-3);
  padding: 2px 8px 0;
  line-height: 1.2;
}
.mv-preset-empty {
  text-align: center;
  padding: 32px 0;
  color: var(--ink-3);
  font-size: 13px;
}

/* ── Server render progress bar ──────────────────────────────────────── */
.mv-render-progress {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}

.mv-render-progress-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}

.mv-render-progress-elapsed {
  color: var(--ink-3);
  white-space: nowrap;
}
.mv-render-progress-note {
  margin: 0;
  font-size: var(--text-xs);
  color: var(--ink-4);
  line-height: 1.35;
}

/* Reuse .mv-progress-track for the bar track (already defined). */
.mv-render-progress-fill {
  width: 0%;
  height: 100%;
  border-radius: inherit;
  background: var(--ink);
  /* Slow ease so the asymptotic creep looks intentional, not choppy. */
  transition: width 800ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* When fill reaches 100% (done state) snap it instantly. */
.mv-render-progress-fill.is-done {
  transition: width 200ms linear;
}

html.dark .mv-render-progress-fill {
  background: #f4f4f0;
}

/* App version stamp under Export — same color as the panel surface so it is
   invisible until selected with the mouse. Centered + small. Auto-adapts to
   light/dark via the --surface token. */
.mv-version {
  margin: 10px 0 2px;
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.04em;
  line-height: 1;
  color: var(--surface);
  user-select: text;
  -webkit-user-select: text;
}

/* Spectrum / Particles / Lyrics / Background modal cards: match the design-system
   card footer — a name + "Free" pill row (like the preset card), replacing the old
   stacked name + plain-text credit. These cards share one DOM shape
   (card > thumb > name > credit), so a single grid rule unifies all four. */
.mv-spectrum-card,
.mv-particle-card {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
}
.mv-spectrum-card > .mv-spectrum-card-canvas,
.mv-particle-card > .mv-particle-card-preview {
  grid-column: 1 / -1;
}
.mv-spectrum-card-name {
  grid-column: 1;
  padding: 8px 6px 8px 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mv-spectrum-card-credit {
  grid-column: 2;
  justify-self: end;
  margin: 0 10px 0 0;
  padding: 2px 7px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  background: #efefec;
  color: #4a4a48;
  border: 1px solid rgba(17, 17, 17, 0.08);
  border-radius: var(--radius-pill);
}

/* ── Platform Badge module (Track Info) ─────────────────────────────────── */
.mv-pb {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
/* No dividers inside Text & Badge (Add text + Platform Badge modules). */
.mv-track-card .mv-pb {
  padding-top: 0;
  border-top: none;
}
/* No dividers inside Cover art (Cover + Filmstrip modules). */
#cover-module,
#filmstrip-module {
  padding-top: 0;
  border-top: none;
}
.mv-pb-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.mv-pb-body {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin-top: 14px;
}
/* show/hide switch — on = accent (blue-500) */
.mv-switch {
  position: relative;
  width: 44px;
  height: 26px;
  flex: 0 0 auto;
  border-radius: var(--radius-pill);
  background: var(--line);
  border: none;
  cursor: pointer;
  transition: background var(--dur-1) var(--ease-out);
}
.mv-switch[aria-checked="true"] { background: var(--mv-accent); }
.mv-switch::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(17, 17, 17, 0.2);
  transition: transform var(--dur-1) var(--ease-out);
}
.mv-switch[aria-checked="true"]::after { transform: translateX(18px); }
/* Smallest switch — used by the Title-text + Platform-badge toggles. */
.mv-switch-sm { width: 32px; height: 18px; }
.mv-switch-sm::after { top: 2px; left: 2px; width: 14px; height: 14px; }
.mv-switch-sm[aria-checked="true"]::after { transform: translateX(14px); }
/* platform multi-select grid */
.mv-pb-platforms {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 6px;
}
.mv-pb-platform {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  padding: 2px;
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--mv-control-radius);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out);
}
.mv-pb-platform:hover { border-color: var(--ink-3); }
.mv-pb-platform.is-selected { border-color: var(--mv-accent); }
.mv-pb-platform img {
  width: 100%;
  height: 100%;
  max-width: 40px;
  max-height: 40px;
  object-fit: contain;
}
/* text segmented buttons (reuse .mv-align-group shell) */
.mv-seg-text .mv-align-btn {
  font-size: var(--text-sm);
  font-weight: 500;
}

/* ── Right-align the chevron in modal-opener selects (Audio/Spectrums/etc.) ───── */
.mv-spectrum-trigger .mv-font-chevron {
  margin-left: auto;
}

/* ── Compact form size — left controller fields, to reduce vertical scrolling ─── */
.mv-app {
  --mv-control-height: 34px;
}
.mv-app input:not([type="range"]):not([type="checkbox"]),
.mv-app select,
.mv-app .mv-select,
.mv-app .mv-spectrum-trigger,
.mv-app .mv-font-trigger,
.mv-app .mv-align-group,
.mv-app .mv-align-btn {
  min-height: var(--mv-control-height);
}
.mv-app input:not([type="range"]):not([type="checkbox"]):not([type="color"]),
.mv-app select,
.mv-app .mv-select {
  padding-top: 6px;
  padding-bottom: 6px;
}
/* Font + Align share a grid row; make both stretch so the font trigger no longer
   renders shorter than its siblings (display:grid was sizing it to content). */
.mv-track-tools-row {
  align-items: stretch;
}
.mv-track-tools-row .mv-font-dropdown,
.mv-track-tools-row .mv-font-trigger {
  height: 100%;
}

/* One tool-menu control-height standard = the Preset control (--mv-control-height,
   34px). The Title-text + Add-text module inputs/font/align drifted taller
   (36–50px) after the moves; pin every one of them back to the standard so the
   whole tool menu is flush. */
#title-text-body input:not([type="range"]):not([type="checkbox"]),
#title-text-body .mv-font-trigger,
#title-text-body .mv-font-dropdown,
.mv-extra-text-tools input:not([type="range"]):not([type="checkbox"]),
.mv-extra-text-tools .mv-font-trigger {
  min-height: var(--mv-control-height);
  height: var(--mv-control-height);
}
/* Compact everything in the tool menu: all selects + form inputs = 34px. */
.mv-app select,
.mv-app .mv-select,
.mv-app .mv-spectrum-trigger,
.mv-app input:not([type="range"]):not([type="checkbox"]):not([type="color"]) {
  height: var(--mv-control-height);
}
/* Zero gap between the Title-text sliders (Align · Color · H/V pos · Size);
   the Subtitle + Font fields above keep the normal field gap. */
#title-text-body { gap: 8px; }
#title-text-body .mv-slider + .mv-slider { margin-top: -8px; }
/* Stop marks for option sliders (badge Appearance/Style/Layout, Align) — one
   tick per option, in the H. pos zero-mark style. */
.mv-slider-stop-mark {
  position: absolute;
  bottom: 0;
  width: 2px;
  height: 4px;
  margin-left: -1px;
  background: var(--ink-4);
  border-radius: 1px;
  pointer-events: none;
}

/* Small space above the preview head (sits below the canvas after the reorder). */
.mv-stage-head {
  margin-top: 3px;
}

/* Audio (and cover/image) file-row clear button: flush to the right edge. */
.mv-audio-clear {
  margin-right: 0;
}

/* Add Text: the Font field sits alone in a 2-col field-row whose empty second
   column reserved a gap, making it ~12px narrower than the Text field above it.
   Use a single column so it spans the full width like the Text input. */
.mv-extra-text-tools .mv-field-row {
  grid-template-columns: 1fr;
}

/* Quality dropdown: per-option render cost on the far right (.mv-check-cost size). */
.mv-quality-dropdown .mv-font-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* Not-yet-available quality options (e.g. 1440p / 4K "Coming soon"). Dimmed and
   non-selectable, but NO strike-through line — the cost badge is swapped for a
   plain "Coming soon" label in the same muted colour (see app.js). */
.mv-font-option.is-disabled {
  opacity: 0.55;
  cursor: default;
}

/* Post-submit "Queued" ticket — calm confirmation instead of a forced
   progress watch. Token-based for dark mode. */
.mv-queued-ticket {
  background: var(--mv-surface, #fff);
  border: 1px solid var(--mv-line, #e5e5e0);
  border-radius: 14px;
  padding: 16px;
  margin: 10px 0;
  font-size: 13px;
}
.mv-qt-head {
  font-size: 15px;
  font-weight: 700;
  color: var(--mv-text, #111);
  margin-bottom: 8px;
}
.mv-qt-body p { margin: 4px 0; color: var(--mv-muted-strong, #4a4a48); line-height: 1.5; }
.mv-qt-dim { color: var(--mv-muted, #8a8a86); font-weight: 400; }
.mv-qt-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.mv-qt-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 40px; padding: 8px 16px; border-radius: 10px;
  font-size: 13px; font-weight: 600; cursor: pointer; text-decoration: none;
  border: 1px solid var(--mv-line, #e5e5e0);
  background: var(--mv-surface, #fff); color: var(--mv-text, #111);
  font-family: inherit;
}
.mv-qt-primary { background: var(--mv-text, #111); color: var(--mv-surface, #fff); border-color: var(--mv-text, #111); }

/* ── Background Loop (multi-background sequence; #scenes-section) ───────── */
#scenes-section {
  margin-top: 0;
}
.mv-scene-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}
.mv-scene-list:empty { margin-top: 0; }
.mv-scene-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  padding: 6px 8px;
  /* Non-grabbed chips slide to make room while a sibling is dragged. */
  transition: transform 160ms var(--ease-out);
}
/* The grabbed card lifts out (scale + shadow) and follows the pointer with no
   transition so it tracks 1:1; siblings keep the transition above. */
.mv-scene-chip.is-grabbing {
  transition: none;
  position: relative;
  z-index: 5;
  box-shadow: 0 10px 26px rgba(17, 17, 17, 0.22);
  cursor: grabbing;
}
html.dark .mv-scene-chip.is-grabbing { box-shadow: 0 12px 28px rgba(0, 0, 0, 0.5); }
.mv-scene-index {
  flex-shrink: 0;
  min-width: 14px;
  text-align: center;
  font-size: var(--text-sm);
  color: var(--ink-3);
}
/* Drag handle (replaces the index number) — grab affordance for the pointer-
   based reorder. */
.mv-scene-handle {
  flex-shrink: 0;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  border: none;
  background: none;
  border-radius: var(--radius-2);
  color: var(--ink-4);
  font-size: 15px;
  letter-spacing: 1px;
  cursor: grab;
  touch-action: none;
}
.mv-scene-handle:active { cursor: grabbing; }
.mv-scene-thumb {
  flex-shrink: 0;
  width: 48px;
  height: 27px;
  object-fit: cover;
  border-radius: 5px;
  background: var(--paper-2);
  pointer-events: none;
}
.mv-scene-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.mv-scene-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-sm);
  color: var(--ink);
}
.mv-scene-start {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-xs);
  line-height: 1.3;
  color: var(--ink-4);
}
.mv-scene-start.is-cut { color: var(--danger); }
.mv-scene-repeat {
  /* Compact − ×N + repeat stepper (was a 9-option <select> — too wide for
     the chip on small viewports). Buttons reuse .mv-scene-btn styling. */
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  height: 28px;
  border: 1px solid var(--line);
  border-radius: var(--radius-2);
  background: var(--paper);
  overflow: hidden;
}
.mv-scene-btn.mv-scene-repeat-btn {
  width: 20px;
  height: 26px;
  border-radius: 0;
  font-size: 13px;
}
.mv-scene-repeat-val {
  min-width: 24px;
  text-align: center;
  font-size: var(--text-sm);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.mv-scene-btn {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  background: none;
  border-radius: var(--radius-2);
  color: var(--ink-3);
  font: inherit;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.mv-scene-btn:hover:not(:disabled) {
  background: rgba(17, 17, 17, 0.07);
  color: var(--ink);
}
.mv-scene-btn:disabled { opacity: 0.3; cursor: default; }
html.dark .mv-scene-btn:hover:not(:disabled) { background: rgba(247, 247, 242, 0.08); }
.mv-scene-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 48px; /* one upload standard, matching .mv-upload */
  margin-top: 8px;
  border-radius: var(--mv-control-radius);
  border: 1px dashed var(--line-2);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}
.mv-scene-add:hover:not(:disabled) { border-color: var(--ink-3); background: #f2f2ee; }
html.dark .mv-scene-add { background: #181816; border-color: #34342f; }
html.dark .mv-scene-add:hover:not(:disabled) { background: #20201d; border-color: var(--ink-3); }
/* Background panel: the Add CTA, scene chips and upload boxes read on the same
   surface as the tools bar/panel (transparent) rather than the off-tone --paper
   fill, so the video/image area matches the rest of the left menu. */
#scenes-section .mv-scene-add,
#scenes-section .mv-scene-chip,
#image-upload-group .mv-upload,
#video-upload-group .mv-upload,
html.dark #image-upload-group .mv-upload,
html.dark #video-upload-group .mv-upload {
  background: transparent;
}
.mv-scene-add:disabled {
  opacity: 0.55;
  cursor: default;
}
/* Anonymous (signed-out) state: the section stays visible but inert — scenes
   only ship on signed-in renders, so the picker must not open while anon. */
#scenes-section.is-anon .mv-scene-list {
  opacity: 0.55;
}
.mv-scene-note {
  margin: 8px 0 0;
  font-size: var(--text-sm);
  color: var(--ink-4);
}

/* ── Custom logo branding (Export panel) ─────────────────────────────────
   The Branding choice (badge / remove / your logo) + the logo controls that
   appear when "Your logo" is selected. Foundation tokens only; dark mode via
   the same html.dark overrides the rest of the sidebar uses. */
/* Match the top margin the panel gives between stacked fields, so "Branding"
   sits at the same rhythm below Quality as the other sections. */
.mv-branding {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 14px;
}
/* Give the "Branding" caption a touch of air above the tight option list. */
.mv-branding .mv-inline-label {
  margin-bottom: 6px;
}
/* Branding options render as plain radio rows (no card box); the label spans
   inherit the shared sidebar-label style (11px / ink-3 / 500) via the selector
   group above, so they read exactly like every other left-menu label. */
.mv-branding .mv-check-row {
  cursor: pointer;
  min-height: 0;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: 0;
  gap: 9px;
}
.mv-branding .mv-check-row.is-disabled {
  opacity: 0.55;
  cursor: default;
}
/* Keep the legacy #remove-watermark checkbox in the DOM (canonical state for
   pricing/engine/saved configs) without rendering it. */
.mv-visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.mv-logo-controls {
  display: flex;
  flex-direction: column;
  /* 6px inter-slider rhythm to match the rest of the left menu (the 6px
     .mv-slider + .mv-slider margin used by Angle / Motion speed / Blend
     softness etc.). */
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  background: var(--paper);
}
/* A little more air around the non-slider members (current-logo row, save CTA)
   so they don't crowd the sliders. */
.mv-logo-controls > .mv-upload-group,
.mv-logo-controls > #brand-kit-save {
  margin-top: 4px;
}
.mv-logo-controls > .mv-upload-group:first-child {
  margin-top: 0;
}
/* When a logo is saved the upload group is hidden, but the adjacent-sibling
   rule (.mv-upload-group + .mv-field) still applies a 14px top margin to the
   "My logo" block — cancel it so it sits flush at the box's top padding. */
#brand-kit-apply-block {
  margin-top: 0;
}
html.dark .mv-logo-controls {
  background: #181816;
  border-color: #34342f;
}
/* Checkerboard behind the thumb so transparent logos stay visible in both themes. */
.mv-logo-thumb {
  width: 28px;
  height: 28px;
  object-fit: contain;
  border-radius: 6px;
  background: repeating-conic-gradient(var(--line) 0% 25%, transparent 0% 50%) 0 0 / 12px 12px;
  flex: none;
}
/* Compact square icon buttons (apply / delete My logo). */
.mv-icon-btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-2);
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.mv-icon-btn:hover { border-color: var(--ink-3); color: var(--ink); background: var(--paper); }
.mv-icon-btn:disabled { opacity: 0.5; cursor: default; }
.mv-icon-btn-danger:hover { border-color: #dc2626; color: #dc2626; background: rgba(220, 38, 38, 0.06); }
html.dark .mv-icon-btn { background: #181816; border-color: #34342f; }
html.dark .mv-icon-btn:hover { border-color: var(--ink-3); }

/* ══════════════════════════════════════════════════════════
   MOBILE EDITOR (≤720px)
   Everything in this section is either display:none outside
   the breakpoint or scoped inside the ≤720px media query, so
   desktop rendering is pixel-unchanged. Layout/interaction
   only — never canvas drawing (offline renders share this
   bundle; goldens must stay stable).
   ══════════════════════════════════════════════════════════ */

@media (max-width: 720px) {
  /* Leave room for the home-indicator inset at the bottom of the scroll. */
  .mv-app {
    padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  }

  /* ── Touch targets (≥42px for primary controls) ────────── */
  .mv-panel-toggle {
    width: 42px;
    height: 42px;
  }

  .mv-preview-btn {
    width: 42px;
    height: 42px;
  }

  .mv-lyric-icon-btn {
    width: 38px;
    height: 38px;
  }

  /* Bigger hit area without inflating the compact file rows. */
  .mv-audio-clear {
    width: 38px;
    height: 38px;
    margin: -6px 0;
  }

  .mv-inline-remove-btn {
    width: 42px;
    min-height: 42px;
  }

  .mv-align-btn {
    min-height: 44px;
  }

  .mv-loop-option {
    padding: 11px 10px;
  }

  .mv-font-trigger,
  .mv-spectrum-trigger,
  .mv-lyric-source-btn {
    min-height: 44px;
  }

  .mv-font-option {
    padding: 12px;
  }

  .mv-scene-repeat {
    height: 36px;
  }

  .mv-scene-btn {
    width: 36px;
    height: 36px;
  }

  .mv-scene-btn.mv-scene-repeat-btn {
    width: 28px;
    height: 34px;
  }

  .mv-spectrum-modal-close {
    width: 42px;
    height: 42px;
  }

  /* Text-link actions (add lyrics manually / sample .lrc). */
  .mv-lyric-textlink {
    padding: 10px 0;
  }

  /* ── Inputs: 16px font stops iOS zoom-on-focus; 44px rows ── */
  .mv-sidebar-card input:not([type="range"]):not([type="color"]):not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="file"]),
  .mv-sidebar-card select {
    min-height: 44px;
    font-size: 16px;
  }

  .mv-lyric-edit-text,
  .mv-lyric-edit-num input {
    font-size: 16px;
  }

  /* ── Sliders: thumb-friendly range inputs ──────────────── */
  .mv-panel-body input[type="range"] {
    height: 30px;
  }

  .mv-panel-body input[type="range"]::-webkit-slider-thumb {
    width: 22px;
    height: 22px;
    margin-top: -9px; /* center 22px thumb over 4px track */
  }

  .mv-panel-body input[type="range"]::-moz-range-thumb {
    width: 22px;
    height: 22px;
  }

  .mv-preview-seek::-webkit-slider-thumb {
    width: 20px;
    height: 20px;
    margin-top: -8px; /* center 20px thumb over 4px track */
  }

  .mv-preview-seek::-moz-range-thumb {
    width: 20px;
    height: 20px;
  }

  /* ── Style-picker sheets: respect the home-indicator inset ── */
  .mv-spectrum-modal-box {
    max-height: 85dvh;
    padding-bottom: calc(28px + env(safe-area-inset-bottom, 0px));
  }
}
/* ── Mix Mode panel (server flag /api/config `mixEnabled`) ─────────────── */
.mv-mix-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}
.mv-mix-list:empty { margin-top: 0; }
.mv-mix-row {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--mv-control-radius);
  padding: 6px 8px;
  /* Non-grabbed rows slide to make room while a sibling is dragged. */
  transition: transform 160ms var(--ease-out);
}
/* The grabbed row lifts out (scale + shadow) and follows the pointer with no
   transition so it tracks 1:1 (same as the background scene chips). */
.mv-mix-row.is-grabbing {
  transition: none;
  position: relative;
  z-index: 5;
  box-shadow: 0 10px 26px rgba(17, 17, 17, 0.22);
  cursor: grabbing;
}
html.dark .mv-mix-row.is-grabbing { box-shadow: 0 12px 28px rgba(0, 0, 0, 0.5); }
.mv-mix-row.has-error { border-color: var(--danger); }
/* 42px touch drag handle (HTML5 DnD source). */
.mv-mix-handle {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 42px;
  border: none;
  background: none;
  border-radius: var(--radius-2);
  color: var(--ink-4);
  font-size: 15px;
  letter-spacing: 1px;
  cursor: grab;
  touch-action: none;
}
.mv-mix-handle:active { cursor: grabbing; }
.mv-mix-art {
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 6px;
  border: 1px dashed var(--line-2);
  background: var(--paper-2) center/cover no-repeat;
  color: var(--ink-4);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}
.mv-mix-art.has-art { border-style: solid; color: transparent; }
.mv-mix-fields {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.mv-mix-fields input {
  width: 100%;
  min-width: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-2);
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
  padding: 2px 6px;
}
.mv-mix-fields input:hover { border-color: var(--line); }
.mv-mix-fields input:focus { border-color: var(--ink-3); outline: none; background: var(--paper-2); }
.mv-mix-fields input.mv-mix-artist { color: var(--ink-3); font-size: var(--text-xs); }
.mv-mix-caption {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-xs);
  line-height: 1.3;
  color: var(--ink-4);
  padding: 0 6px;
}
.mv-mix-caption.is-error { color: var(--danger); }
#mix-panel.is-anon .mv-mix-list { opacity: 0.45; pointer-events: none; }

/* ── Audio mode selector (top of the Audio panel: Single track | Mix) ──────
   Reuses the .mv-align-group segmented shell. 42px minimum height keeps the
   primary mode choice a comfortable touch target at EVERY viewport width
   (the .mv-app compact-height override would otherwise shrink it to 34px). */
.mv-audio-mode { margin-bottom: 10px; }
.mv-app .mv-audio-mode .mv-align-btn {
  min-height: 42px;
  flex-direction: column;
  gap: 1px;
  font-size: var(--text-sm);
  font-weight: 500;
}
.mv-audio-mode .mv-audio-mode-sub {
  font-size: var(--text-xs);
  font-weight: 400;
  line-height: 1;
  opacity: 0.75;
}
.mv-audio-mode .mv-align-btn:disabled {
  opacity: 0.5;
  cursor: default;
}
.mv-audio-mode-hint { margin: -4px 0 8px; }
/* Mix mode replaces the single-file controls with the track list (the Audio
   panel carries .is-mix while the Mix mode is selected). display:none (not
   [hidden]) so it never fights loadAudio/clearAudio's own hidden toggling. */
#audio-panel.is-mix #audio-upload-label,
#audio-panel.is-mix #audio-file-info { display: none; }
#mix-panel { margin-top: 2px; }

/* Filmstrip → Track name styling controls (revealed when Track name is On). */
#filmstrip-name-controls {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
