/* T3 — Stems mixer (src/studio/mixer/).

   The card is the shell's mixer slot: header row, T4's Sections row, the
   timeline (ruler, a row per stem, Metronome, Loop A–B, playhead) and T7's
   transport. Every track row is [header 148][pan 44][M/S 28][lane], 8px
   apart, so the lanes start 244px in and the Loop A–B info spans the first
   three columns. Positions along the song are custom properties (--at,
   --from, --to: fractions of the song), mapped across the lane's inner
   width (8px padding each side). Colours come from tokens.css; each row sets
   --track-color to its stem's token. */

.st-shell__mixer.mixer {
  --mixer-played: var(--st-warn);
  --mixer-rest: var(--st-neutral);
  --mixer-lane-start: 244px;
  --mixer-pad: 8px;
  padding: 16px;
  border-radius: var(--st-radius-card);
  outline: 1px solid var(--st-line);
  outline-offset: -0.5px;
  background: var(--st-surface);
}

.mixer > [data-slot='mixer-head'] { flex: none; margin-bottom: 12px; container: mixer-head / inline-size; }

/* The tracks scroll inside the card when the window is short, so the
   transport keeps its own row. The padding (taken back by the margins) keeps
   focus rings and the playhead's tail inside the scroller; the scroll padding
   keeps a ring whole when Tab scrolls its control to an edge. */
.mixer > [data-slot='mixer-tracks'] {
  margin: 6px -4px 7px;
  padding: 0 4px 5px;
  overflow: hidden auto;
  scroll-padding-block: 6px;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  container: st-mixer-tracks / size;
}

/* Until T7's transport fills its slot, keep its room so the rows sit where
   the design puts them. */
.mixer > [data-slot='transport']:empty { height: 55.5px; }

/* ---- Header row ------------------------------------------------------------ */

.mixer-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.mixer-head__title { margin: 0; color: var(--st-text); font: 600 14px/normal var(--st-font); white-space: nowrap; }
.mixer-head__spacer { flex: 1; }

.mixer-presets { display: flex; gap: 2px; padding: 3px; border-radius: var(--st-radius-control); outline: 1px solid var(--st-line); outline-offset: -0.5px; background: var(--st-panel); }
.mixer-presets__item {
  padding: 5px 11px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--st-text-faint);
  font: 500 12px/normal var(--st-font);
  white-space: nowrap;
  cursor: pointer;
}
.mixer-presets__item:hover { color: var(--st-text); }
.mixer-presets__item[aria-pressed='true'] {
  outline: 1px solid var(--st-line-strong);
  outline-offset: -0.5px;
  background: var(--st-surface-2);
  color: var(--st-text);
}

.mixer-stem-audio {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px 6px 12px;
  border-radius: var(--st-radius-control);
  outline: 1px solid color-mix(in srgb, var(--st-stem-audio) 25%, transparent);
  outline-offset: -0.5px;
  background: color-mix(in srgb, var(--st-stem-audio) 7%, transparent);
  cursor: pointer;
}
.mixer-stem-audio__label { color: var(--st-stem-audio-ink); font: 500 12px/normal var(--st-font); white-space: nowrap; }
.mixer-stem-audio .st-switch[aria-checked='true'] { background: var(--st-stem-audio-on); }
.mixer-stem-audio[data-on='false'] { outline-color: var(--st-line); background: none; }
.mixer-stem-audio[data-on='false'] .mixer-stem-audio__label { color: var(--st-text-dim); }

.mixer-hide {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 10px;
  border: 0;
  border-radius: 8px;
  outline: 1px solid var(--st-line);
  outline-offset: -0.5px;
  background: none;
  color: var(--st-text-dim);
  font: 400 12px/normal var(--st-font);
  cursor: pointer;
}
.mixer-hide:hover { background: var(--st-surface-2); color: var(--st-text); }
.mixer-hide .st-icon { width: 13px; height: 13px; }

.mixer-presets__short { display: none; }

