/* Marker — DAW-style review tool. Mobile-first, dark only, single accent. */

:root {
  --bg: #0c0c0d;
  --surface: #131316;
  --surface-2: #18181c;
  --surface-3: #1e1e22;
  --border: #262628;
  --border-soft: #1d1d20;
  --text: #e8e8ea;
  --text-dim: #8a8a90;
  --text-faint: #54545a;
  --accent: #c8ff00;
  --accent-dim: rgba(200, 255, 0, 0.18);
  --danger: #ff5562;
  --warn: #ffb454;

  --font-mono: "IBM Plex Mono", "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-sans: "Archivo", "Inter", system-ui, -apple-system, sans-serif;

  --grid: linear-gradient(rgba(255,255,255,0.018) 1px, transparent 1px) 0 0 / 100% 8px,
          linear-gradient(90deg, rgba(255,255,255,0.018) 1px, transparent 1px) 0 0 / 8px 100%;

  --transport-h: calc(64px + env(safe-area-inset-bottom));
  --wave-height: 180px;
}

* { box-sizing: border-box; }

/* Browsers default `[hidden] { display: none }` at low priority — any
   class with `display: inline-flex / flex / block` defined on the same
   element wins and the [hidden] attribute silently does nothing. Force
   it back so toggling `el.hidden = true` actually hides the element
   regardless of what other display rules apply. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
  touch-action: manipulation;  /* kills 300ms tap delay on iOS */
  text-rendering: optimizeLegibility;
  /* Mobile guard — any element wider than the viewport (an overlong
     title, a stretched topbar full of icon buttons, the transport
     bar) used to shift the body sideways and cut off content. Just
     clip the overflow; do NOT force width / max-width — on iOS Safari
     that combo can render the body narrower than the visual viewport
     and leave a black gutter on the right. */
  overflow-x: clip;
}
/* `overflow-x: clip` doesn't exist on older Safari — fall back to
   hidden, which has the same visual effect at the cost of forming a
   new containing block. */
@supports not (overflow-x: clip) {
  html, body { overflow-x: hidden; }
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  padding-bottom: env(safe-area-inset-bottom);
  -webkit-user-select: none;
  user-select: none;
}
/* Pages that actually render a .topbar (every page except the login
   screen) get top padding equal to the fixed topbar's height, so the
   first page element starts BELOW the bar and not under it. */
body:has(.topbar) {
  padding-top: calc(56px + env(safe-area-inset-top));
}

/* Re-enable selection where users actually want it (notes, share links). */
textarea, input, .marker-text, .transcript, .share-link {
  -webkit-user-select: text;
  user-select: text;
}

/* PWA standalone mode (iOS home-screen + Android-installed) — pull
   the topbar all the way up under the status bar and trust the
   safe-area paddings to keep content readable. */
html[data-display="standalone"] body {
  overscroll-behavior-y: contain;
}
html[data-display="standalone"] .topbar {
  background: var(--bg);
  /* darker hairline under the status bar when notched */
  border-bottom-color: var(--border);
}

/* Disable the iOS pull-to-refresh / rubber-banding that would tear the
   fixed transport bar away from the bottom. */
@supports (-webkit-touch-callout: none) {
  html, body { overscroll-behavior-y: none; }
}

a { color: var(--accent); text-decoration: none; }

button, input, textarea, select {
  font: inherit;
  color: inherit;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 10px 12px;
  outline: none;
}
button { cursor: pointer; user-select: none; }
button:disabled { opacity: 0.4; cursor: not-allowed; }
input:focus, textarea:focus, select:focus { border-color: var(--accent); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 16px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  border: 1px solid var(--border);
  background: var(--surface-2);
  transition: border-color 0.12s, background 0.12s;
  min-height: 44px;
}
.btn:hover { border-color: var(--text-dim); }
.btn.primary {
  background: var(--accent); color: #0a0a0a; border-color: var(--accent);
}
.btn.primary:hover { filter: brightness(1.05); }
.btn.danger { color: var(--danger); }
.btn.ghost { background: transparent; }
.btn.sm { min-height: 32px; padding: 6px 10px; font-size: 11px; }

.label {
  text-transform: uppercase;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--text-dim);
}

.mono { font-family: var(--font-mono); }
.dim  { color: var(--text-dim); }
.faint { color: var(--text-faint); }

/* Header */
.topbar {
  /* FIXED, not sticky. On iOS Safari the rubber-band overscroll at the
     top of the document drags a sticky bar DOWN with the bounce,
     briefly revealing the track-header / waveform above the topbar's
     bottom edge. position: fixed pins the bar to the viewport instead
     so it can't bounce. Body has matching padding-top so layout flow
     starts below the bar. */
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  padding: env(safe-area-inset-top) 16px 0;
  display: flex; align-items: center; gap: 12px;
  height: calc(56px + env(safe-area-inset-top));
  min-width: 0;
}
.brand {
  font-family: var(--font-mono); font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase; font-size: 13px;
}
.brand .accent { color: var(--accent); }
/* Inline build tag in the topbar. Tightens letter-spacing + drops a
   tier so it reads as metadata, not as part of the brand. Shown on
   every authenticated page so the user always knows which build they
   are looking at. */
.brand-version {
  font-family: var(--font-mono); font-weight: 400;
  font-size: 10px; letter-spacing: 0.12em;
  color: var(--text-faint);
  margin-left: 8px;
}
@media (max-width: 380px) {
  /* Smallest phones already drop the tier badge; keep the brand line
     readable by hiding the version too. The footer fallback on
     non-topbar pages still surfaces it for the auth screen. */
  .brand-version { display: none; }
}
.topbar .spacer { flex: 1; }
.topbar .meta {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-dim);
  text-transform: uppercase; letter-spacing: 0.12em;
}
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text);
}
/* Scale the inline SVG up to fill the button — the hardcoded
   width="16" attribute leaves too much empty padding inside the chip
   and the icons read as tiny on a phone. CSS dimensions win over the
   HTML attribute. */
.icon-btn svg {
  width: 20px; height: 20px;
}

/* Containers */
.container {
  padding: 16px;
  padding-bottom: calc(var(--transport-h) + 24px);
  max-width: 760px;
  margin: 0 auto;
}
.section { margin-bottom: 28px; }
/* Visible divider between consecutive sections on the main page so the
   transition from Tracks → Shared with me → Saved share links reads as
   distinct regions instead of bleeding together. The thin top border
   plus extra padding mirrors the topbar / track-list border styling so
   it sits in the app's existing visual language. */
.section + .section {
  border-top: 1px solid var(--border);
  padding-top: 24px;
  margin-top: 8px;
}
.section h2 {
  font-family: var(--font-mono); text-transform: uppercase;
  letter-spacing: 0.16em; font-size: 12px; color: var(--text-dim);
  margin: 0 0 10px;
  display: flex; align-items: center; gap: 10px;
}
.h2-dot {
  display: inline-block;
  width: 8px; height: 8px;
  background: var(--accent);
}
.quota.inline { margin: 0 0 0 8px; }

/* Collapsible upload section. The native <details>/<summary> keeps it
   a single tap to expand, accessible without JS, and the summary
   mirrors the section h2 so a closed upload still reads as a
   prominent heading row (green dot, mono caps) rather than disappearing
   into the page chrome. Default-closed because the form is tall and
   the track list is the primary content. */
.upload-collapse > summary {
  list-style: none;
  cursor: pointer;
  font-family: var(--font-mono); text-transform: uppercase;
  letter-spacing: 0.16em; font-size: 12px; color: var(--text-dim);
  margin: 0 0 10px;
  display: flex; align-items: center; gap: 10px;
  padding: 6px 0;
  user-select: none;
}
.upload-collapse > summary::-webkit-details-marker { display: none; }
/* Chevron drawn with a CSS triangle so it inherits the dim text color
   without an extra SVG. Rotates 90° when the details element opens. */
