/* OrbKord — Glacier.
   An instrument panel, not a dashboard. Structure comes from tone, spacing and
   alignment; a border only appears where two surfaces actually meet.

   All hues live in the :root / body.light blocks. The accent also lives in
   js/renderer.js THEMES and js/fretboard.js FALLBACK and must move with them.

   The accent means one thing: live or armed. Sounding keys, the playhead, a
   toggle that is on, the one primary action of a section. Never decoration. */

/* SMuFL music font, for microtonal accidentals (js/smufl.js). Shipped with the
   app, never taken from the OS, so the staff is the same on every machine.
   Bravura is SIL OFL 1.1, licence beside the font. font-display: block,
   because a fallback face has no glyph at these codepoints and would flash a
   box. Nothing downloads until a glyph is actually drawn. */
@font-face {
  font-family: "Bravura";
  src: url("../assets/fonts/bravura/Bravura.woff2") format("woff2");
  font-weight: normal;
  font-style: normal;
  font-display: block;
}
/* 1em = four staff spaces, origin on the note. In running text, size it with
   font-size. <smufl-glyph> carries this class. */
.smufl-font {
  font-family: "Bravura";
  font-weight: normal;
  font-style: normal;
  font-synthesis: none;
  line-height: 1;
  text-transform: none;
  letter-spacing: 0;
}

