/* dj.css -- the rig layout: decks, mixer, browser.
 *
 * Three columns on a desktop (deck A | mixer | deck B), collapsing to a single
 * column on narrow screens with the mixer between the two decks, which is the
 * order a thumb wants them in.
 */

.rig {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  gap: 8px;
  padding: 8px 8px 26px;
}

/* ------------------------------------------------------------- top bar */

.topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 6px 8px;
  background: var(--bg-panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
}
.brand {
  font-family: "Press Start 2P", monospace;
  font-size: 0.72rem;
  color: var(--hud-green);
  letter-spacing: 0.08em;
}
.master-bpm { display: flex; align-items: baseline; gap: 6px; }
.master-bpm .num { font-size: 1.05rem; color: var(--hud-orange); }
.rec-btn.armed { background: var(--hud-red); border-color: var(--hud-red); color: #fff; }
.rec-time { color: var(--hud-red); font-variant-numeric: tabular-nums; }
/* The last minute of the cap. Amber rather than red: red is already the
   recording colour, so it would say nothing. */
.rec-time.ending { color: var(--hud-orange); }
@media (prefers-reduced-motion: no-preference) {
  .rec-time.ending { animation: rec-ending 1s steps(2, end) infinite; }
}
@keyframes rec-ending { 50% { opacity: 0.45; } }

/* --------------------------------------------------------------- decks */

.decks {
  display: grid;
  grid-template-columns: 1fr minmax(210px, 250px) 1fr;
  gap: 8px;
  align-items: start;
}
@media (max-width: 1100px) {
  .decks { grid-template-columns: 1fr; }
  .mixer { order: 3; }
}

.deck {
  background: var(--bg-panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.deck.drop-target { border-color: var(--hud-orange); box-shadow: 0 0 0 2px rgba(255,145,48,0.25); }

.deck-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.deck-id {
  font-family: "Press Start 2P", monospace;
  font-size: 1rem;
  color: var(--hud-green);
  width: 22px;
  text-align: center;
}
.track-meta { flex: 1 1 60px; min-width: 0; }
.track-title {
  font-size: 0.94rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.track-artist { font-size: 0.76rem; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.deck-nums { display: flex; gap: 12px; align-items: center; flex: 0 0 auto; }
.bpm-box, .time-box { display: flex; flex-direction: column; align-items: flex-end; }
.bpm-box .num { font-size: 1.15rem; color: var(--hud-orange); }
.time-box .num { font-size: 0.95rem; }
.time-box .dim { font-size: 0.74rem; }

.overview { width: 100%; height: 34px; display: block; border-radius: 3px; cursor: pointer; }
.waveform { width: 100%; height: 108px; display: block; border-radius: 3px; }

.deck-body { display: flex; gap: 10px; align-items: center; }

/* -------------------------------------------------------------- platter */

.platter {
  position: relative;
  width: clamp(130px, 22vw, 190px);
  aspect-ratio: 1;
  flex: 0 0 auto;
  border-radius: 50%;
  cursor: grab;
  touch-action: none;
  user-select: none;
  background:
    radial-gradient(circle at 50% 50%, #16241f 0 22%, #0b1512 22.5% 100%);
  border: 2px solid var(--panel-border);
  display: grid;
  place-items: center;
}
.platter.scratching { cursor: grabbing; border-color: var(--hud-orange); }
.platter.bending { border-color: var(--hud-blue); }
.platter-face {
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  background: repeating-radial-gradient(circle at 50% 50%,
    rgba(255,255,255,0.045) 0 2px, rgba(0,0,0,0) 2px 5px);
  pointer-events: none;
}
/* The rim is a visual cue for the pitch-bend zone -- inside is position, the
   outer ring is a nudge. */
.platter::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 10px solid rgba(57,255,143,0.07);
  pointer-events: none;
}
.platter-marker {
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  pointer-events: none;
  background: conic-gradient(from 0deg, rgba(57,255,143,0.75) 0 3deg, rgba(0,0,0,0) 3deg 360deg);
  will-change: transform;
}
.platter-label {
  font-family: "Press Start 2P", monospace;
  font-size: 0.8rem;
  color: var(--hud-green-dim);
  pointer-events: none;
}

.deck-controls { display: flex; gap: 10px; flex: 1 1 auto; min-width: 0; }
.transport { display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; }
.transport .hud-btn { width: 100%; }
.hud-btn.play.on { background: var(--hud-green-dim); border-color: var(--hud-green); color: #04120c; }
.hud-btn.sync.on { background: var(--hud-blue); border-color: var(--hud-blue); color: #04120c; }
.hud-btn.keylock.on { background: var(--hud-orange); border-color: var(--hud-orange); color: #04120c; }

.pitch { display: flex; flex-direction: column; align-items: center; gap: 4px; flex: 0 0 auto; }

/* -------------------------------------------------- faders and knobs */

.fader { position: relative; touch-action: none; }
.fader.vertical { width: var(--touch); height: 130px; }
.fader.horizontal { width: 100%; height: var(--touch); }
.fader-track {
  position: absolute;
  background: rgba(0,0,0,0.6);
  border: 1px solid var(--panel-border);
  border-radius: 3px;
}
.fader.vertical .fader-track { left: 50%; transform: translateX(-50%); width: 8px; top: 4px; bottom: 4px; }
.fader.horizontal .fader-track { top: 50%; transform: translateY(-50%); height: 8px; left: 4px; right: 4px; }
.fader-cap {
  position: absolute;
  background: linear-gradient(#dff8ec, #86b6a0);
  border-radius: 3px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.6);
  pointer-events: none;
}
.fader.vertical .fader-cap { left: 50%; transform: translateX(-50%); width: 30px; height: 22px; }
.fader.horizontal .fader-cap { top: 50%; transform: translateY(-50%); width: 22px; height: 30px; }
.fader.active .fader-cap { background: linear-gradient(#fff, var(--hud-green)); }

.knob {
  position: relative;
  width: var(--touch);
  height: var(--touch);
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, #1d3129, #0a1512);
  border: 1px solid var(--panel-border);
  touch-action: none;
  cursor: ns-resize;
  display: grid;
  place-items: center;
}
.knob.active, .knob:focus-visible { border-color: var(--hud-green); outline: none; }
.knob-ind {
  position: absolute;
  width: 2px;
  height: 42%;
  top: 6%;
  background: var(--hud-green);
  transform-origin: 50% 100%;
  border-radius: 1px;
  pointer-events: none;
}
.knob-val {
  position: absolute;
  bottom: -13px;
  font-size: 0.58rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  white-space: nowrap;
}

/* --------------------------------------------------------------- pads */

.pads { display: grid; grid-template-columns: repeat(8, 1fr); gap: 4px; }
.pad {
  min-height: var(--touch);
  border-radius: 4px;
  border: 1px solid var(--panel-border);
  background: rgba(8, 22, 18, 0.9);
  color: var(--text-main);
  font-family: "Press Start 2P", monospace;
  font-size: 0.5rem;
  cursor: pointer;
}
.pad.set { color: #04120c; }
.pad:focus-visible { outline: 2px solid var(--hud-blue); outline-offset: 2px; }

.loops, .gridrow { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
.loops .hud-btn, .gridrow .hud-btn { padding: 4px 6px; }
/* Deliberately not shrinking these below the touch minimum either; the rows
   wrap instead, which is what flex-wrap is for. */
.hud-btn.loop-exit.on, .hud-btn.kill.on { background: var(--hud-red); border-color: var(--hud-red); color: #fff; }

/* -------------------------------------------------------------- mixer */

.mixer {
  background: var(--bg-panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.strips { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
.strip { display: flex; flex-direction: column; align-items: center; gap: 15px; }
.strip .lbl { margin-bottom: -8px; }
.kills { display: flex; gap: 3px; flex-wrap: wrap; justify-content: center; }
/* No min-width override here. Squeezing these to 30px to fit three across a
   narrow strip puts them under the sitewide 44px touch minimum, and a kill
   button is exactly the control someone stabs at mid-mix without looking. */
.kills .hud-btn { padding: 4px 6px; }
.chfader-row { display: flex; gap: 6px; align-items: flex-end; }
.meter { width: 10px; height: 130px; background: rgba(0,0,0,0.55); border: 1px solid var(--panel-border); border-radius: 2px; }
.meter.tall { height: 160px; width: 14px; }
.clip {
  font-family: "Press Start 2P", monospace;
  font-size: 0.45rem;
  color: #2a1418;
  background: rgba(255,70,85,0.18);
  border: 1px solid rgba(255,70,85,0.3);
  border-radius: 3px;
  padding: 3px 5px;
}
.clip.lit { background: var(--hud-red); color: #fff; }
.cue-btn.on { background: var(--hud-blue); border-color: var(--hud-blue); color: #04120c; }

.xfader-row { display: flex; flex-direction: column; gap: 6px; }
.xf-opts { display: flex; gap: 4px; justify-content: center; flex-wrap: wrap; }
.xf-opts .hud-btn { padding: 4px 6px; }

/* ------------------------------------------------------------ browser */

.browser {
  background: var(--bg-panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 190px;
}
.browser-tabs { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.browser-subtabs { display: flex; gap: 4px; flex-wrap: wrap; }
.browser-subtabs .hud-btn { padding: 6px 8px; }
.sortbox { display: flex; align-items: center; gap: 6px; }
#browser-sort {
  min-height: var(--touch);
  padding: 4px 8px;
  background: rgba(0,0,0,0.45);
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  color: var(--text-main);
  font-family: inherit;
  font-size: 0.76rem;
}
#browser-sort:focus-visible { outline: 2px solid var(--hud-blue); outline-offset: 2px; }

.crumb { display: flex; align-items: center; gap: 8px; min-width: 0; }
.crumb #crumb-text {
  color: var(--hud-green);
  font-size: 0.78rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sechead {
  font-family: "Press Start 2P", monospace;
  font-size: 0.5rem;
  color: var(--hud-orange);
  letter-spacing: 0.06em;
  padding: 10px 6px 4px;
}
#browser-search {
  flex: 1 1 180px;
  min-width: 140px;
  min-height: var(--touch);
  padding: 6px 10px;
  background: rgba(0,0,0,0.45);
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  color: var(--text-main);
  font-family: inherit;
}
/* Six views of a hundred rows each: 300px was the cramped part of picking a
   track mid-mix. Capped in vh so it never eats a short screen whole. */
.browser-body { max-height: min(46vh, 420px); overflow-y: auto; overflow-x: hidden; }
.browser-body .hint { color: var(--text-dim); font-size: 0.82rem; line-height: 1.6; }

.row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  border-bottom: 1px solid rgba(57,255,143,0.09);
  min-height: var(--touch);
}
.row:hover { background: rgba(57,255,143,0.06); }

/* A drill-down row is a real button: the whole strip is the target, and it
   keeps keyboard focus and Enter working without any extra handling. */
button.row {
  width: 100%;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  /* The UA's default button border would draw a box round every drill-down
     row, which no other row in the list has. */
  border: 0;
  border-bottom: 1px solid rgba(57,255,143,0.09);
}
button.row:focus-visible { outline: 2px solid var(--hud-blue); outline-offset: -2px; }

.row .thumb {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 3px;
  border: 1px solid var(--panel-border);
  background: rgba(0,0,0,0.5);
  object-fit: cover;
}
.row .thumb.round { border-radius: 50%; }
.row .thumb.blank { background: rgba(57,255,143,0.07); }

.row .txt { flex: 1 1 120px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.row .l1, .row .l2 { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .l1 { font-size: 0.86rem; }
.row .l2 { font-size: 0.74rem; color: var(--text-dim); }
.row .chev { flex: 0 0 auto; color: var(--hud-green-dim); font-size: 1rem; padding-right: 4px; }
.row .r-bpm {
  flex: 0 0 auto;
  color: var(--hud-orange);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}
.row .r-time { flex: 0 0 auto; color: var(--text-dim); font-size: 0.78rem; font-variant-numeric: tabular-nums; }
.more-btn { width: 100%; margin-top: 8px; }
/* No min-width override: 38px is under the sitewide 44px touch minimum, and
   these are the load-to-deck buttons -- the most-tapped control in the browser. */
.row .hud-btn { padding: 4px 8px; }

.statusbar {
  display: flex;
  gap: 10px;
  align-items: center;
  font-size: 0.74rem;
  color: var(--text-dim);
  padding: 0 6px;
}

/* Wide content must scroll inside its own box; the page body must never
   scroll sideways. */
@media (max-width: 760px) {
  .pads { grid-template-columns: repeat(4, 1fr); }
  .deck-body { flex-wrap: wrap; justify-content: center; }
  .waveform { height: 84px; }
}

/* ---------------------------------------------------------- FX + sampler */

.fxbar {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: center;
  background: var(--bg-panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 8px 10px;
}
.fx-rack, .sampler { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.sampler { flex: 1 1 320px; min-width: 0; }
#fx-type {
  min-height: var(--touch);
  padding: 6px 10px;
  background: rgba(0,0,0,.45);
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  color: var(--text-main);
  font-family: "Press Start 2P", monospace;
  font-size: .5rem;
}
.fx-beats { display: flex; gap: 3px; }
.fx-beats .hud-btn { padding: 4px 6px; }
.hud-btn.fx-on.on { background: var(--hud-orange); border-color: var(--hud-orange); color: #04120c; }
/* The sampler pads share the deck pad styling but must not stretch across the
   whole bar when there is room to spare. */
/* auto-fit rather than a fixed 8 columns: eight pads squeezed into whatever
   room is left beside the FX rack came out 33px wide, under the touch
   minimum. They wrap to a second row instead. */
.sampler-pads {
  flex: 1 1 380px;
  min-width: 0;
  grid-template-columns: repeat(auto-fit, minmax(46px, 1fr));
}
.pad.loaded { border-color: var(--hud-blue); }
.pad.firing { background: var(--hud-blue); color: #04120c; }

/* ------------------------------------------------------------------ MIDI */

.midi-list { max-height: 320px; overflow-y: auto; margin: 10px 0; }
.midi-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  border-bottom: 1px solid rgba(57,255,143,.09);
  min-height: var(--touch);
}
.midi-row .m-name { flex: 1 1 auto; font-size: .8rem; }
.midi-row .m-bound { flex: 0 0 auto; font-size: .7rem; color: var(--hud-blue); }
.midi-row .hud-btn { padding: 4px 8px; }
.midi-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.midi-row.learning { background: rgba(255,145,48,.14); }