.upload-collapse > summary::after {
  content: "";
  margin-left: auto;
  width: 0; height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 0.15s;
}
.upload-collapse[open] > summary::after { transform: rotate(90deg); }
.upload-collapse[open] > summary .upload-summary-hint { display: none; }
.upload-summary-hint { font-size: 10px; letter-spacing: 0.12em; }

/* Auth */
.auth-wrap {
  min-height: 100dvh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: 24px;
  background:
    radial-gradient(1200px 600px at 50% -10%, rgba(200,255,0,0.04), transparent 60%),
    var(--bg);
}
.auth-card {
  width: 100%; max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 28px 22px;
}
.auth-version {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.18em;
  color: var(--text-dim); text-transform: uppercase;
  margin-top: 18px; text-align: center;
}
/* App pitch card under the login form. Same width and surface as
   auth-card so it reads as a continuation of the sign-in panel rather
   than a footer afterthought. */
.auth-pitch {
  width: 100%; max-width: 380px;
  margin-top: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 18px 22px;
}
.auth-pitch-label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em;
  color: var(--text-dim); text-transform: uppercase;
  margin-bottom: 10px;
}
.auth-pitch-dot {
  width: 8px; height: 8px; background: var(--accent);
  display: inline-block; flex-shrink: 0;
}
.auth-pitch p {
  margin: 0;
  font-size: 13px; line-height: 1.6; color: var(--text);
}
.auth-card h1 {
  font-family: var(--font-mono); font-size: 13px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text); margin: 0 0 4px;
}
.auth-card .sub {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-dim);
  text-transform: uppercase; letter-spacing: 0.14em; margin-bottom: 20px;
}
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.field input { background: var(--surface-2); }
.tabs { display: flex; border: 1px solid var(--border); margin-bottom: 22px; }
.tabs button {
  flex: 1; background: transparent; border: 0; padding: 10px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-dim);
}
.tabs button.active { background: var(--surface-2); color: var(--text); }
.error {
  color: var(--danger); font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.08em; text-transform: uppercase;
  margin-top: 10px; min-height: 14px;
}

/* Upload */
.upload-zone {
  border: 1px dashed var(--border);
  background:
    var(--grid),
    var(--surface);
  padding: 22px;
  text-align: center;
  margin-bottom: 12px;
}
.upload-zone.drag { border-color: var(--accent); background-color: var(--surface-2); }
.upload-zone .label-l {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-dim);
  letter-spacing: 0.14em; text-transform: uppercase;
}
.upload-zone .filename {
  font-family: var(--font-mono); font-size: 12px; color: var(--text); margin-top: 6px;
  word-break: break-all;
}
.upload-fields { display: flex; flex-direction: column; gap: 8px; }
.upload-fields input { background: var(--surface-2); }
.upload-progress {
  margin-top: 10px; height: 2px; background: var(--surface-2);
  position: relative; overflow: hidden;
}
.upload-progress > span {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0;
  background: var(--accent); transition: width 0.15s linear;
}

/* Track list */
.track-list { display: flex; flex-direction: column; gap: 0; border-top: 1px solid var(--border); }
.track-row {
  display: flex; align-items: center; gap: 8px;
  padding: 14px 4px; border-bottom: 1px solid var(--border-soft);
}
.track-row:hover { background: var(--surface); }
.track-link {
  display: flex; flex: 1; min-width: 0; align-items: center; gap: 12px;
  text-decoration: none; color: inherit; cursor: pointer;
  padding: 0 4px;
}
/* Cover-art thumbnail in the track list. Empty placeholder keeps the
   row grid aligned regardless of whether the track has art. */
.track-art {
  width: 40px; height: 40px;
  object-fit: cover;
  border: 1px solid var(--border);
  background: var(--surface-2);
  flex-shrink: 0;
}
.track-art.empty {
  background:
    linear-gradient(135deg, transparent 49%, var(--border) 49%, var(--border) 51%, transparent 51%) 0 0 / 8px 8px,
    var(--surface-2);
}
.track-row .title { flex: 1; min-width: 0; }
.track-row .title .t1 { font-weight: 600; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.track-row .title .t2 {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-dim);
  text-transform: uppercase; letter-spacing: 0.1em; margin-top: 2px;
}
.track-del, .track-edit {
  width: 32px; height: 32px;
  background: transparent; border: 1px solid var(--border-soft);
  color: var(--text-faint);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; padding: 0;
}
.track-del:hover { color: var(--danger); border-color: var(--danger); }
.track-edit:hover { color: var(--accent); border-color: var(--accent); }
.badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 28px; height: 22px; padding: 0 7px;
  border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
}
.badge.accent { background: var(--accent); color: #0a0a0a; border-color: var(--accent); }
.badge.dim { color: var(--text-dim); }

.empty {
  text-align: center; padding: 40px 20px;
  border: 1px dashed var(--border);
  background: var(--grid), var(--surface);
}
.empty .label { display: block; margin-bottom: 6px; }
.marker-list .empty { margin: 16px; }

/* Recurring small-text caption block — fineprint / hint under inputs / sheet meta */
.fineprint {
  font-family: var(--font-mono);
  font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-dim);
  line-height: 1.5;
  min-height: 1em;
}
.fineprint:not(:empty) { margin-bottom: 18px; }

/* Generic sheet body content (paragraph + bullet list) used by upgrade /
   confirm / alert sheets so they share the marker-sheet typography. */
.sheet-body {
  color: var(--text-dim);
  font-size: 14px; line-height: 1.5;
  margin: 0 0 16px;
}
.sheet-benefits {
  list-style: none; padding: 0;
  margin: 0 0 18px;
  display: flex; flex-direction: column; gap: 6px;
  font-family: var(--font-mono); font-size: 12px;
  letter-spacing: 0.04em;
}
.sheet-benefits li {
  color: var(--text);
  padding-left: 12px;
  border-left: 1px solid var(--border);
}
.sheet-benefits li.off {
  color: var(--text-faint);
  text-decoration: line-through;
}

/* Track page */
.track-header {
  padding: 14px 16px 12px;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 14px;
  /* A long unbroken title (e.g. "groovebox_2_edit_master_v3") would
     otherwise force the parent block wider than the viewport. Let it
     wrap inside its own box instead. */
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.track-header-body { flex: 1; min-width: 0; }
.track-header-art {
  width: auto; height: auto; flex-shrink: 0;
  max-height: var(--wave-height);
  max-width: var(--wave-height);
  object-fit: contain;
  border: 1px solid var(--border);
}
.track-header .title { font-weight: 700; font-size: 18px; min-width: 0; }
.track-header .meta {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-dim);
  letter-spacing: 0.12em; text-transform: uppercase; margin-top: 4px;
  display: flex; gap: 14px; flex-wrap: wrap;
}
.share-tagline {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-dim);
  letter-spacing: 0.04em; margin-top: 8px; line-height: 1.4;
}