:root {
  /* Surfaces, darkest to lightest. --bg is shared with the canvas (renderer
     THEMES.dark.bg) so the stage and the workspace are one surface. */
  --bg: #0b0d11;
  --bg-bar: #111419;
  --surface: #1b1f27;          /* raised caps: buttons */
  --surface-hi: #232833;
  --well: #080a0d;             /* recessed: selects, slider tracks, segments */
  --line: #262b35;             /* a real edge between two surfaces */
  --line-soft: #1b1f27;        /* hairline dividers */

  --text: #bcc1cb;
  --text-hi: #eef1f5;
  --text-dim: #808797;         /* labels: 4.9:1 on --bg-bar */
  --text-faint: #5b6271;       /* hints only, never the sole carrier of meaning */

  /* Glacier, hsl(188 68% 62%). Held under 80% saturation on purpose. */
  --accent: #5bd1e0;
  --accent-deep: #2e9cad;
  --accent-soft: rgba(91, 209, 224, .12);
  --accent-line: rgba(91, 209, 224, .38);
  --accent-glow: rgba(91, 209, 224, .45);
  --accent-ink: #04222b;       /* text on a solid accent fill */
  --danger: #ff5a72;
  --danger-soft: rgba(255, 90, 114, .12);

  /* Radius encodes role: pill = action, ctl = chooser, card = container. */
  --r-pill: 999px;
  --r-ctl: 8px;
  --r-card: 12px;

  --h-ctl: 30px;               /* one control height in the bars */
  --h-side: 32px;              /* a touch taller in the inspector */

  /* One light source, overhead. Shadows are tinted to the background hue. */
  /* Depth comes from the surface ladder plus a hairline edge and a lit top
     edge, never from a drop shadow (Raycast / Linear dark systems). */
  --cap: inset 0 1px 0 rgba(255, 255, 255, .05), inset 0 0 0 1px rgba(255, 255, 255, .035);
  /* Focus: a 2px accent ring held back to ~60% so it guides, not shouts. */
  --focus: color-mix(in srgb, var(--accent) 62%, transparent);
  --sink: inset 0 1px 2px rgba(0, 0, 0, .55);
  --shadow-pop: 0 18px 44px rgba(3, 6, 12, .6);

  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

body.light {
  --bg: #eceff3;
  --bg-bar: #f8f9fb;
  --surface: #ffffff;
  --surface-hi: #f3f5f8;
  --well: #e4e8ee;
  --line: #d4dae2;
  --line-soft: #e3e7ed;

  --text: #373c47;
  --text-hi: #0f1218;
  --text-dim: #626978;
  --text-faint: #939aa8;

  --accent: #2a93a5;
  --accent-deep: #1d7181;
  --accent-soft: rgba(42, 147, 165, .11);
  --accent-line: rgba(42, 147, 165, .45);
  --accent-glow: rgba(42, 147, 165, .35);
  --accent-ink: #ffffff;
  --focus: color-mix(in srgb, #2a93a5 70%, transparent);
  --danger: #d8344f;
  --danger-soft: rgba(216, 52, 79, .1);

  --cap: inset 0 1px 0 rgba(255, 255, 255, .9), 0 0 0 1px rgba(25, 40, 60, .09), 0 1px 2px rgba(25, 40, 60, .1);
  --sink: inset 0 1px 2px rgba(30, 45, 65, .14);
  --shadow-pop: 0 18px 44px rgba(20, 40, 60, .18);
}

/* Native dropdown lists, scrollbars and checkboxes follow the theme too. */
:root { color-scheme: dark; }
:root:has(body.light) { color-scheme: light; }

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 13px;
  /* Note names, BPMs, split points and velocities change constantly; tabular
     figures stop them jittering as they do. */
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

button, select, input, label, .btn { touch-action: manipulation; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ------------------------------------------------- Icons */
.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.ico {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
}
.btn-label { line-height: 1; }

/* Status LED: the one place the accent is allowed to glow. */
.led {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: var(--text-faint);
  transition: background-color .2s var(--ease), box-shadow .2s var(--ease);
}
.btn.on .led { background: var(--accent); box-shadow: 0 0 7px var(--accent-glow); }

kbd {
  display: inline-block;
  min-width: 18px;
  padding: 1px 5px;
  border-radius: 4px;
  background: linear-gradient(180deg, var(--surface-hi), var(--surface));
  box-shadow: var(--cap);
  color: var(--text);
  font: 500 11px/16px var(--font);
  text-align: center;
}

/* ================================================= Controls */

/* Action: a raised cap. No outline; the cap's tone and its top highlight
   separate it from the bar. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: var(--h-ctl);
  padding: 0 13px;
  background: var(--surface);
  color: var(--text);
  border: 0;
  border-radius: var(--r-pill);
  box-shadow: var(--cap);
  font: 500 12.5px/1 var(--font);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: background-color .16s var(--ease), color .16s var(--ease),
              box-shadow .16s var(--ease), transform .08s var(--ease);
}
.btn:hover:not(:disabled) { background: var(--surface-hi); color: var(--text-hi); }
.btn:active:not(:disabled) { transform: translateY(1px); box-shadow: var(--sink); }
.btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.btn:disabled { opacity: .38; cursor: default; }

/* Primary action of its group: tinted, never a slab of cyan. */
.btn.accent {
  color: var(--accent);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.btn.accent:hover:not(:disabled) { color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent); }

/* A toggle that is on. */
.btn.on {
  color: var(--accent);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.btn.on:hover:not(:disabled) { color: var(--accent); }

.btn { position: relative; }
.btn.rec {
  color: var(--danger);
  background: var(--danger-soft);
  box-shadow: inset 0 0 0 1px var(--danger);
}
/* Pulses animate opacity only (compositor-friendly), on an overlay. */
.btn.rec::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--danger);
  opacity: 0;
  pointer-events: none;
  animation: pulse-o 1.2s ease-in-out infinite;
}
@keyframes pulse-o { 50% { opacity: .16; } }
/* A select cannot host a pseudo-element, so a busy chooser breathes whole. */
.btn.busy {
  color: var(--accent);
  pointer-events: none;
  animation: busy-o 1.2s ease-in-out infinite;
}
@keyframes busy-o { 50% { opacity: .55; } }

/* Round: icon-only transport and utility buttons. The label stays in the DOM
   (setBtn() rewrites it, screen readers read it) but is not drawn. */
.btn.round {
  width: var(--h-ctl);
  padding: 0;
}
.btn.round .btn-label,
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Chooser: a recessed well with a squarer radius, so a dropdown never reads
   as a button. */
select.btn {
  appearance: none;
  -webkit-appearance: none;
  justify-content: flex-start;
  padding: 0 28px 0 10px;
  border-radius: var(--r-ctl);
  color: var(--text-hi);
  background-color: var(--well);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='9' height='6' viewBox='0 0 9 6'><path d='M1 1l3.5 3.5L8 1' fill='none' stroke='%23808797' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  box-shadow: var(--sink);
  font-weight: 450;
  text-overflow: ellipsis;
  overflow: hidden;
  min-width: 0;
}
/* The chevron is a data URI, so it cannot read a CSS variable. Restated. */
body.light select.btn {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='9' height='6' viewBox='0 0 9 6'><path d='M1 1l3.5 3.5L8 1' fill='none' stroke='%23626978' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}
select.btn:hover:not(:disabled) { background-color: var(--well); box-shadow: var(--sink), inset 0 0 0 1px var(--line); }
select.btn:active:not(:disabled) { transform: none; box-shadow: var(--sink); }
/* Explicit list colours: Windows dark mode otherwise paints its own. */
select.btn optgroup { background: var(--bg-bar); color: var(--text-dim); font-weight: 600; }
select.btn option { background: var(--bg-bar); color: var(--text-hi); }

/* Segmented control: a well housing caps; the selected cap rises out of it. */
.seg {
  display: flex;
  padding: 2px;
  gap: 2px;
  background: var(--well);
  border-radius: var(--r-ctl);
  box-shadow: var(--sink);
}
.seg-btn {
  flex: 1;
  height: calc(var(--h-side) - 4px);
  padding: 0 10px;
  background: none;
  border: 0;
  border-radius: 6px;
  color: var(--text-dim);
  font: 500 12.5px/1 var(--font);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .16s var(--ease), color .16s var(--ease);
}
.seg-btn:hover { color: var(--text-hi); }
.seg-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.seg-btn.on {
  background: var(--surface-hi);
  color: var(--text-hi);
  box-shadow: var(--cap);
}

/* ------------------------------------------------- Range sliders */
/* Tracks are wells; the travelled part lights in the accent. WebKit cannot
   read the value from the track, so paintRange() mirrors it onto --fill. */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  height: 20px;
  background: transparent;
  cursor: pointer;
  --fill: 0;          /* 0..1, kept in sync by paintRange() */
  --thumb: 14px;
  /* The colour break follows the thumb's centre, which travels between half
     a thumb from each end. */
  --stop: calc(var(--thumb) / 2 + var(--fill) * (100% - var(--thumb)));
}
input[type="range"]:disabled { opacity: .4; cursor: default; }
input[type="range"]:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 4px; }
input[type="checkbox"]:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    var(--accent) 0 var(--stop), var(--well) var(--stop) 100%);
  box-shadow: var(--sink);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px; height: 14px; border-radius: 50%;
  margin-top: -5px;
  background: var(--text-hi);
  border: 0;
  box-shadow: 0 1px 3px rgba(3, 6, 12, .6), inset 0 -1px 0 rgba(0, 0, 0, .12);
  transition: transform .12s var(--ease);
}
body.light input[type="range"]::-webkit-slider-thumb {
  background: #fff;
  box-shadow: 0 0 0 1px rgba(25, 40, 60, .16), 0 1px 3px rgba(25, 40, 60, .25);
}
input[type="range"]:hover:not(:disabled)::-webkit-slider-thumb { transform: scale(1.12); }
input[type="range"]:active:not(:disabled)::-webkit-slider-thumb { transform: scale(.94); }