/* A narrow card (Practice below about 1600px wide): short preset labels,
   Hide as an icon. Narrower still (1280): the presets take their own row. */
@container mixer-head (max-width: 780px) {
  .mixer-presets__long { display: none; }
  .mixer-presets__short { display: inline; }
  .mixer-hide { width: 30px; padding: 0; justify-content: center; }
  .mixer-hide__label { display: none; }
}
@container mixer-head (max-width: 600px) {
  .mixer-head { flex-wrap: wrap; row-gap: 8px; }
  .mixer-presets { order: 1; flex: 1 0 100%; }
  .mixer-presets__item { flex: 1; }
}

/* ---- Timeline ---------------------------------------------------------------- */

/* Track height (layout menu): fixed rows, Compact by default. Rows never stretch to
   fill the card (spare room stays empty below) or shrink (the tracks scroll instead). */
.mixer-timeline { --track-h: 40px; --meter-h: 24px; position: relative; display: flex; flex-direction: column; gap: 6px; }
/* The stereo meter is about 60% of the row, in whole pixels (meter.ts paints whole pixels). */
.mixer-timeline[data-track-height='comfy'] { --track-h: 56px; --meter-h: 32px; }
.mixer-timeline[data-track-height='tall'] { --track-h: 88px; --meter-h: 52px; }

.mixer-ruler { flex: none; display: flex; height: 20px; }
.mixer-ruler__spacer { flex: none; width: var(--mixer-lane-start); }
.mixer-ruler__lane { position: relative; flex: 1; min-width: 0; cursor: pointer; }
.mixer-ruler__label {
  position: absolute;
  top: 3px;
  /* A label near the end stops at the lane's edge, whole ("01:00" is 5ch; songs are 25 min at most). */
  left: min(calc(var(--mixer-pad) + (100% - 2 * var(--mixer-pad)) * var(--at, 0)), calc(100% - 5ch));
  color: var(--st-text-faint);
  font: 400 10px/normal var(--st-font-mono);
  white-space: nowrap;
  pointer-events: none;
}
.mixer-ruler__label[hidden] { display: none; }

.mixer-playhead {
  position: absolute;
  top: 0;
  right: var(--mixer-pad);
  bottom: 0;
  left: calc(var(--mixer-lane-start) + var(--mixer-pad));
  z-index: 4;
  pointer-events: none;
  /* Clipped (with room for the head at either end), so moving the track
     never changes the timeline's overflow and the page doesn't repaint. */
  overflow: clip;
  overflow-clip-margin: 8px;
}
/* Moved by transform only (timeline.ts sets it): a full-width track whose
   left edge is the line, in its own layer so a move only recomposites. */
.mixer-playhead__track { position: absolute; inset: 0; will-change: transform; }
.mixer-playhead__track::before {
  content: '';
  position: absolute;
  top: 6px;
  bottom: -3px;
  left: -1px;
  width: 2px;
  background: var(--st-accent);
  box-shadow: 0 0 8px color-mix(in srgb, var(--st-accent) 60%, transparent);
}
.mixer-playhead__head { position: absolute; top: 0; left: -6px; width: 12px; height: 12px; border-radius: 6px; outline: 2px solid var(--st-on-accent); outline-offset: -1px; background: var(--st-accent); }

/* ---- Track rows ---------------------------------------------------------------- */

.mixer-track { display: flex; flex: none; gap: 8px; height: var(--track-h); }
.mixer-track[hidden] { display: none; }

/* No stems yet (a reopened song before it's split again): the Metronome keeps
   its row and a hint takes the stems' room. */
.mixer-timeline[data-stems='0'] { min-height: 100%; }
.mixer-empty { display: flex; flex: 1; flex-direction: column; align-items: center; justify-content: center; gap: 6px; min-height: 56px; padding: 12px; border-radius: 10px; outline: 1px dashed var(--st-line); outline-offset: -0.5px; text-align: center; }
.mixer-empty__title { margin: 0; color: var(--st-text-dim); font: 500 12.5px/normal var(--st-font); }
.mixer-empty__body { margin: 0; color: var(--st-text-faint); font: 400 11.5px/17px var(--st-font); }