/* Waveform */
.waveform-wrap {
  position: relative;
  background:
    var(--grid),
    var(--surface);
  border-bottom: 1px solid var(--border);
  height: var(--wave-height);
  touch-action: none;
  user-select: none;
}
.waveform-wrap canvas { display: block; width: 100%; height: 100%; }
.playhead {
  position: absolute; top: 0; bottom: 0; width: 1px;
  background: var(--accent);
  pointer-events: none;
  box-shadow: 0 0 6px var(--accent);
}
.playhead::before {
  content: ""; position: absolute; left: -3px; top: 0;
  width: 7px; height: 7px; background: var(--accent);
}
.pin {
  position: absolute; top: 0; bottom: 0; width: 1px;
  background: var(--text); opacity: 0.85;
  /* Pin must be hoverable so the wave→list highlight cross-link
     fires. Scrub gestures still work because pointerdown/touchstart
     bubble up to the wave container's delegated handlers. */
  pointer-events: auto;
  cursor: inherit;
  /* Expand the hit area horizontally a touch — a 1 px line is
     basically un-hoverable otherwise. background-clip: content-box
     keeps the painted stripe at the original 1 px width while the
     padding stays a transparent 3 px hit-buffer on each side. Without
     the clip the background bled into the padding and the pin looked
     like an 8 px slab. */
  margin-left: -3px;
  padding-left: 3px;
  padding-right: 3px;
  box-sizing: content-box;
  background-clip: content-box;
}
.pin.done { opacity: 0.25; }
.pin::after {
  /* Cap is positioned relative to the .pin's padding-box edge. With the
     3 px hit-area padding-left, the visible 1 px stripe sits 3 px inside
     the box, so the cap (10 px wide) is shifted right to stay centered
     on the stripe instead of on the hit-area's left edge. */
  content: ""; position: absolute; top: 0; left: -1px;
  width: 10px; height: 10px;
  background: var(--text); border: 1px solid var(--bg);
}
.pin.done::after { background: var(--text-faint); }
.pin.voice::before {
  /* Centered on the visible 1 px stripe (which lives 3 px inside the
     pin's padding-box because of the hover hit-area). */
  content: ""; position: absolute; top: 12px; left: 0px;
  width: 7px; height: 7px;
  background: var(--accent);
  border: 1px solid var(--bg);
  border-radius: 50%;
}

/* Author color overrides the default white-ish pin cap when set */
.pin[style*="--author-color"]::after { background: var(--author-color, var(--text)); }

/* Private marker — dashed stem, hollow cap. The dashes are painted via
   a repeating gradient so they live in the 2 px content area (clipped
   to content-box like the solid pin) instead of on the border edge,
   which would draw 3 px to the left of where the public pin renders. */
.pin.private {
  background: repeating-linear-gradient(
    to bottom,
    var(--text) 0,
    var(--text) 4px,
    transparent 4px,
    transparent 7px
  );
  background-clip: content-box;
}
.pin.private::after {
  background: var(--bg);
  border: 1px solid var(--text);
}
.pin.private[style*="--author-color"]::after {
  background: var(--bg);
  border-color: var(--author-color, var(--text));
}