input[type="range"]::-moz-range-track { height: 4px; border-radius: 2px; background: var(--well); }
input[type="range"]::-moz-range-progress { height: 4px; border-radius: 2px; background: var(--accent); }
input[type="range"]::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 50%; border: 0;
  background: var(--text-hi);
  box-shadow: 0 1px 3px rgba(3, 6, 12, .6);
}

input[type="checkbox"] {
  accent-color: var(--accent);
  width: 14px; height: 14px;
}

/* ================================================= App header */
.appbar {
  flex-shrink: 0;
  background: var(--bg-bar);
  border-bottom: 1px solid var(--line-soft);
  position: relative;
  z-index: 20;               /* the login dropdown must sit over the stage */
}

.bar {
  display: flex;
  align-items: center;
  /* One line at every laptop width: the seek bar and the selects give up
     width first (below). Wrapping is only allowed on small screens, because
     flex-wrap breaks a line before anything has had the chance to shrink. */
  flex-wrap: nowrap;
  column-gap: 20px;
  row-gap: 8px;
  padding: 0 16px;
  min-width: 0;
}
.bar-primary { min-height: 52px; padding-top: 10px; padding-bottom: 10px; }
.bar-context {
  min-height: 44px;
  padding-top: 7px;
  padding-bottom: 7px;
  border-top: 1px solid var(--line-soft);
}
.bar-spacer { flex: 1 1 0; min-width: 0; }

.brand {
  font: inherit;
  display: flex;
  align-items: center;
  gap: 8px;
  padding-right: 6px;
  color: var(--text-hi);
}
.brand-mark { width: 20px; height: 20px; color: var(--accent); }
.brand-name { font-size: 15px; font-weight: 650; letter-spacing: -.01em; }

