/* mock.css — the iPad's screen: a capture of River's Mixer, with its moving
   parts drawn live over it.

   Everything is placed in the capture's own pixels (2420 × 1668), as
   multiples of --px, so the overlays land on the picture at any size. The
   meters are redrawn whole — the pill, its dots, the fader's line and cap —
   because the capture's own were caught mid-song. Measured off
   the app's Mixer: dots on a 10 px grid, #323948 unlit on a #3a4151
   pill, #3d968e lit; the fader line white, fading out towards the bottom. */

.mixer {
  --px: calc(100cqw / 2420);
  --dot-off: #323948;
  --dot-on: #3d968e;
  --pill: #3a4151;
  position: absolute; inset: 0;
  background: #161B26 url("../images/mixer.png") 0 0 / 100% 100% no-repeat;
  font-family: -apple-system, "SF Pro Text", "IBM Plex Sans", system-ui, sans-serif;
  user-select: none; -webkit-user-select: none;
}

/* A box at capture coordinates: --x, --y, --w, --h. */
.at {
  position: absolute;
  left: calc(var(--x) * var(--px)); top: calc(var(--y) * var(--px));
  width: calc(var(--w) * var(--px)); height: calc(var(--h) * var(--px));
}

/* ---------- meters ---------- */
/* Per meter: --gx, --gy, the grid's phase in the pill (a dot's tile corner);
   --lit-x, --lit-w, the columns that light. */
.meter {
  --grid: calc(var(--gx) * var(--px)) calc(var(--gy) * var(--px)) / calc(10 * var(--px)) calc(10 * var(--px));
  border-radius: calc(40 * var(--px));
  background: radial-gradient(circle, var(--dot-off) calc(3.2 * var(--px)), transparent calc(3.8 * var(--px))) var(--grid), var(--pill);
  overflow: hidden;
}
/* The lit dots: the same grid in teal, the pill's full size so its phase is
   the same, clipped to the lit columns and from the bottom up to --lvl. */
.meter .lit {
  position: absolute; inset: 0;
  background: radial-gradient(circle, var(--dot-on) calc(3.2 * var(--px)), transparent calc(3.8 * var(--px))) var(--grid);
  clip-path: inset(calc(100% - var(--lvl, 0%)) calc(100% - (var(--lit-x) + var(--lit-w)) * var(--px)) 0 calc(var(--lit-x) * var(--px)));
}
.meter .line {
  position: absolute; bottom: calc(4 * var(--px));
  left: calc(var(--cap-x) * var(--px) - 5 * var(--px)); width: calc(10 * var(--px));
  top: calc(var(--cap-y) * var(--px) + 26 * var(--px));
  border-radius: calc(5 * var(--px));
  background: linear-gradient(rgba(230, 236, 245, 0.78), rgba(230, 236, 245, 0.06));
}
.meter .cap {
  position: absolute;
  left: calc(var(--cap-x) * var(--px)); top: calc(var(--cap-y) * var(--px));
  width: calc(54 * var(--px)); height: calc(54 * var(--px));
  transform: translate(-50%, -50%); border-radius: 50%;
  border: calc(6 * var(--px)) solid #c9ced8;
}

/* ---------- the position readout ---------- */
.readout {
  background: #1d232f;
  display: grid; justify-items: center; align-content: center;
  color: #E6ECF5; font-weight: 500; font-size: calc(34 * var(--px));
  font-variant-numeric: tabular-nums; letter-spacing: 0.01em;
}