/* Zoom state visualization on the waveform container */
.waveform-wrap.zoomed {
  outline: 1px solid var(--accent);
  outline-offset: -1px;
  background:
    var(--grid),
    linear-gradient(180deg, rgba(200, 255, 0, 0.04), rgba(200, 255, 0, 0.02)),
    var(--surface);
  cursor: grab;
}
.waveform-wrap.zoomed:active { cursor: grabbing; }
.waveform-wrap.zoomed::after {
  content: "ZOOM · DRAG TO PAN · TAP TO MARK"; position: absolute; top: 6px; right: 8px;
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.16em;
  color: var(--accent);
  pointer-events: none;
  max-width: calc(100% - 16px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 480px) {
  .waveform-wrap.zoomed::after { content: "ZOOM · DRAG · TAP"; }
}

.exit-zoom-btn {
  display: none;
  margin: 6px 16px;
}
.exit-zoom-btn.show { display: inline-flex; }
.timeruler {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 16px;
  font-family: var(--font-mono); font-size: 9px;
  color: var(--text-faint); letter-spacing: 0.06em;
  display: flex; justify-content: space-between;
  padding: 0 6px; pointer-events: none;
}

/* Multi-version compare panel — stacked mini-waveforms with per-row
   visibility toggle and offset slider for visual A/B alignment. */
.compare-panel {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.compare-header {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 16px 6px;
}
.compare-rows { display: flex; flex-direction: column; padding: 0 0 6px; }
.compare-row {
  display: grid;
  /* visBtn · Listen · info · canvas · Reset */
  grid-template-columns: 28px 96px 110px 1fr auto;
  align-items: center; gap: 10px;
  padding: 6px 12px;
  border-top: 1px solid var(--border-soft);
  background: var(--bg);
  transition: border-color 120ms, box-shadow 120ms;
}
.compare-row.current { background: var(--surface-2); }
.compare-row.hidden { opacity: 0.5; }
/* The version whose audio is currently coming out of the main player gets
   a glowing inset accent border so the user can see at a glance which
   row they're hearing. */
.compare-row.auditioning {
  box-shadow: inset 3px 0 0 var(--accent);
}

.cmp-vis {
  width: 22px; height: 22px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  cursor: pointer; padding: 0;
  position: relative;
}
.cmp-vis::after {
  content: ""; position: absolute;
  inset: 4px;
  background: transparent;
  border: 1px solid var(--row-color, var(--text-dim));
}
.cmp-vis.on::after { background: var(--row-color, var(--accent)); }
.cmp-vis:disabled { cursor: default; opacity: 1; }

.cmp-info { min-width: 0; }
.cmp-label {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cmp-offset {
  font-size: 10px; color: var(--text-dim);
  letter-spacing: 0.06em; margin-top: 2px;
}

.cmp-wave-host {
  height: 64px;
  background:
    /* A faint vertical center line + a 1/2 marker hint help the user
       see how each version maps onto the shared reference timeline. */
    linear-gradient(rgba(255,255,255,0.08) 1px, transparent 1px) 0 50% / 100% 1px no-repeat,
    linear-gradient(rgba(255,255,255,0.018) 1px, transparent 1px) 0 0 / 100% 8px,
    var(--surface);
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border-soft);
  touch-action: pan-y;
}
.cmp-wave-host.draggable { cursor: grab; }
.cmp-wave-host.draggable.dragging {
  cursor: grabbing; border-color: var(--accent);
  background-color: var(--surface-2);
}
.cmp-wave-host canvas { display: block; width: 100%; height: 100%; pointer-events: none; }
/* Vertical playhead indicator inside each compare row. Position is set
   in JS (style.left). All rows share the same X so when versions are
   aligned via drag, the line crosses each waveform at the equivalent
   musical moment. The active row's line is the bright accent so the
   user can see at a glance which version is being heard right now. */
.cmp-playhead {
  position: absolute; top: -2px; bottom: -2px;
  width: 2px; margin-left: -1px;
  background: rgba(255, 255, 255, 0.35);
  pointer-events: none;
  transition: background 80ms, box-shadow 80ms;
  z-index: 2;
}
.cmp-playhead::before {
  content: "";
  position: absolute;
  top: -3px; left: -3px;
  width: 8px; height: 8px;
  background: inherit;
  border-radius: 50%;
}
.compare-row.auditioning .cmp-playhead {
  background: var(--accent);
  box-shadow: 0 0 8px rgba(200, 255, 0, 0.55);
}

.cmp-actions {
  display: flex; gap: 6px; align-items: center;
}
.cmp-actions .btn.sm { font-size: 9px; padding: 4px 8px; min-height: 24px; }
/* Listen button — fills with accent to read as the primary A/B action. */
.cmp-listen {
  background: var(--accent); color: #0a0a0a; border-color: var(--accent);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.cmp-listen:hover { filter: brightness(1.06); border-color: var(--accent); }
.cmp-listen svg { display: block; }
.compare-row.auditioning .cmp-listen {
  background: var(--surface-3); color: var(--accent); border-color: var(--accent);
}

#compare-toggle.active {
  border-color: var(--accent);
  color: var(--accent);
}

@media (max-width: 640px) {
  /* On phones the columns become: visBtn · Listen · info-+-actions
     in row 1, canvas spanning full width below. */
  .compare-row {
    grid-template-columns: 28px auto 1fr auto;
    grid-template-rows: auto auto;
    gap: 6px 10px;
  }
  .cmp-wave-host { grid-column: 1 / -1; }
}

/* Version switcher — small tab strip above the waveform when this
   track is part of a version chain. */
.version-switcher {
  display: flex; gap: 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  overflow-x: auto;
}
/* Each tab lives inside a wrapper so we can pin a delete-× to it without
   the × becoming part of the tab's click target. */
.version-tab-wrap {
  flex: 1; min-width: 60px;
  display: flex; align-items: stretch;
  border-right: 1px solid var(--border-soft);
  position: relative;
}
.version-tab-wrap:last-child { border-right: 0; }
.version-tab-wrap.active { background: var(--surface-3); }
.version-tab {
  flex: 1; min-width: 0;
  padding: 8px 22px 8px 10px; min-height: 32px;
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-dim); text-decoration: none;
  text-align: center;
  display: inline-flex; align-items: center; justify-content: center;
  white-space: nowrap;
}
.version-tab.active { color: var(--accent); }
.version-tab:hover:not(.active) { color: var(--text); background: var(--surface-2); }
.version-tab-del {
  position: absolute; top: 50%; right: 4px;
  transform: translateY(-50%);
  width: 18px; height: 18px; padding: 0;
  background: transparent; border: 1px solid transparent;
  color: var(--text-faint);
  display: inline-flex; align-items: center; justify-content: center;
  opacity: 0; transition: opacity 100ms, color 100ms, border-color 100ms;
}
.version-tab-wrap:hover .version-tab-del { opacity: 1; }
.version-tab-del:hover { color: var(--danger); border-color: var(--danger); }
.version-tab-del:focus { opacity: 1; }
@media (hover: none) {
  /* On touch devices reveal the × permanently — there's no hover state. */
  .version-tab-del { opacity: 0.6; }
}

/* Sync controls for A/B compare */
.version-sync-ctrl {
  display: flex; gap: 6px;
  padding: 4px 10px;
  border-left: 1px solid var(--border-soft);
  align-items: center;
  flex-shrink: 0;
}
.version-sync-ctrl .btn.sm {
  font-size: 9px; padding: 4px 8px; min-height: 24px;
}

/* Track-row decorations for the version chain in the app list */
.track-row.versioned-child {
  background: var(--surface);
}
.chain-marker {
  display: inline-flex; align-items: center; justify-content: center;
  /* min-width / height / margin-right MATCH .chain-toggle so a parent
     row's chain badge and a child row's "└" occupy the same column —
     artwork, title, and badge all line up vertically. */
  min-width: 42px; height: 24px; margin-right: 6px;
  font-family: var(--font-mono); font-size: 13px;
  color: var(--text-faint);
}
/* Head of a multi-version chain — gets a chevron+count badge that
   expands/collapses the older siblings underneath. */
.track-row.chain-head {
  border-bottom: 0;
}
.chain-toggle {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  min-width: 42px; height: 24px; padding: 0 8px; margin-right: 6px;
  border: 1px solid var(--border);
  background: var(--surface-2); color: var(--text-dim);
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.08em; line-height: 1;
  cursor: pointer; user-select: none;
  transition: background 90ms, color 90ms, border-color 90ms;
}
.chain-toggle:hover {
  background: var(--surface-3); color: var(--text);
  border-color: var(--accent);
}
.chain-toggle[data-expanded="1"] {
  background: var(--surface-3); color: var(--text);
}
.chain-count {
  font-size: 10px; opacity: 0.75; letter-spacing: 0.04em;
}

/* Per-link marker whitelist picker inside the share sheet */
.share-marker-list {
  display: flex; flex-direction: column;
  border: 1px solid var(--border);
  max-height: 220px; overflow-y: auto;
  margin-top: 10px;
}
.share-marker-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 10px; border-top: 1px solid var(--border-soft);
  cursor: pointer; user-select: none;
  font-size: 12px;
}
.share-marker-row:first-child { border-top: 0; }
.share-marker-row input[type=checkbox],
.friend-share-row input[type=checkbox] {
  -webkit-appearance: none;
  appearance: none;
  width: 16px; height: 16px; flex-shrink: 0;
  margin: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  position: relative;
}
.share-marker-row input[type=checkbox]:hover,
.friend-share-row input[type=checkbox]:hover {
  border-color: var(--text-dim);
}
.share-marker-row input[type=checkbox]:focus-visible,
.friend-share-row input[type=checkbox]:focus-visible {
  outline: 1px solid var(--accent); outline-offset: 1px;
}
.share-marker-row input[type=checkbox]:checked,
.friend-share-row input[type=checkbox]:checked {
  background: var(--accent);
  border-color: var(--accent);
}
.share-marker-row input[type=checkbox]:checked::after,
.friend-share-row input[type=checkbox]:checked::after {
  content: "";
  width: 9px; height: 5px;
  border-left: 2px solid #0a0a0a;
  border-bottom: 2px solid #0a0a0a;
  transform: translateY(-1px) rotate(-45deg);
}
.share-marker-row .smk-ts {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-dim);
  letter-spacing: 0.08em; min-width: 58px;
}
.share-marker-row .smk-text {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.share-marker-row .smk-author {
  font-family: var(--font-mono); font-size: 9px; color: var(--text-faint);
  letter-spacing: 0.12em; text-transform: uppercase;
  flex-shrink: 0;
}

/* Friend-share rows inside the share sheet */
.friend-share-list {
  display: flex; flex-direction: column;
  border: 1px solid var(--border);
  max-height: 220px; overflow-y: auto;
  margin-bottom: 10px;
}
.friend-share-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px; border-top: 1px solid var(--border-soft);
  cursor: pointer; user-select: none;
}
/* Mono numeric input for share-link download cap. Narrow so it sits
   inline with the rest of the vis-row without dominating it. */
.vis-row .dl-max-input {
  width: 110px;
  padding: 4px 8px;
  background: var(--surface); border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 12px; color: var(--text);
  -moz-appearance: textfield;
}
.vis-row .dl-max-input::-webkit-outer-spin-button,
.vis-row .dl-max-input::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
.vis-row .dl-max-input:focus { border-color: var(--accent); outline: 0; }
/* Tiny download chip in the shared-with-me track list. */
.track-row .track-dl {
  flex-shrink: 0;
  width: 32px; height: 32px;
  margin-left: 6px;
}
/* "N NEW" pill on owned tracks — sits just left of the open/total
   counter so the row reads "2 NEW · 3/8" without rearranging the
   existing badge geometry. */
.track-link .track-new { margin-right: 6px; }
/* Saved-shares overview is grouped per sharer so the user sees
   "everything from Mike, then everything from Sarah" rather than a
   single timeline mixing them. The header doubles as a quick visual
   anchor for unread counts via the .accent badge. */
.saved-share-group-header {
  display: flex; align-items: center; gap: 10px;
  margin: 16px 0 6px;
  padding: 0 2px;
}
.saved-share-group-name {
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.14em; color: var(--text-dim);
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.saved-share-group-badge { flex-shrink: 0; }
/* Per-sharer CTAs live in the header — "Add friend" for strangers,
   "Accept request" when they've pinged us, "Request sent" when we've
   pinged them. Sized down so they sit next to the dim mono group name
   without dominating it. */
.saved-share-friend-btn {
  flex-shrink: 0;
  min-height: 24px; padding: 2px 9px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
  text-transform: uppercase;
}
.saved-share-friend-status {
  flex-shrink: 0;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
  color: var(--text-faint); text-transform: uppercase;
}
.saved-share-group-header:first-child { margin-top: 0; }
.friend-share-row:first-child { border-top: 0; }
.friend-share-name {
  flex: 1; min-width: 0;
}
.friend-share-name .t1 {
  font-size: 13px; color: var(--text);
}
.friend-share-name .t2 {
  font-size: 11px;
}
/* Compact uppercase badge used inside the share sheet (older-links list +
   friend rows). Mirrors the look of the existing .badge but small/inline. */
.share-tag {
  display: inline-flex; align-items: center; justify-content: center;
  height: 20px; padding: 0 7px;
  border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 9px; line-height: 1;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-dim);
  flex-shrink: 0;
}
.share-existing-row {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 8px 0; border-top: 1px solid var(--border-soft);
}
.share-existing-url {
  flex: 1; min-width: 140px;
  font-size: 11px; word-break: break-all;
}