.grp {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
/* A context group reads "Label  [control] [control]". Sentence case, no
   tracking: a label, not a heading. */
.grp-label {
  letter-spacing: .01em;
  margin-right: 4px;
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}
/* Hairline between context groups, drawn only where a group follows another
   on the same line of intent. */
.bar-context .grp + .grp::before {
  content: '';
  width: 1px;
  height: 16px;
  margin-right: 14px;
  background: var(--line);
}

/* Transport: the playhead is the one elastic control. */
.grp-transport { flex: 1 1 440px; max-width: 640px; }
.transport-play:not(:disabled) { color: var(--text-hi); }
#seek { flex: 1 1 260px; min-width: 90px; margin: 0 6px; }
#rate { width: 66px; flex: 0 0 auto; }

#key-select { width: 166px; }
#split-mode { width: 136px; }
#split-point { width: 78px; }
#sound-select { width: 136px; }
#pitch-system { width: 116px; }
.bar-context select.btn { flex: 0 1 auto; min-width: 70px; }
.grp-video, .tb-account, .brand, .grp-source { flex-shrink: 0; }
/* Toggles keep their size, the selects beside them give way instead. A
   shrunk toggle group just spills its last button past the bar's edge. */
.grp-view { flex-shrink: 0; }

.knob-row {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 6px;
}
.knob-label { color: var(--text-dim); font-size: 12px; }
#master-volume, #reverb-amount { width: 72px; flex: 0 0 auto; }

/* ------------------------------------------------- Auth (top bar) */
.tb-account { display: flex; align-items: center; min-width: 0; }
.tb-account:has(#auth-box:empty) { display: none; }

#auth-box {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  max-width: 100%;
}
#auth-box .auth-email {
  font-size: 12.5px; color: var(--text-dim); max-width: 180px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Plan badge: a label, so it is square-cornered and quiet. */
#auth-box .auth-trial {
  font-size: 10.5px; font-weight: 600; letter-spacing: .04em; color: var(--text);
  background: var(--surface);
  border-radius: 4px;
  padding: 3px 6px; white-space: nowrap;
}
#auth-box .auth-note { font-size: 12px; color: var(--text-dim); }

/* Login / sign-up dropdown panel */
.auth-panel {
  position: absolute; top: calc(100% + 12px); right: 0; z-index: 200;
  width: 300px; display: flex; flex-direction: column; gap: 10px;
  padding: 18px; background: var(--bg-bar);
  border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--shadow-pop);
  cursor: default; text-align: left;
  animation: auth-pop .12s ease-out;
}
@keyframes auth-pop { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.auth-panel-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: 2px; }
.auth-title { font-size: 15px; font-weight: 650; color: var(--text-hi); }
.auth-sub { font-size: 12.5px; color: var(--text-dim); }

.auth-input {
  width: 100%; padding: 10px 12px;
  background: var(--well); color: var(--text-hi);
  border: 1px solid var(--line); border-radius: var(--r-ctl);
  box-shadow: var(--sink);
  font-family: inherit; font-size: 13px; outline: none;
  transition: border-color .2s var(--ease);
}
.auth-input::placeholder { color: var(--text-dim); }
.auth-input:focus-visible { border-color: var(--accent); box-shadow: var(--sink), 0 0 0 3px var(--accent-soft); }

.auth-primary { justify-content: center; width: 100%; height: 36px; font-size: 13px; }

.auth-links { display: flex; justify-content: space-between; gap: 8px; }
.auth-link {
  background: none; border: none; padding: 2px 0; cursor: pointer;
  font-family: inherit; font-size: 12.5px; color: var(--text-dim); text-decoration: none;
}
.auth-link:hover { color: var(--accent); }

.auth-divider {
  display: flex; align-items: center; gap: 10px;
  color: var(--text-dim); font-size: 12px;
}
.auth-divider::before, .auth-divider::after {
  content: ''; flex: 1; height: 1px; background: var(--line-soft);
}

.auth-google { justify-content: center; width: 100%; height: 36px; font-size: 12.5px; }