.mixer-track__header {
  position: relative;
  display: flex;
  flex: none;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 148px;
  padding: 6px 12px 6px 24px;
  border-radius: 10px;
  /* The 1px line drawn as the card's outline would be (half in, half out),
     but as a shadow: an outline here repaints the whole page whenever the
     meter inside it moves. */
  box-shadow: 0 0 0 0.5px var(--st-line), inset 0 0 0 0.5px var(--st-line);
  background: var(--st-panel);
}
/* The focused row comes forward, so the next row never covers its ring. */
.mixer-track__header:focus-within { z-index: 1; }
.mixer-track__top { display: flex; align-items: center; gap: 8px; min-width: 0; color: var(--track-color); }
.mixer-track__icon { flex: none; width: 14px; height: 14px; }
.mixer-metronome-icon { flex: none; width: 16px; height: 16px; }
.mixer-metronome-icon__needle { stroke: var(--st-menu-bg); }
.mixer-track__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  color: var(--track-color);
  font: 500 13px/16px var(--st-font);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mixer-track .st-slider { gap: 0; }
.mixer-track .st-slider__track { min-width: 0; }
/* Compact: a 14px name line and a 12px slider, 2px apart, leave 6px above and below in 40px. */
.mixer-timeline[data-track-height='compact'] .mixer-track__header { gap: 2px; }
.mixer-timeline[data-track-height='compact'] .mixer-track__name { line-height: 14px; }
.mixer-timeline[data-track-height='compact'] .mixer-metronome-icon { width: 14px; height: 14px; }
.mixer-timeline[data-track-height='compact'] .mixer-track .st-slider { height: 12px; }
.mixer-timeline[data-track-height='compact'] .mixer-track .st-slider__track { height: 12px; }
.mixer-timeline[data-track-height='compact'] .mixer-track .st-slider__track::before,
.mixer-timeline[data-track-height='compact'] .mixer-track .st-slider__fill { top: 4px; }
.mixer-timeline[data-track-height='compact'] .mixer-track .st-slider__thumb { top: 0; }
.mixer-timeline[data-track-height='compact'] .mixer-track .st-slider__readout { line-height: 12px; }

/* The stereo meter: --meter-h tall (about 60% of the row), centred, with its
   bars 8px from the card's left edge and 8px from the text column. meter.ts
   sets the bars' transforms directly, a whole pixel at a time; each bar and
   peak mark is its own small layer, so a moving meter is recomposited, not
   repainted (a repaint here walks the whole page's paint every frame), and it
   reads the height from the box. The box is padded to hold the glow, fully
   contained, and inside the card at every row height. */
.mixer-meter {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 2px;
  display: flex;
  gap: 2px;
  box-sizing: content-box;
  width: 8px;
  height: var(--meter-h);
  margin: auto 0;
  padding: 6px;
  contain: strict;
}
.mixer-meter__side { position: relative; width: 3px; height: 100%; border-radius: 2px; background: color-mix(in srgb, var(--track-color) 12%, transparent); }
.mixer-meter__level {
  position: absolute;
  inset: 0;
  border-radius: 2px;
  background: linear-gradient(to top, var(--track-color), color-mix(in srgb, var(--track-color) 50%, transparent));
  box-shadow: 0 0 6px color-mix(in srgb, var(--track-color) 70%, transparent);
  transform: scaleY(0);
  transform-origin: bottom;
  will-change: transform;
}
.mixer-meter__peak { position: absolute; right: 0; bottom: 0; left: 0; height: 2px; border-radius: 1px; background: var(--track-color); opacity: 0; will-change: transform; }
.mixer-meter__side.has-peak .mixer-meter__peak { opacity: 1; }
.mixer-meter__side.is-clipping .mixer-meter__peak { background: var(--st-error); opacity: 1; }
.mixer-meter__side.is-clipping .mixer-meter__level { border-top: 3px solid var(--st-error); }