/* Filters + search + sort row */
.filters {
  display: flex; gap: 0; padding: 12px 16px; border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.filters button {
  flex: 1; background: transparent; border: 0;
  padding: 8px; min-height: 36px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-dim);
  border: 1px solid var(--border-soft); border-left: 0;
}
.filters button:first-child { border-left: 1px solid var(--border-soft); }
.filters button.active { background: var(--surface-3); color: var(--text); border-color: var(--border); }

.list-controls {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface);
}
.list-controls input[type="search"] {
  flex: 1; min-width: 0; height: 32px; padding: 0 10px;
  background: var(--surface-2); border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 12px;
}
/* Custom dropdown — replaces the OS-native <select> menu so we stay on
   brand. Used at least for the marker sort selector; reusable elsewhere. */
.select-host { display: inline-flex; }
.select-trigger {
  height: 32px; padding: 0 10px;
  background: var(--surface-2); border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 10px;
  cursor: pointer; user-select: none;
  white-space: nowrap;
}
.select-trigger:hover { color: var(--text); border-color: var(--text-dim); }
.select-trigger.open { color: var(--text); border-color: var(--accent); background: var(--surface-3); }
.select-trigger:focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; }
.select-value { font: inherit; letter-spacing: inherit; text-transform: inherit; }
.select-caret {
  width: 0; height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform 0.12s ease-out;
}
.select-trigger.open .select-caret { transform: scaleY(-1); }

.select-menu {
  z-index: 100;
  background: var(--surface-3);
  border: 1px solid var(--border);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 4px 0;
  min-width: 140px;
}
.select-item {
  display: block; width: 100%;
  padding: 9px 14px 9px 28px;
  background: transparent; border: 0;
  color: var(--text-dim);
  text-align: left;
  font: inherit; letter-spacing: inherit; text-transform: inherit;
  cursor: pointer;
  position: relative;
}
.select-item:hover, .select-item:focus-visible {
  background: var(--surface);
  color: var(--text);
  outline: none;
}
.select-item.active { color: var(--accent); }
.select-item.active::before {
  content: ""; position: absolute;
  left: 14px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 12px;
  background: var(--accent);
}
.list-controls button.bulk {
  height: 32px; padding: 0 10px;
  background: transparent; border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
  text-transform: uppercase;
  display: inline-flex; align-items: center; justify-content: center;
  text-align: center;
}
.list-controls button.bulk:hover { color: var(--accent); border-color: var(--accent); }

/* Marker list */
.marker-list {
  padding: 0;
  /* Reserve room for the fixed transport. The shortcut bar is hidden by
     default — opening it adds extra reserve via the .shortcuts-bar:not([hidden])
     selector below. */
  padding-bottom: var(--transport-h);
}
body.shortcuts-open .marker-list {
  padding-bottom: calc(var(--transport-h) + 38px);
}
.marker-row {
  /* CSS Grid pins the timestamp column to a fixed track width so every
     row aligns at the same X regardless of whether the marker is a
     point or a range. The previous flex + fixed-width approach
     occasionally let the content stretch the box; grid is rigid. */
  display: grid;
  grid-template-columns: 96px 1fr auto;
  align-items: start;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-soft);
}
.marker-row.done .marker-text { color: var(--text-faint); text-decoration: line-through; }
.marker-row.done .marker-ts { color: var(--text-faint); }

.marker-row.private .marker-ts {
  border-style: dashed;
}
.marker-row .private-badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.14em;
  color: var(--text-dim);
  margin-left: 6px;
  text-transform: uppercase;
}
.marker-row .author-dot {
  display: inline-block; width: 7px; height: 7px;
  margin-right: 6px;
  background: var(--author-color, var(--text-dim));
  vertical-align: middle;
}

.voice-row {
  display: flex; align-items: center; gap: 8px; margin-top: 8px;
  padding: 8px 10px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
}
.voice-play {
  width: 28px; height: 28px;
  background: var(--surface-3); color: var(--text);
  border: 1px solid var(--border);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.voice-play:hover { color: var(--accent); border-color: var(--accent); }
.voice-play.playing { background: var(--accent); color: #0a0a0a; border-color: var(--accent); }
.voice-bar {
  flex: 1; height: 2px; background: var(--border);
  position: relative; overflow: hidden;
}
.voice-bar > span {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0;
  background: var(--accent);
}
.voice-dur {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-dim);
  letter-spacing: 0.06em;
}
.transcript {
  margin-top: 6px; padding: 6px 8px;
  border-left: 2px solid var(--border);
  font-size: 12px; color: var(--text-dim); line-height: 1.45;
  font-style: italic;
}
.transcript.pending { color: var(--text-faint); }
.transcript.failed { color: var(--danger); }
.marker-ts {
  /* Lives in the row's fixed 96 px grid column; width is implicit so
     the box can never grow even if the content tries to overflow.
     `min-width: 0` + word-break unlock that behaviour on edge cases
     (extremely long synthetic timestamps in tests, e.g.). */
  min-width: 0; max-width: 100%; box-sizing: border-box;
  width: 100%;
  font-family: var(--font-mono); font-size: 12px; color: var(--text);
  letter-spacing: 0.06em; padding: 6px 8px; border: 1px solid var(--border);
  background: var(--surface-2); cursor: pointer; text-align: center;
  display: inline-flex; align-items: center; justify-content: center;
}
.marker-ts.range {
  /* Range markers stack start+end vertically inside the same box width
     so the column geometry is identical to a point marker. */
  flex-direction: column; gap: 2px; padding: 4px 6px;
}
.marker-ts.range .ts-start,
.marker-ts.range .ts-end {
  display: block; line-height: 1.1;
}
.marker-ts.range .ts-end {
  font-size: 10px; color: var(--text-dim); letter-spacing: 0.04em;
}
.marker-ts:hover { color: var(--accent); border-color: var(--accent); }

/* Per-marker colour picker inside the marker sheet.
   Curated palette aligned with the app's design tokens. Square swatches
   to match the rest of the DAW look (no border-radius soup), with a
   crisp accent ring on the active selection and a subtle lift on
   hover. No native color input — the presets cover the workflow and
   the browser default doesn't blend in. */
.color-swatches {
  display: inline-flex; align-items: center; gap: 6px;
  flex-wrap: wrap;
  padding: 2px 0;
}
.color-swatch {
  width: 28px; height: 28px; padding: 0;
  flex-shrink: 0;
  border: 1px solid rgba(255, 255, 255, 0.06);
  background: var(--swatch, var(--surface-2));
  cursor: pointer;
  position: relative;
  transition: transform 130ms cubic-bezier(.2,.7,.2,1),
              box-shadow 130ms ease,
              border-color 130ms ease,
              filter 130ms ease;
  /* Inner hairline so light swatches don't bleed into the dark page
     and dark swatches keep a visible edge. */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35);
}
.color-swatch:hover {
  transform: translateY(-1px);
  filter: brightness(1.08);
}
.color-swatch:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.color-swatch.active {
  /* Triple ring: dark gap between swatch and the bright accent ring so
     it reads clearly against any colour underneath, including the
     accent-coloured priority swatch itself. */
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.35),
    0 0 0 2px var(--bg),
    0 0 0 4px var(--accent);
  transform: translateY(-1px);
}
.color-swatch.reset {
  background: var(--surface-2);
  border-color: var(--border);
  box-shadow: none;
  /* Diagonal slash → "no colour assigned" mark, drawn purely in CSS so
     it scales with the swatch and inherits the accent in active state. */
  background-image: linear-gradient(
    135deg,
    transparent 0,
    transparent calc(50% - 1px),
    var(--text-dim) calc(50% - 1px),
    var(--text-dim) calc(50% + 1px),
    transparent calc(50% + 1px),
    transparent 100%
  );
}
.color-swatch.reset.active {
  background-image: linear-gradient(
    135deg,
    transparent 0,
    transparent calc(50% - 1px),
    var(--accent) calc(50% - 1px),
    var(--accent) calc(50% + 1px),
    transparent calc(50% + 1px),
    transparent 100%
  );
}