.auth-msg {
  font-size: 12.5px; line-height: 1.4; padding: 8px 10px; border-radius: 8px;
  border: 1px solid transparent;
}
.auth-msg-error { color: #ff9b9b; background: #2a1518; border-color: #5a2a2f; }
.auth-msg-ok    { color: #9be7c4; background: #10251c; border-color: #205a44; }
.auth-msg-info  { color: var(--text); background: var(--surface); border-color: var(--line); }
body.light .auth-msg-error { color: #a11f2a; background: #fdecee; border-color: #f3c2c8; }
body.light .auth-msg-ok    { color: #1a7a4f; background: #e7f7ee; border-color: #b6e2c9; }

/* ================================================= Workspace */
.workspace {
  display: flex;
  flex: 1;
  width: 100%;
  min-height: 0;
  overflow: hidden;
  position: relative;   /* anchors the access-gate overlay */
}

/* ------------------------------------------------- Sidebar: an inspector */
.sidebar {
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  width: 284px;
  min-width: 284px;
  background: var(--bg-bar);
  border-right: 1px solid var(--line-soft);
  padding: 14px 18px 20px;
  overflow-y: auto;
  flex-shrink: 0;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.sidebar::-webkit-scrollbar { width: 8px; }
.sidebar::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }

.sidebar [hidden] { display: none !important; }

/* The mode switch heads the harmoniser; its sections follow directly. */
.seg-mode { margin: 2px 0 14px; }
.seg-mode .seg-btn.on { color: var(--accent); }

/* Sections are separated by one hairline and air, not by boxes. */
.insp {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 0;
  border-top: 1px solid var(--line-soft);
}
/* The harmoniser section sits right under the mode switch it belongs to. */
.seg-mode + .insp,
.seg-mode + .insp + .insp { border-top: 0; padding-top: 0; }
.insp-guitar { border-top: 0; padding-top: 2px; margin-bottom: 14px; padding-bottom: 18px; border-bottom: 1px solid var(--line-soft); }
.insp-last { padding-bottom: 0; }

.insp-title {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-hi);
  margin-bottom: 2px;
}

/* Label-left rows: the eye scans one column of names, then one of values. */
.row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
}
.row-label {
  font-size: 12.5px;
  color: var(--text-dim);
  white-space: nowrap;
}
.row > select.btn,
.row > .seg { width: 100%; }
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; min-width: 0; }
.pair > select.btn { width: 100%; padding: 0 22px 0 9px; background-position: right 8px center; }

.sidebar .btn,
.sidebar .seg-btn { font-size: 12.5px; }
.sidebar .btn { height: var(--h-side); }
.sidebar .btn.block { width: 100%; justify-content: center; }
/* The one thing each section is for. */
.sidebar .btn.primary { height: 36px; font-size: 13px; font-weight: 600; }
.sidebar .btn.primary + .btn.block { margin-top: -2px; }
/* Armed / recording: the tint deepens and the ring closes, so "on" is
   visible at a glance and not only through the LED. */
.sidebar .btn.primary.on {
  background: color-mix(in srgb, var(--accent) 24%, transparent);
  box-shadow: inset 0 0 0 1px var(--accent);
  color: var(--text-hi);
}

.slider-row {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 36px;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  color: var(--text-dim);
}
.slider-row .end:last-child { text-align: right; }
.slider-row .val { color: var(--text-hi); font-weight: 500; }
.slider-row input[type="range"] { width: 100%; min-width: 0; }

.sub { display: flex; flex-direction: column; gap: 6px; }
.sub + .sub { margin-top: 6px; }
.sub-label { font-size: 12.5px; color: var(--text); }

.check-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; color: var(--text); cursor: pointer;
  min-height: 22px;
}
.check-row:has(input:disabled) { opacity: .4; cursor: default; }

/* ------------------------------------------------- Stage */
/* The canvas IS the workspace. Its background is the same colour, so the
   16:9 letterbox is invisible and there is no card-inside-a-panel frame. */
.stage-wrap {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 12px;
  min-height: 0;
  min-width: 0;
  background: var(--bg);
}

#stage {
  display: block;
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 16 / 9;
  background: var(--bg);
}

/* ------------------------------------------------- Status bar */
.statusbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 30px;
  padding: 4px 16px;
  background: var(--bg-bar);
  border-top: 1px solid var(--line-soft);
  font-size: 12px;
  color: var(--text-dim);
  flex-shrink: 0;
}
#midi-status {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--text); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
#midi-status::before {
  content: '';
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-faint);
  flex: 0 0 auto;
}
.midi-in { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
#midi-input { height: 22px; padding: 0 10px; font-size: 12px; max-width: 240px; overflow: hidden; text-overflow: ellipsis; }
#midi-input[hidden] { display: none; }
.hint { text-align: right; white-space: nowrap; }

/* ================================================= Access gate (trial/paywall) */
/* Covers the workspace but NOT the header, so the login dropdown stays
   reachable. auth.js creates/updates #app-gate. */
.app-gate {
  position: absolute;
  inset: 0;
  z-index: 15;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(10, 11, 14, .72);   /* fallback */
  background: color-mix(in srgb, var(--bg) 76%, transparent);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
}
.app-gate[hidden] { display: none; }

.gate-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 360px;
  max-width: calc(100vw - 32px);
  padding: 30px 28px;
  background: var(--bg-bar);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow-pop);
  text-align: center;
}
.gate-logo { font-size: 12px; font-weight: 700; letter-spacing: .24em; color: var(--accent); }
.gate-title { font-size: 19px; font-weight: 650; color: var(--text-hi); text-wrap: balance; }
.gate-sub { font-size: 13px; line-height: 1.5; color: var(--text-dim); text-wrap: pretty; }
.gate-cta { justify-content: center; width: 100%; height: 40px; font-size: 14px; }
.gate-note { font-size: 12px; color: var(--text-dim); }

/* ================================================= Air Brass */
.breath-modal {
  overscroll-behavior: contain;
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(10, 11, 14, .72);
  background: color-mix(in srgb, var(--bg) 76%, transparent);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
}
.breath-modal[hidden] { display: none; }

/* The QR sits on white in both themes for scan contrast. */
.breath-qr {
  width: 208px;
  height: 208px;
  padding: 12px;
  border-radius: 12px;
  background: #fff;
}
.breath-qr svg { width: 100%; height: 100%; display: block; }