.mixer-track__pan { display: flex; flex: none; flex-direction: column; align-items: center; justify-content: center; gap: 3px; width: 44px; }
.mixer-track__sides { display: flex; justify-content: space-between; width: 38px; color: var(--st-text-faint); font: 700 9px/normal var(--st-font-mono); }
/* Compact: a smaller knob with L and R beside its foot, so the column fits 40px. */
.mixer-timeline[data-track-height='compact'] .mixer-track__pan { position: relative; }
.mixer-timeline[data-track-height='compact'] .st-knob { width: 30px; height: 30px; }
.mixer-timeline[data-track-height='compact'] .st-knob__pointer { top: 4px; height: 9px; }
.mixer-timeline[data-track-height='compact'] .mixer-track__sides { position: absolute; bottom: 1px; width: 44px; }
.mixer-track[data-pan='L'] [data-side='L'],
.mixer-track[data-pan='R'] [data-side='R'] { color: var(--track-color); }

.mixer-track__ms { display: flex; flex: none; flex-direction: column; gap: 4px; width: 28px; }
.mixer-ms { display: grid; flex: 1; place-items: center; min-height: 0; padding: 0; border: 0; border-radius: 6px; outline: 1px solid var(--st-line); outline-offset: -0.5px; background: var(--st-surface-2); color: var(--st-text-faint); font: 700 10px/normal var(--st-font-mono); cursor: pointer; }
.mixer-ms:not(:disabled):hover { color: var(--st-text); }
.mixer-ms:disabled { cursor: default; }
.mixer-ms--mute[aria-pressed='true'] { outline-color: transparent; background: var(--st-accent-strong); color: var(--st-on-accent); }
.mixer-ms--solo[aria-pressed='true'] { outline-color: transparent; background: var(--st-chord-ink); color: var(--st-on-chord-ink); }

.mixer-track__lane {
  position: relative;
  flex: 1;
  min-width: 0;
  padding: 0 var(--mixer-pad);
  border-radius: 8px;
  background: color-mix(in srgb, var(--track-color) 7%, transparent);
  cursor: pointer;
}
.mixer-track[data-channel='metronome'] .mixer-track__lane { background: color-mix(in srgb, var(--track-color) 5%, transparent); }
.mixer-track__canvas { position: absolute; top: 0; right: var(--mixer-pad); bottom: 0; left: var(--mixer-pad); width: calc(100% - 2 * var(--mixer-pad)); height: 100%; }
.mixer-timeline[data-stem-audio='off'] .mixer-track:not([data-channel='metronome']) { opacity: 0.45; }

/* The Metronome rate, over the left of its lane. */
.mixer-rate.st-seg {
  position: absolute;
  top: 50%;
  left: var(--mixer-pad);
  z-index: 1;
  height: 30px;
  padding: 3px;
  border-radius: var(--st-radius-control);
  outline: 1px solid color-mix(in srgb, var(--track-color) 25%, transparent);
  background: var(--st-menu-bg);
  box-shadow: 6px 0 10px var(--st-menu-bg);
  transform: translateY(-50%);
  cursor: default;
}
.mixer-rate .st-seg__item { height: 100%; padding: 0 9px; color: var(--st-text-faint); font: 500 11.5px/normal var(--st-font-mono); }
.mixer-rate .st-seg__item[aria-checked='true'] {
  outline: 1px solid var(--track-color);
  background: color-mix(in srgb, var(--track-color) 15%, transparent);
  color: var(--st-metronome-ink);
  font-weight: 700;
}

/* ---- Loop A–B row ---------------------------------------------------------------- */