/* Marker category — single-select chip row inside the marker sheet.
   Tighter padding + smaller font than .btn so 9 chips fit in one row
   on desktop and wrap cleanly on a 375px phone. */
.cat-chips {
  display: flex; flex-wrap: wrap; gap: 6px;
  flex: 1; min-width: 0;
}
.cat-chip {
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 5px 9px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-dim);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.cat-chip:hover { border-color: var(--text-dim); color: var(--text); }
.cat-chip.active {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
/* Inline chip surfaced on a marker row's meta line whenever the
   category is something other than "general". Same mono caps look as
   the .private-badge but with a hairline border so the two visually
   read as distinct labels. */
.cat-tag {
  display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.1em;
  padding: 1px 6px; margin-left: 8px;
  border: 1px solid var(--border);
  color: var(--text-dim);
}

/* Hover cross-link: hovering a marker pin (or range overlay) on the
   waveform highlights the matching row in the list below, and vice
   versa. `.hover-peer` is toggled in JS via data-marker-id matching. */
.marker-row.hover-peer {
  background: var(--surface);
  box-shadow: inset 3px 0 0 var(--accent);
}
.pin.hover-peer,
.range-overlay.hover-peer {
  filter: brightness(1.35) drop-shadow(0 0 6px var(--author-color, var(--accent)));
  z-index: 4;
}
.range-overlay.hover-peer {
  outline: 1px solid var(--author-color, var(--accent));
  outline-offset: -1px;
}
.marker-body { flex: 1; min-width: 0; }
.marker-text { font-size: 14px; word-wrap: break-word; }
.marker-meta {
  font-family: var(--font-mono); font-size: 10px; color: var(--text-faint);
  letter-spacing: 0.1em; text-transform: uppercase; margin-top: 4px;
}
.marker-actions { display: flex; gap: 6px; flex-shrink: 0; }
.marker-actions button {
  width: 32px; height: 32px; padding: 0;
  background: transparent; border: 1px solid var(--border);
  color: var(--text-dim);
}
.marker-actions button:hover { color: var(--text); border-color: var(--text-dim); }
.marker-actions button.active { background: var(--accent); color: #0a0a0a; border-color: var(--accent); }

/* Keyboard shortcut cheatsheet sitting just above the transport. Stays
   visible at all times on desktop so the DAW-style workflow keys are
   always within glance distance. Hidden on small screens to keep the
   transport bar uncluttered on phones. */
.shortcuts-bar {
  position: fixed; left: 0; right: 0;
  bottom: var(--transport-h);
  z-index: 29;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0;
  padding: 6px 16px;
  background: var(--bg);
  border-top: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-dim);
  overflow-x: auto;
  /* Push the marker-list above so the bar doesn't cover content. */
}
.sc-item {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border-right: 1px solid var(--border-soft);
  flex-shrink: 0;
  cursor: pointer; user-select: none;
}
.sc-item:hover { color: var(--text); background: var(--surface); }
.sc-item:last-child { border-right: 0; }
.sc-item kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 18px; padding: 0 5px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-family: var(--font-mono); font-size: 10px;
  color: var(--text);
}
.sc-help kbd { border-color: var(--accent); color: var(--accent); }
@media (max-width: 720px) {
  /* On phones the workflow is touch-first; the bar would steal screen
     space without giving useful affordances. */
  .shortcuts-bar { display: none; }
}

/* Help sheet — full shortcut list. */
.shortcuts-grid h3 {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-dim);
  margin: 14px 0 6px;
}
.shortcuts-grid h3:first-child { margin-top: 0; }
.sc-row {
  display: grid; grid-template-columns: 130px 1fr;
  gap: 10px; align-items: baseline;
  padding: 4px 0;
  border-top: 1px solid var(--border-soft);
  font-size: 12px;
}
.sc-row:first-of-type { border-top: 0; }
.sc-row kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 20px; padding: 0 6px;
  margin-right: 2px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-family: var(--font-mono); font-size: 11px;
  color: var(--text);
}

/* Transport bar */
.transport {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  background: var(--bg);
  border-top: 1px solid var(--border);
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: 12px;
  height: var(--transport-h);
  /* `left:0; right:0` already pins the bar to the viewport edges; we
     just need to make sure its inner content can't overflow. */
  box-sizing: border-box;
  overflow-x: hidden;
}
.transport .play {
  width: 44px; height: 44px;
  background: var(--accent); color: #0a0a0a;
  border: 1px solid var(--accent);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.transport .add-marker {
  width: 44px; height: 44px;
  border: 1px solid var(--border); background: var(--surface-2);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.transport .add-marker:hover { border-color: var(--accent); color: var(--accent); }
.transport .time {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.04em;
  color: var(--text); flex: 1; text-align: right;
}
.transport .time .dim { color: var(--text-dim); }

/* Volume — speaker toggle + horizontal slider. Slider hides on very
   narrow screens because the icon doubles as the mute action. */
.volume {
  display: inline-flex; align-items: center; gap: 6px;
  flex-shrink: 0;
}
.vol-btn {
  width: 36px; height: 36px; padding: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  display: inline-flex; align-items: center; justify-content: center;
}
.vol-btn:hover { color: var(--accent); border-color: var(--accent); }
.vol-btn.muted { color: var(--text-faint); }

.vol-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 80px; height: 28px;
  background: transparent;
  cursor: pointer;
  outline: none;
  /* The fill % is computed in JS via --fill so the left side of the track
     gets the accent and the right side stays neutral. */
}
.vol-slider::-webkit-slider-runnable-track {
  height: 2px;
  background:
    linear-gradient(to right,
      var(--accent) 0,
      var(--accent) var(--fill, 100%),
      var(--border) var(--fill, 100%),
      var(--border) 100%);
}
.vol-slider::-moz-range-track {
  height: 2px;
  background:
    linear-gradient(to right,
      var(--accent) 0,
      var(--accent) var(--fill, 100%),
      var(--border) var(--fill, 100%),
      var(--border) 100%);
}
.vol-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 10px; height: 10px;
  margin-top: -4px;
  background: var(--accent);
  border: 0;
  cursor: pointer;
}
.vol-slider::-moz-range-thumb {
  width: 10px; height: 10px;
  background: var(--accent);
  border: 0;
  cursor: pointer;
}
@media (max-width: 540px) {
  .vol-slider { display: none; }
  /* Tight transport — drop the extra-large gaps and let buttons shrink
     so the playhead time stays visible on a phone instead of being
     pushed off the right edge. */
  .transport { gap: 8px; padding-left: 10px; padding-right: 10px; }
  .transport .play, .transport .add-marker { width: 40px; height: 40px; }
  .loop-controls button { width: 28px; height: 28px; padding: 0; }
  .loop-status { display: none; }
  /* The track-header meta line on the track page — long titles + many
     meta chips would otherwise overflow. */
  .track-header { padding: 12px 16px 8px; }
  .track-header .title { font-size: 18px; line-height: 1.2; }
  .track-header .meta { gap: 8px; flex-wrap: wrap; }
  /* Topbar — every icon-btn is 32×32 + 6 px gaps; with five action
     buttons + brand + badges that's still too much for a 375 px
     viewport. Drop the secondary icons (shortcuts, export) entirely
     on phones — both are reachable elsewhere (? key / marker sheet)
     and the trash + share + edit trio is what users actually need
     within thumb-reach. */
  .topbar { padding-left: 12px; padding-right: 12px; gap: 6px; }
  .topbar .icon-btn { width: 36px; height: 36px; }
  .topbar .icon-btn svg { width: 18px; height: 18px; }
  .topbar .brand { font-size: 12px; }
  .topbar #export-btn,
  .topbar #shortcuts-btn { display: none; }
  /* Compare-row buttons need to wrap on narrow screens; the Listen
     pill stays prominent. */
  .compare-row { padding: 6px 10px; }
}
@media (max-width: 380px) {
  /* Smallest phones — drop the tier badge text too. The track page's
     tier info isn't actionable for the owner mid-review. */
  .topbar #tier-badge { display: none; }
  .topbar .icon-btn { width: 34px; height: 34px; }
  .topbar .icon-btn svg { width: 17px; height: 17px; }
  .topbar { gap: 4px; padding-left: 10px; padding-right: 10px; }
}