/* The transport's stop and play, over the capture's own buttons. */
.hit { background: transparent; border: 0; padding: 0; cursor: pointer; border-radius: calc(10 * var(--px)); }
.hit:focus-visible { outline: 2px solid #3FB8A6; outline-offset: -2px; }
.hit.on::after {
  content: ""; position: absolute; inset: 18%; border-radius: 50%;
  box-shadow: 0 0 calc(30 * var(--px)) calc(6 * var(--px)) rgba(63, 184, 166, 0.35);
}

/* ---------- the intro, over the Mixer until it plays ----------
   What River is, a line under it, and the Preview capsule, set straight on
   the Mixer. Sized in the
   capture's pixels like everything else here, so it scales with the iPad.
   It gives way once the music is heard. */
.intro {
  /* Straight on the Mixer, no card: centred on the screen. */
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: calc(1640 * var(--px));
  text-align: center; color: #E6ECF5;
  display: grid; justify-items: center; gap: calc(52 * var(--px));   /* capture px: 2 to the iPad's point */
  /* The swap with the highlights: quicker than the sound's 2s fade-in, so
     the words have moved on by the time the music is up. */
  --intro-fade: 0.45s;
  transition: opacity var(--intro-fade) ease-out, visibility var(--intro-fade);
}
/* SF Rounded, medium: the app's own face where Apple's systems have it,
   the system sans at the same weight everywhere else. */
.intro h1, .intro h2, .intro p {
  font-family: ui-rounded, "SF Pro Rounded", system-ui, -apple-system, "Helvetica Neue", sans-serif;
  font-weight: 500;
}
.intro h1 {
  margin: 0; letter-spacing: -0.005em; line-height: 1.1;
  font-size: calc(92 * var(--px)); text-wrap: balance;
}
/* "Introducing" in the subheading's voice (its size and weight), so River
   carries the heading; River keeps its own size, not scaled from the line. */
.intro h1 .lead { display: block; font-size: calc(68 * var(--px)); font-weight: 400; }
.intro h1 .name { display: block; font-size: calc(124 * var(--px)); letter-spacing: -0.01em; }
/* Placeholder for the app icon, between the two words, until there's
   artwork: the iOS icon's proportions (corner radius 22.37% of the side),
   Midnight's tertiary into the teal, with a faint rim and a soft drop so it
   sits off the Mixer's dark ground. Swap for an <img> when the icon exists. */
.intro h1 .app-icon {
  display: block; margin: calc(28 * var(--px)) auto calc(16 * var(--px));
  width: calc(264 * var(--px)); aspect-ratio: 1; border-radius: 22.37%;
  background: linear-gradient(145deg, #8C7BE0, #3FB8A6);
  box-shadow: inset 0 0 0 calc(2 * var(--px)) rgba(255, 255, 255, 0.18),
              0 calc(16 * var(--px)) calc(40 * var(--px)) rgba(0, 0, 0, 0.5);
}
/* What it is: a step lighter than the heading, and the platforms a size
   down again, so they read as a footnote to the line. */
.intro h2 {
  margin: 0; font-weight: 400; line-height: 1.25;
  font-size: calc(68 * var(--px)); text-wrap: balance;
}
.intro h2 .platforms { font-size: 0.75em; color: #AEB6C6; }
.intro p {
  margin: 0; color: #AEB6C6; line-height: 1.4;
  font-size: calc(58 * var(--px)); text-wrap: balance; max-width: 26em;
}
.listen {
  margin-top: calc(10 * var(--px));
  display: inline-flex; align-items: center; gap: 8px;
  /* The tabs' type at the tabs' size (IBM Plex Sans, semi-bold, 18px —
     fixed, not scaled with the screen), black with light text, a faint rim
     so it holds against the Mixer's dark ground. */
  font-family: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
  font-weight: 600; font-size: 18px; line-height: 1.15;
  padding: 7px 18px 7px 14px;
  border-radius: 999px; cursor: pointer;
  background: #000; color: #E6ECF5;
  border: 1px solid rgba(230, 236, 245, 0.2);
  transition: filter 0.2s, transform 0.2s;
}
.listen:hover { border-color: #E6ECF5; }
.listen:active { transform: scale(0.98); }
.listen svg { width: 19px; height: 19px; fill: currentColor; }
/* The highlights take the intro's place while the music plays, and the intro
   returns on stop. In turn, never together: whichever is arriving waits out
   the other's fade (transition-delay sits on the arriving state, as the
   transition is taken from the state being entered). */
.mixer:not([data-mode="live"]) .intro.highlights,
.mixer[data-mode="live"] .intro:not(.highlights) { opacity: 0; visibility: hidden; }
.mixer:not([data-mode="live"]) .intro:not(.highlights) { transition-delay: var(--intro-fade); }
/* Left-aligned, the block as wide as its longest line and still centred in
   the space, so the ragged edge sits on the right of a centred column. */
.intro.highlights {
  left: 54%;   /* in the space between the strips and the master */
  width: max-content; max-width: calc(1640 * var(--px));
  text-align: left; justify-items: start; gap: calc(44 * var(--px));
}
.intro.highlights h1 { margin-bottom: calc(6 * var(--px)); font-size: calc(92 * var(--px)); }
/* Label over detail: the feature bright and a step heavier, what it does
   under it in the dimmer grey, close enough to read as one item. */
.intro.highlights p { max-width: none; line-height: 1.3; }
.intro.highlights b {
  display: block; margin-bottom: calc(4 * var(--px));
  font-weight: 700; color: #E6ECF5;
}
/* Line by line: the block itself is up at once, its lines rise in one after
   another once the intro has gone, 120ms apart. Going away they all leave
   together with the block. */
.intro.highlights > * {
  opacity: 0; transform: translateY(calc(14 * var(--px)));
  transition: opacity 0.35s ease-out, transform 0.35s ease-out;
}
.mixer[data-mode="live"] .intro.highlights > * {
  opacity: 1; transform: none;
  transition-delay: calc(var(--intro-fade) + var(--line, 0) * 120ms);
}
.intro.highlights > :nth-child(2) { --line: 1; }
.intro.highlights > :nth-child(3) { --line: 2; }
.intro.highlights > :nth-child(4) { --line: 3; }
.intro.highlights > :nth-child(5) { --line: 4; }
.mixer[data-mode="loading"] .listen { animation: breathe 1.2s ease-in-out infinite; }
@keyframes breathe { 50% { opacity: 0.6; } }

@media (prefers-reduced-motion: reduce) {
  .intro, .listen, .meter .lit { transition: none; }
  .intro.highlights > * { transition: none; transform: none; }
  /* The swap, at once. !important as the delays above sit on selectors
     carrying the mode, which outweigh anything plainer here. */
  .intro, .intro.highlights > * { transition-delay: 0s !important; }
  .mixer[data-mode="loading"] .listen { animation: none; }
}

/* ---------- faders, pan and mutes: the mix, touchable ---------- */
.meter { cursor: ns-resize; touch-action: none; }
.meter:focus-visible, .pan:focus-visible { outline: 2px solid #3FB8A6; outline-offset: 2px; }
.meter.dragging .cap { border-color: #ffffff; }

/* The pan knob, redrawn over the capture's: the face and rim as captured,
   the pointer and its tip in the purple the app uses for parameters, and the
   LFO's reach as a faint arc around it. */
.pan { cursor: ns-resize; touch-action: none; border-radius: 50%; }
.pan svg { width: 100%; height: 100%; overflow: visible; }
.pan .face { fill: #3a4151; stroke: #4a5163; stroke-width: 4; }
.pan .reach { fill: none; stroke: #8c7be0; stroke-width: 7; stroke-linecap: round; opacity: 0.45; }
.pan .pointer { stroke: #8c7be0; stroke-width: 5; stroke-linecap: round; }
.pan .tip { fill: #8c7be0; }

/* A strip's mute: the teal dot when it's sounding, dark when it's muted. */
.mute { background: transparent; border: 0; padding: 0; cursor: pointer; display: grid; place-items: center; border-radius: 50%; }
.mute span {
  width: calc(28 * var(--px)); height: calc(28 * var(--px)); border-radius: 50%;
  background: #3a9c91; box-shadow: 0 0 0 calc(10 * var(--px)) #272d3b;
  transition: background 0.15s;
}
.mute[aria-pressed="true"] span { background: #4a5163; }
.mute:focus-visible { outline: 2px solid #3FB8A6; outline-offset: 0; }