.breath-status { font-size: 13px; color: var(--text); min-height: 18px; }
.breath-status.ok  { color: #58d996; }
.breath-status.err { color: #ff9b9b; }
body.light .breath-status.ok  { color: #1a7a4f; }
body.light .breath-status.err { color: #a11f2a; }

.breath-actions { display: flex; gap: 8px; }

.breath-settings {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  padding-top: 12px;
  border-top: 1px solid var(--line-soft);
}
.breath-row {
  display: grid;
  grid-template-columns: 52px 1fr 54px;
  align-items: center;
  gap: 10px;
  font-size: 12.5px;
  color: var(--text-dim);
}
.breath-row b { font-weight: 600; color: var(--text-hi); text-align: right; }

/* Header pill: live breath meter + link-state dot (click reopens the QR). */
.breath-pill {
  border: 0;
  font: inherit;
  color: inherit;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: var(--h-ctl);
  padding: 0 10px;
  border-radius: var(--r-pill);
  background: var(--well);
  box-shadow: var(--sink);
  cursor: pointer;
}
.breath-pill[hidden] { display: none; }
.breath-pill:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.breath-pill-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-faint); }
.breath-pill-dot.ok   { background: #58d996; }
.breath-pill-dot.warn { background: #e8c268; }
.breath-pill-meter {
  width: 48px;
  height: 4px;
  border-radius: 2px;
  background: var(--bg);
  overflow: hidden;
}
#breath-pill-fill {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--accent);
}

/* ================================================= Responsive */
/* Laptop: the context bar is the first thing to run out of room. Group
   labels that the controls already explain go first. */
@media (max-width: 1440px) {
  .bar { column-gap: 14px; }
  .bar-context .grp + .grp::before { margin-right: 8px; }
  #key-select { width: 146px; }
  #split-mode { width: 118px; }
  #sound-select { width: 120px; }
  #pitch-system { width: 104px; }
  #master-volume, #reverb-amount { width: 56px; }
  .knob-row { margin-left: 2px; }
}
/* The two view toggles explain themselves; their group label goes first. */
@media (max-width: 1380px) {
  .grp-label[id="lbl-view"] { display: none; }
}

/* ---------------------------------------------------------------- Audio -> MIDI
   js/audio-to-midi.js. The top bar only ever holds the button; the job panel and the picker
   sheet are fixed layers, so a running job never shifts the bar. Tokens only, so body.light
   themes everything. Radius by role: pill = action, ctl = chooser, card = container. */

/* Activity ring on the bar button while a job runs. Absolutely placed: no layout change. */
.a2m-btn { position: relative; }
.a2m-btn-ring {
  position: absolute; top: 4px; right: 4px; width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 2px var(--bg-bar); opacity: 0;
  transition: opacity .2s var(--ease);
}
.a2m-btn.is-busy .a2m-btn-ring { opacity: 1; }
.a2m-btn.has-result .a2m-btn-ring { opacity: 1; background: var(--text-hi); }
@media (prefers-reduced-motion: no-preference) {
  .a2m-btn.is-busy .a2m-btn-ring { animation: a2m-pulse 1.6s var(--ease) infinite; }
}
@keyframes a2m-pulse { 50% { box-shadow: 0 0 0 4px var(--accent-soft); } }

/* Job panel */
.a2m-panel {
  position: fixed; right: 16px; bottom: 44px; z-index: 900;
  width: min(360px, calc(100vw - 32px));
  padding: 14px 14px 12px;
  background: var(--bg-bar); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-card);
  box-shadow: var(--cap), var(--shadow-pop);
  font-size: 12px;
}
.a2m-panel[hidden], .a2m-panel [hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .a2m-panel:not([hidden]) { animation: a2m-rise .24s var(--ease); }
}
@keyframes a2m-rise { from { opacity: 0; transform: translateY(8px); } }
.a2m-panel-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.a2m-panel-file {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-hi); font-weight: 600; font-size: 13px;
}
.a2m-icon-btn {
  flex: 0 0 auto; width: 24px; height: 24px; border-radius: var(--r-pill);
  border: 0; background: transparent; color: var(--text-dim); font-size: 16px; line-height: 1;
  cursor: pointer;
}
.a2m-icon-btn:hover { background: var(--surface); color: var(--text-hi); }
.a2m-icon-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }

/* Step track: three labels above one bar. The bar is the single source of progress. */
.a2m-steps {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px;
  list-style: none; margin: 0 0 6px; padding: 0;
  color: var(--text-faint); font-size: 11px;
}
.a2m-steps li.is-done { color: var(--text-dim); }
.a2m-steps li.is-now { color: var(--accent); font-weight: 600; }
.a2m-bar {
  position: relative; height: 4px; border-radius: var(--r-pill);
  background: var(--well); box-shadow: var(--sink); overflow: hidden;
}
.a2m-bar > span {
  position: absolute; inset: 0 auto 0 0; width: 0; border-radius: inherit;
  background: var(--accent); transition: width .4s var(--ease);
}
.a2m-panel.error .a2m-bar > span { background: var(--danger); }
/* Waiting with no measurable progress: a slow travelling highlight inside the current step. */
.a2m-bar.is-indeterminate > span::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--text-hi) 45%, transparent), transparent);
  transform: translateX(-100%);
}
@media (prefers-reduced-motion: no-preference) {
  .a2m-bar.is-indeterminate > span::after { animation: a2m-sweep 1.4s var(--ease) infinite; }
}
@keyframes a2m-sweep { to { transform: translateX(100%); } }

.a2m-text { margin: 10px 0 0; color: var(--text-hi); line-height: 1.4; }
.a2m-panel.error .a2m-text { color: var(--danger); }
.a2m-sub { color: var(--text-dim); font-weight: 400; }
.a2m-panel .a2m-sub { margin-top: 2px; min-height: 1.3em; }
.a2m-warn { margin-top: 6px; color: var(--text); }
.a2m-panel-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 12px; }
.btn.a2m-act { height: calc(var(--h-ctl) - 4px); padding: 0 10px; font-size: 12px; }
a.btn.a2m-act:not([hidden]) { display: inline-flex; align-items: center; text-decoration: none; }
.btn.a2m-primary { background: var(--accent); color: var(--accent-ink); box-shadow: none; font-weight: 600; }
.btn.a2m-primary:hover { background: color-mix(in srgb, var(--accent) 88%, white); }
.btn.a2m-primary:disabled { background: var(--surface); color: var(--text-faint); }
.a2m-credits { margin-left: auto; color: var(--text-dim); white-space: nowrap; }

/* Picker sheet */
.a2m-dialog-back {
  position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgba(3, 6, 12, .6);
}
.a2m-dialog-back[hidden], .a2m-dialog [hidden] { display: none; }
.a2m-dialog {
  width: min(520px, 100%); max-height: calc(100dvh - 32px); overflow: auto;
  background: var(--bg-bar); color: var(--text); border: 1px solid var(--line);
  border-radius: var(--r-card); box-shadow: var(--cap), var(--shadow-pop); padding: 18px; font-size: 13px;
}
.a2m-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 12px; }
.a2m-dialog h2 { margin: 0; font-size: 15px; color: var(--text-hi); }
.a2m-h3 { margin: 18px 0 8px; font-size: 12px; font-weight: 600; color: var(--text-dim); }
.a2m-dialog-file { margin: 0 0 12px; color: var(--text-hi); word-break: break-word; }

/* A raised button like the mode cards, icon tile on the left. Lights up in
   the accent while a file is dragged over it. */
.a2m-drop {
  display: grid; grid-template-columns: auto 1fr; column-gap: 14px; row-gap: 3px;
  width: 100%; padding: 14px 16px; text-align: left; cursor: pointer;
  background: var(--surface); color: var(--text); font: inherit;
  border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--cap);
  transition: border-color .15s var(--ease), background .15s var(--ease), box-shadow .15s var(--ease);
}
/* Children never take the pointer, so dragging across them does not fire
   dragleave on the button and flicker the drop state. */
.a2m-drop > * { pointer-events: none; }
.a2m-drop:hover { border-color: var(--accent-line); background: var(--surface-hi); }
.a2m-drop.is-over { border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 0 3px var(--accent-soft); }
.a2m-drop:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.a2m-drop-icon {
  grid-row: 1 / 3; align-self: center; display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: var(--r-ctl);
  background: var(--accent-soft); color: var(--accent);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.a2m-drop-icon svg { width: 20px; height: 20px; }
.a2m-drop.is-over .a2m-drop-icon { background: var(--accent); color: var(--accent-ink); }
.a2m-drop-title { align-self: end; color: var(--text-hi); font-weight: 600; }
.a2m-drop-hint { align-self: start; color: var(--text-dim); font-size: 12px; text-wrap: balance; }

/* Mode cards: the radio stays a real, visible radio (keyboard and test friendly). */
.a2m-cards { display: grid; gap: 8px; }
.a2m-card {
  display: grid; grid-template-columns: auto 1fr auto; align-items: start; gap: 10px;
  padding: 10px 12px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-ctl);
  box-shadow: var(--cap); transition: border-color .15s var(--ease), background .15s var(--ease);
}
.a2m-card:hover { border-color: var(--accent-line); }
.a2m-card:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.a2m-card:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 1px; }
.a2m-card:has(input:disabled) { cursor: not-allowed; background: var(--well); box-shadow: none; }
.a2m-card:has(input:disabled):hover { border-color: var(--line); }
.a2m-card input { margin-top: 2px; accent-color: var(--accent); }
.a2m-card-body { display: grid; gap: 2px; min-width: 0; }
.a2m-card-title { color: var(--text-hi); font-weight: 600; }
.a2m-card:has(input:disabled) .a2m-card-title { color: var(--text-dim); }
.a2m-card-desc { color: var(--text-dim); font-size: 12px; line-height: 1.4; }
.a2m-cost {
  align-self: center; padding: 2px 8px; border-radius: var(--r-pill); white-space: nowrap;
  background: var(--well); color: var(--text); font-size: 11px;
}
.a2m-card:has(input:checked) .a2m-cost { color: var(--accent); }