.mixer-loop { display: flex; flex: none; gap: 8px; height: 44px; }
.mixer-loop[hidden] { display: none; }
.mixer-loop__info {
  display: flex;
  flex: none;
  align-items: center;
  gap: 8px;
  width: 236px;
  padding: 0 4px 0 12px;
  border-radius: 10px;
  outline: 1px solid color-mix(in srgb, var(--st-loop) 25%, transparent);
  outline-offset: -0.5px;
  background: color-mix(in srgb, var(--st-loop) 6%, transparent);
}
.mixer-loop__text { display: flex; flex: 1; flex-direction: column; gap: 1px; min-width: 0; }
.mixer-loop__label { color: var(--st-loop-ink); font: 600 9.5px/normal var(--st-font-mono); letter-spacing: 1.2px; text-transform: uppercase; }
.mixer-loop__range { overflow: hidden; color: var(--st-text); font: 500 12px/normal var(--st-font); text-overflow: ellipsis; white-space: nowrap; }
.mixer-loop__btn {
  display: grid;
  flex: none;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 7px;
  outline: 1px solid var(--st-line);
  outline-offset: -0.5px;
  background: none;
  color: var(--st-text-dim);
  cursor: pointer;
}
.mixer-loop__btn:not(:disabled):hover { background: var(--st-surface-2); color: var(--st-text); }
.mixer-loop__btn:disabled { opacity: 0.45; cursor: default; }
/* At the saved-loop limit Save loop stays pressable (it opens the transport's list), dimmed. */
.mixer-loop__btn[data-full='true'] { opacity: 0.6; }
.mixer-loop__btn .st-icon { width: 14px; height: 14px; }
.mixer-loop__btn--toggle[aria-pressed='true'] {
  outline-color: color-mix(in srgb, var(--st-loop) 50%, transparent);
  background: color-mix(in srgb, var(--st-loop) 15%, transparent);
  color: var(--st-loop-ink);
}

.mixer-loop__overview {
  position: relative;
  flex: 1;
  min-width: 0;
  padding: 0 var(--mixer-pad);
  border-radius: 8px;
  outline: 1px solid var(--st-line);
  outline-offset: -0.5px;
  background: var(--st-panel);
  cursor: pointer;
  touch-action: none;
}
.mixer-loop__inner { position: relative; height: 100%; }
/* The keyboard's seek slider over the whole strip, under the handles; a
   press on it is a press on the strip (loop-row.ts listens on the strip). */
.mixer-loop__seek { position: absolute; inset: 0; z-index: 1; border-radius: 8px; }
.mixer-loop__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.mixer-loop__region {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--from, 0) * 100%);
  width: calc((var(--to, 0) - var(--from, 0)) * 100%);
  z-index: 1; /* over the seek slider: a press inside the loop moves it (loop-row.ts) */
  background: color-mix(in srgb, var(--st-loop) 14%, transparent);
  cursor: grab;
  touch-action: none;
}
.mixer-loop__region.is-dragging { cursor: grabbing; }
.mixer-loop__edge { position: absolute; top: -3px; bottom: -3px; left: calc(var(--at, 0) * 100% - 1px); z-index: 1; width: 2px; border-radius: 1px; background: var(--st-loop); pointer-events: none; }
.mixer-loop__handle {
  position: absolute;
  top: 50%;
  left: calc(var(--at, 0) * 100% - 19px);
  z-index: 2;
  width: 38px;
  height: 22px;
  border-radius: 11px;
  background: var(--st-loop);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--st-shadow) 50%, transparent);
  color: var(--st-on-loop);
  font: 700 12px/22px var(--st-font);
  text-align: center;
  transform: translateY(-50%);
  cursor: ew-resize;
  touch-action: none;
  user-select: none;
}
.mixer-loop__handle:focus-visible { z-index: 3; } /* above the other handle */
.mixer-loop__handle.is-dragging { box-shadow: 0 0 0 3px color-mix(in srgb, var(--st-loop) 35%, transparent), 0 2px 8px color-mix(in srgb, var(--st-shadow) 50%, transparent); }
.mixer-loop[data-has-range='false'] :is(.mixer-loop__region, .mixer-loop__edge, .mixer-loop__handle) { display: none; }
/* The loop toggle is off (decision 28): the remembered range, or "Loop off", greyed. */
.mixer-loop[data-looping='false'] .mixer-loop__range { color: var(--st-text-dim); }