/* Bottom sheet */
.sheet-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,0.55);
  opacity: 0; pointer-events: none; transition: opacity 0.18s;
  z-index: 40;
}
.sheet-backdrop.show { opacity: 1; pointer-events: auto; }
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0;
  background: var(--surface);
  border-top: 1px solid var(--border);
  transform: translateY(100%);
  transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.2, 1);
  z-index: 41;
  padding: 18px 16px calc(18px + env(safe-area-inset-bottom));
  max-height: 80dvh; overflow-y: auto;
}
.sheet.show { transform: translateY(0); }
.sheet .sheet-head {
  display: flex; align-items: center; gap: 10px; margin-bottom: 14px;
}
.sheet .sheet-head .label { flex: 1; }
.sheet textarea {
  width: 100%; min-height: 100px; resize: vertical;
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 12px; font-family: var(--font-sans);
}
.sheet textarea.locked {
  color: var(--text-dim); cursor: not-allowed;
  background: var(--surface);
}
.guest-lock-note {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
  color: var(--text-dim); text-transform: uppercase;
  border: 1px dashed var(--border);
  padding: 8px 10px; margin-bottom: 10px;
  line-height: 1.4;
}
.sheet .form-block {
  display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px;
}
.sheet .form-block input[type=text] {
  width: 100%; background: var(--surface-2); border: 1px solid var(--border);
  color: inherit; font: inherit; padding: 10px 12px; outline: none;
}
.sheet .form-block input[type=text]:focus,
.sheet .form-block input[type=number]:focus { border-color: var(--accent); }
.sheet .form-block input[type=number] {
  width: 100%; background: var(--surface-2); border: 1px solid var(--border);
  color: inherit; font: inherit; padding: 10px 12px; outline: none;
}
.sheet .form-block.form-row {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
}
.form-col { display: flex; flex-direction: column; gap: 6px; }
.form-inline {
  display: flex; align-items: center; gap: 6px;
}
.form-inline input[type=number] { flex: 1; min-width: 0; }

/* BPM pill in the track header */
.bpm-pill {
  display: inline-flex; align-items: center; justify-content: center;
  height: 20px; padding: 0 8px;
  border: 1px solid var(--accent);
  color: var(--accent);
  font-family: var(--font-mono); font-size: 10px; line-height: 1;
  letter-spacing: 0.12em; text-transform: uppercase;
}

/* Audio-quality pill in the transport bar */
.quality-pill {
  background: transparent; border: 1px solid var(--border-soft);
  color: var(--text-faint);
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: 4px 8px; min-height: 22px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  white-space: nowrap;
}
.quality-pill:hover { color: var(--text); border-color: var(--text-dim); }

/* Upload .asd picker row */
.asd-picker {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.asd-picker .filename { font-size: 11px; }

/* Voice recorder embedded in the comment sheet */
.recorder {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  margin-top: 12px;
}
.recorder .rec-btn {
  width: 40px; height: 40px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  color: var(--text);
}
.recorder.recording .rec-btn {
  background: var(--danger); color: #0a0a0a; border-color: var(--danger);
  animation: pulse 1s ease-in-out infinite;
}
.recorder .rec-meta {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 11px; color: var(--text-dim);
  letter-spacing: 0.12em; text-transform: uppercase;
}
.recorder .rec-meta .time {
  display: block; color: var(--text); font-size: 13px; margin-bottom: 2px; letter-spacing: 0.06em;
}
.recorder .rec-discard {
  width: 32px; height: 32px;
  background: transparent; border: 1px solid var(--border);
  color: var(--text-dim);
  display: inline-flex; align-items: center; justify-content: center;
}
.recorder .rec-discard:hover { color: var(--danger); border-color: var(--danger); }

@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 85, 98, 0.6); }
  50%      { box-shadow: 0 0 0 6px rgba(255, 85, 98, 0); }
}

.recorder.unsupported { opacity: 0.5; }
.recorder.unsupported .rec-btn { background: var(--surface); cursor: not-allowed; }

/* Existing voice slot in the marker-edit sheet — appears only when the
   marker being edited already has a voice attached. Lets the user replay,
   delete, or overwrite (by recording a new note in the recorder below). */
.existing-voice {
  border: 1px solid var(--border);
  background: var(--surface-2);
  padding: 10px 12px;
  margin-top: 10px;
  display: flex; flex-direction: column; gap: 8px;
}
.existing-voice .label { margin: 0; }
.existing-voice .voice-row {
  margin-top: 0;
  background: var(--surface);
}
.existing-voice .btn.sm { align-self: flex-start; color: var(--danger); border-color: var(--border); }
.existing-voice .btn.sm:hover { border-color: var(--danger); }

.recorder.locked { position: relative; }
.recorder.locked .rec-btn { background: var(--surface); cursor: not-allowed; color: var(--text-faint); }
.recorder.locked .rec-meta { color: var(--text-faint); }
.pro-lock-badge {
  font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.18em;
  color: var(--text-dim); border: 1px solid var(--border);
  padding: 2px 6px; text-transform: uppercase;
  cursor: pointer; background: transparent;
  white-space: nowrap;
}
.pro-lock-badge:hover { background: var(--accent); color: #0a0a0a; border-color: var(--accent); }

/* Tier badge in topbar */
.tier-badge {
  display: inline-flex; align-items: center; justify-content: center;
  height: 32px; padding: 0 14px;
  font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  letter-spacing: 0.18em;
  text-decoration: none; text-transform: uppercase;
  border: 1px solid var(--border);
}
.tier-badge.pro { background: var(--accent); color: #0a0a0a; border-color: var(--accent); }
.tier-badge.free { color: var(--text-dim); }
.tier-badge.free:hover { color: var(--accent); border-color: var(--accent); }

/* Quota line under track list / inline */
.quota {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em;
  color: var(--text-dim); text-transform: uppercase;
  margin: 8px 0 4px;
}
.quota.warn { color: var(--warn); }
.quota.over { color: var(--danger); }
.quota a { text-decoration: underline; }

/* Account page */
.account-wrap {
  max-width: 600px; margin: 16px auto;
  padding: 16px;
  padding-bottom: calc(40px + env(safe-area-inset-bottom));
}
.acc-section {
  border-top: 1px solid var(--border);
  padding: 22px 0 18px;
}
.acc-section:first-of-type { border-top: 0; }
.acc-form {
  display: flex; flex-direction: column; gap: 12px;
  max-width: 360px;
}
.acc-form-row {
  display: flex; gap: 8px;
  margin-bottom: 8px;
}
.acc-form-row input { flex: 1; min-width: 0; }
.kv {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 0; margin-bottom: 14px;
  border-bottom: 1px solid var(--border-soft);
}
.kv-key {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-dim);
  min-width: 80px;
}
.kv-val { color: var(--text); font-size: 13px; }

/* Friend list rows */
.friend-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border-soft);
}
.friend-info { flex: 1; min-width: 0; }
.friend-info .t1 { font-weight: 600; font-size: 14px; }
.friend-info .t2 {
  font-size: 11px; color: var(--text-dim);
  margin-top: 2px;
  letter-spacing: 0.06em;
  word-break: break-all;
}
.friend-actions { display: flex; gap: 6px; flex-shrink: 0; }