.a2m-price { margin: 14px 0 12px; color: var(--text-hi); }
.a2m-dialog-actions { display: flex; justify-content: flex-end; gap: 8px; }
.a2m-dialog-actions .btn:disabled { cursor: not-allowed; }

/* Library */
.a2m-library { display: grid; gap: 6px; }
.a2m-lib-item {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 8px;
  padding: 8px 10px; background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r-ctl);
}
.a2m-lib-name { color: var(--text-hi); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.a2m-lib-meta { color: var(--text-dim); font-size: 11px; margin-top: 2px; }
.a2m-lib-meta.is-failed { color: var(--danger); }
.a2m-lib-actions { display: flex; gap: 4px; }
.a2m-lib-empty { padding: 14px; text-align: center; color: var(--text-dim); background: var(--well); border-radius: var(--r-ctl); }
.a2m-skel { height: 44px; border-radius: var(--r-ctl); background: var(--surface); opacity: .6; }
@media (prefers-reduced-motion: no-preference) {
  .a2m-skel { animation: a2m-fade 1.2s var(--ease) infinite alternate; }
}
@keyframes a2m-fade { to { opacity: .25; } }

@media (max-width: 640px) {
  .a2m-panel { right: 8px; left: 8px; width: auto; bottom: 8px; }
}

@media (max-width: 1100px) {
  .bar { flex-wrap: wrap; }
}

@media (max-width: 1280px) {
  .brand-name { display: none; }
  #auth-box .auth-email { display: none; }
  .file-btn .btn-label {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap;
  }
  .file-btn { width: var(--h-ctl); padding: 0; }
  .sidebar { width: 256px; min-width: 256px; padding: 12px 14px 18px; }
}

/* Small screens: stack the sidebar above the stage and let the bars wrap. */
@media (max-width: 820px) {
  html, body { overflow: auto; height: auto; min-height: 100dvh; }
  .bar { padding: 8px 16px; }
  .bar-spacer { display: none; }
  .bar-context .grp + .grp::before { display: none; }
  .grp { flex-wrap: wrap; }
  .grp-transport { flex: 1 1 100%; }
  .workspace { flex-direction: column; overflow: visible; }
  .sidebar { width: 100%; min-width: 0; border-right: 0; border-bottom: 1px solid var(--line-soft); overflow: visible; }
  .stage-wrap { padding: 8px 0; }
  .statusbar { flex-direction: column; align-items: flex-start; }
  .hint { white-space: normal; text-align: left; }
}

/* Touch screens: every target grows to 40px (Linear's tap floor). */
@media (pointer: coarse) {
  :root { --h-ctl: 40px; --h-side: 40px; }
  input[type="range"] { height: 32px; }
}

/* Notched screens: keep the bars' content out of the safe-area insets. */
@supports (padding: env(safe-area-inset-left)) {
  .bar, .statusbar {
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
  }
  .statusbar { padding-bottom: max(4px, env(safe-area-inset-bottom)); }
}

.a2m-lib-bar { display: flex; justify-content: flex-end; }
.a2m-rm { min-width: 28px; padding-inline: 8px; color: var(--text-dim); }
.a2m-rm:hover { color: var(--text-hi); }

.a2m-buy { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 10px 0 4px; }
.a2m-buy-lead { color: var(--text-dim); font-size: 12px; margin-right: 4px; }
.a2m-pack { text-decoration: none; }

.a2m-pricing { margin: 8px 0 2px; color: var(--text-dim); font-size: 12px; }
.a2m-pricing summary { cursor: pointer; color: var(--text); }
.a2m-pricing ul { margin: 6px 0 0 16px; padding: 0; line-height: 1.6; }
.a2m-note { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 60; background: var(--panel, #12151b);
  color: var(--text-hi, #eef1f5); border: 1px solid var(--line, #262b35); border-radius: 10px; padding: 10px 16px; font-size: 13px; }