/* Billing page */
.billing-wrap {
  max-width: 580px; margin: 24px auto; padding: 24px;
}
.plan-card {
  border: 1px solid var(--border); background: var(--surface);
  padding: 22px; margin-bottom: 14px;
}
.plan-card.current {
  border-color: var(--accent);
  background: linear-gradient(180deg, rgba(200,255,0,0.05), transparent 80%), var(--surface);
}
.plan-card .plan-name {
  font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 0.16em;
  font-size: 13px; color: var(--text-dim);
}
.plan-card .plan-price {
  font-size: 28px; font-weight: 700; margin: 6px 0 14px;
}
/* Plan features share the typography of the upgrade-sheet benefits so
   the marketing surface and the upsell sheet read as the same family. */
.plan-card .plan-features {
  list-style: none; padding: 0; margin: 0 0 18px;
  display: flex; flex-direction: column; gap: 6px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.04em;
}
.plan-card .plan-features li {
  color: var(--text);
  padding-left: 12px;
  border-left: 1px solid var(--border);
}
.plan-card .plan-features li.off { color: var(--text-faint); text-decoration: line-through; }
.sheet .sheet-actions { display: flex; gap: 10px; margin-top: 14px; }
.sheet .sheet-actions .btn { flex: 1; }

/* Range marker overlay on the waveform — a thin tinted band along the
   top of the wave area rather than a full-height frame, so the peaks
   stay readable and the visualisation matches the lightweight pin
   stems. The start- and end-pins still mark the exact boundaries. */
.range-overlay {
  position: absolute; top: 3px; height: 4px;
  background: rgba(122, 217, 255, 0.55);
  /* Receives hover so the wave→list highlight cross-link works on
     range markers. Scrub gestures still work via the delegated
     pointer handlers on the wave container. */
  pointer-events: auto;
  cursor: inherit;
}
.range-overlay.done { background: rgba(255, 255, 255, 0.18); }
.range-overlay[style*="--author-color"] {
  /* tinting via the author colour when present */
  background: color-mix(in srgb, var(--author-color, #7ad9ff) 55%, transparent);
}

/* Range markers: the 10 px top band + the two pin caps already mark
   start and end clearly. Hiding the full-height stems on both ends
   stops the visualisation from looking like an unclosed three-sided
   frame around the waveform. The cap stays solid (same shape as the
   point-marker cap, just clamped to the start / end position) so it
   still anchors visually. */
.pin.range-start,
.pin.range-end {
  background: transparent;
  bottom: auto;
  /* Just tall enough for the 10 px cap to show; no stem bleeding
     down into the wave peaks. */
  height: 11px;
}
/* Private range markers carry the dashed-gradient background — clear
   it the same way as the solid stem so the dashes don't shine through
   along the wave. */
.pin.range-start.private,
.pin.range-end.private {
  background: none;
}

/* Loop region — coloured differently from range markers so the two
   never get confused visually. */
.loop-overlay {
  position: absolute; top: 0; bottom: 16px;
  background: rgba(200, 255, 0, 0.06);
  border-left: 2px solid var(--accent);
  border-right: 2px solid var(--accent);
  pointer-events: none;
}
.loop-pin {
  position: absolute; top: 0; bottom: 0; width: 0;
  border-left: 2px solid var(--accent);
  pointer-events: none;
}
.loop-pin::after {
  content: ""; position: absolute; top: 0; left: -4px;
  width: 8px; height: 4px; background: var(--accent);
}

/* Loop controls in the transport bar */
.loop-controls {
  display: flex; gap: 6px;
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.08em;
}
.loop-controls button {
  width: 32px; height: 32px;
  border: 1px solid var(--border); background: var(--surface-2);
  color: var(--text-dim);
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
}
.loop-controls button.active { border-color: var(--accent); color: var(--accent); }
.loop-controls button:hover { color: var(--accent); border-color: var(--accent); }
.loop-status {
  font-family: var(--font-mono); font-size: 10px; color: var(--text-dim);
  letter-spacing: 0.08em; padding: 6px 10px;
  align-self: center;
  white-space: nowrap;
  text-transform: uppercase;
  border: 1px solid transparent;
  cursor: default;
}
/* Loop is armed (in OR out set) → status reads as a real button you can
   tap to clear. Visual hint: hairline border + cursor. */
.loop-status.armed {
  border-color: var(--border);
  cursor: pointer;
  color: var(--text);
}
.loop-status.armed:hover { border-color: var(--danger); color: var(--danger); }
.loop-status.active { color: var(--accent); border-color: var(--border); cursor: pointer; }
.loop-status.active:hover { border-color: var(--danger); color: var(--danger); }
.loop-status .clear-x {
  display: inline-block; margin-left: 6px;
  color: var(--text-faint);
}
.loop-status:hover .clear-x { color: inherit; }

/* Visibility toggle in marker sheet */
.vis-row {
  display: flex; align-items: center; gap: 10px;
  margin-top: 10px; padding: 8px 10px;
  border: 1px solid var(--border);
  background: var(--surface-2);
}
.vis-row .vis-label {
  flex: 1;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-dim);
}
.vis-row .vis-toggle {
  display: inline-flex; border: 1px solid var(--border);
}
.vis-row .vis-toggle button {
  padding: 5px 10px; min-height: 28px;
  background: transparent; border: 0;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-dim);
  border-left: 1px solid var(--border-soft);
}
.vis-row .vis-toggle button:first-child { border-left: 0; }
.vis-row .vis-toggle button.active { background: var(--accent); color: #0a0a0a; }

/* Active range editor inside the marker sheet. The end-time input lets
   the user dial in the exact range stop without having to scrub the
   playhead, and the "↺ Playhead" button snaps it to the current audio
   position for the common "play, hear where to stop, tap" workflow. */
.range-end-controls {
  display: inline-flex; align-items: center; gap: 6px;
}
.range-end-controls .mono.dim {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-dim);
}
.vis-row .range-end-input {
  width: 84px;
  padding: 4px 8px;
  background: var(--surface); border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 12px; color: var(--text);
}
.vis-row .range-end-input:focus { border-color: var(--accent); outline: 0; }
.vis-row .range-end-input.invalid { border-color: var(--danger); }

/* Share dialog */
.share-block {
  border: 1px solid var(--border); padding: 14px;
  background: var(--surface); margin-top: 8px;
}
.share-link {
  font-family: var(--font-mono); font-size: 12px;
  background: var(--surface-2); padding: 10px; border: 1px solid var(--border-soft);
  word-break: break-all; user-select: all;
  margin-top: 6px;
}
.share-block .label { margin-bottom: 6px; display: block; }
.share-block .vis-row-spaced { margin-top: 10px; margin-bottom: 0; }
.share-block .fineprint { margin-top: 6px; }
.share-block .share-actions {
  display: flex; gap: 8px; margin-top: 12px;
}

/* Toast */
.toast {
  position: fixed; left: 50%; bottom: calc(var(--transport-h) + 14px);
  transform: translateX(-50%) translateY(20px);
  background: var(--surface-3); border: 1px solid var(--border);
  padding: 10px 14px; font-family: var(--font-mono);
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  opacity: 0; transition: all 0.18s; z-index: 60;
  pointer-events: none;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.err { border-color: var(--danger); color: var(--danger); }
