/* dj.css — the ManyHand DJ console. */

:root{
  --cream:#faf5ec; --paper:#fffdf8; --ink:#221a12; --inksoft:#6f6152;
  --brand:#0e386d; --brand2:#0b7d74; --line:#e8ddc9;

  --bg:#0a0c11; --panel:#141821; --panel2:#1a1f2a; --panel3:#212836;
  --edge:#2a3140; --edge2:#39435a;
  --text:#e9eef6; --dim:#8b95a7; --faint:#7d8799;
  --accent:#ffb62e; --a-blue:#4fa8ff; --a-orange:#ff9d3c;
  --green:#39d98a; --red:#ff4d4d; --purple:#a97bff;
  --radius:14px;
}

*{ box-sizing:border-box; margin:0; padding:0; -webkit-tap-highlight-color:transparent; }
html,body{ height:100%; }
body{
  font-family:"Hanken Grotesk",system-ui,-apple-system,sans-serif;
  background:var(--cream); color:var(--ink); line-height:1.5;
  display:flex; flex-direction:column; min-height:100%;
}

header.site{ display:flex; align-items:center; justify-content:space-between; padding:12px 18px;
  border-bottom:1.5px solid var(--line); background:var(--paper); }
header.site .brand{ font-family:"Fraunces",Georgia,serif; font-weight:900; font-size:20px; letter-spacing:-.02em;
  color:var(--brand); text-decoration:none; display:flex; align-items:center; gap:8px; }
header.site .brand span{ color:var(--brand2); }
header.site .back{ font-size:13px; font-weight:700; color:var(--brand); text-decoration:none; }

/* the console spans the window; only the reading content keeps a measure */
main{ width:100%; max-width:2200px; margin:0 auto; padding:16px 14px calc(36px + env(safe-area-inset-bottom)); overflow-x:clip; }
#stage{ width:100%; }
h1.title{ font-family:"Fraunces",Georgia,serif; font-weight:900; font-size:28px; text-align:center; margin:2px 0; }
.sub{ text-align:center; color:var(--inksoft); font-size:14.5px; margin-bottom:14px; }

/* first visit only: says the console is already yours to poke at, then gets
   out of the way for good the moment a track lands */
#firstrun{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap; justify-content:center;
  max-width:820px; margin:0 auto 12px; padding:9px 14px;
  background:var(--paper); border:1.5px solid var(--line); border-radius:12px;
}
#firstrun[hidden]{ display:none; }
#firstrun p{ flex:1 1 320px; font-size:13.5px; color:var(--inksoft); line-height:1.45; }
#firstrun b{ color:var(--ink); }
#firstrun .mini{ flex:0 0 auto; padding:7px 14px; font-size:12px;
  background:var(--brand); border-color:var(--brand); color:#fff; border-radius:8px; }
#firstrun .mini:hover{ filter:brightness(1.12); }

/* short windows: give the console back the space the page furniture was using */
@media (max-height:1000px){
  main{ padding-top:8px; }
  h1.title{ font-size:19px; margin:0; }
  .sub{ display:none; }
}
@media (max-height:820px){
  header.site{ padding:7px 18px; }
  header.site .brand{ font-size:17px; }
  h1.title{ font-size:16px; }
  /* a short window needs the height for the console — but a stacked layout
     scrolls, so there the hint costs nothing and is worth more */
  body:not(.dj-stack) #firstrun{ display:none; }
  .tabbar{ margin:8px 0 6px; }
  .tabbar button{ padding:5px 11px; font-size:11px; }
}


footer.site{ margin-top:auto; text-align:center; padding:16px; font-size:13px; color:var(--inksoft);
  border-top:1.5px solid var(--line); background:var(--paper); }
footer.site a{ color:var(--brand); font-weight:700; }

/* ------------------------------------------------------------ rig shell */
/* The console is scaled to whatever height the window leaves, so the whole
   instrument is always on screen without scrolling. */
/* The stage is laid out wider than its container and scaled back down, so it
   is anchored top-left: an over-wide block cannot be centred by auto margins,
   and scaling about the centre would push it off to one side. Scaling about
   the left corner lands its right edge exactly on the container's. */
#stage{ margin:0; transform-origin:top left; }
.rig{
  container-type:inline-size; container-name:rig;
  background:linear-gradient(180deg,#171c26,#0c0f15);
  border:1.5px solid var(--edge); border-radius:18px; padding:12px;
  color:var(--text); box-shadow:0 26px 60px -30px rgba(0,0,0,.85), inset 0 1px 0 rgba(255,255,255,.05);
}
.console{ display:grid; grid-template-columns:minmax(0,1fr) 272px minmax(0,1fr); gap:10px; align-items:start; }
@container rig (min-width:1180px){ .console{ grid-template-columns:minmax(0,1fr) 330px minmax(0,1fr); gap:12px; } }

/* ---------------------------------------------------------------- deck */
.deck{
  background:var(--panel); border:1px solid var(--edge); border-radius:var(--radius);
  padding:10px; display:flex; flex-direction:column; gap:8px; position:relative; min-width:0;
  /* the deck lays itself out from its own width, not the window's — the console
     is scaled, so the viewport is not what decides how much room a deck has */
  container-type:inline-size; container-name:deck;
}
.deck.focused{ border-color:var(--edge2); box-shadow:0 0 0 1px rgba(255,182,46,.25); }
.deck[id="deckA"]{ --deck-accent:var(--a-blue); }
.deck[id="deckB"]{ --deck-accent:var(--a-orange); }
.deck.over{ outline:2px dashed var(--accent); outline-offset:-6px; }

.deck-top{ display:flex; align-items:center; gap:8px; min-height:24px; }
.dtag{ font-size:10.5px; font-weight:800; letter-spacing:.14em; color:var(--deck-accent); }
.dname{ flex:1; min-width:0; font-size:12.5px; font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.badge{ font-size:11px; font-weight:800; padding:2px 6px; border-radius:6px; background:var(--panel3); border:1px solid var(--edge); }
.badge.bpm{ color:var(--accent); font-variant-numeric:tabular-nums; }
.badge.key{ color:var(--green); }
.badge.dim{ color:var(--faint); }
.linkbtn{ font:inherit; font-size:11px; font-weight:700; color:var(--dim); background:none; border:0; cursor:pointer; text-decoration:underline; }
.linkbtn:hover{ color:var(--text); }
button.badge.bpm{ cursor:pointer; font-family:inherit; }
button.badge.bpm:hover{ border-color:var(--accent); }

/* tempo + beat-grid editor */
.gridedit{ position:absolute; z-index:8; top:34px; left:10px; right:10px;
  background:var(--panel3); border:1px solid var(--edge2); border-radius:10px; padding:8px;
  display:flex; flex-direction:column; gap:6px; box-shadow:0 14px 30px -14px #000; }
.gridedit[hidden]{ display:none; }
.ge-row{ display:flex; gap:5px; align-items:center; flex-wrap:wrap; }
.ge-row label{ font-size:10px; font-weight:800; letter-spacing:.08em; color:var(--dim); display:flex; align-items:center; gap:4px; }
.ge-row input{ font:inherit; font-size:12px; width:72px; padding:3px 5px; border-radius:6px;
  background:var(--panel); color:var(--text); border:1px solid var(--edge); font-variant-numeric:tabular-nums; }
.ge-lab{ font-size:10px; font-weight:800; letter-spacing:.08em; color:var(--dim); }

.wavewrap{ position:relative; }
.wave-detail{ width:100%; height:84px; display:block; background:#080a0f; border:1px solid var(--edge); border-radius:8px; cursor:ew-resize; touch-action:none; }
.wave-over{ width:100%; height:34px; display:block; background:#080a0f; border:1px solid var(--edge); border-radius:8px; cursor:pointer; margin-top:4px; }
.wave-tools{ position:absolute; right:6px; top:6px; display:flex; gap:4px; opacity:.55; }
.wave-tools:hover{ opacity:1; }
.timebar{ display:flex; justify-content:space-between; font-size:12px; font-variant-numeric:tabular-nums; color:var(--dim); margin-top:4px; }
.deck.ending .t-rem{ color:var(--red); animation:blink 1s steps(2) infinite; }
@keyframes blink{ 50%{ opacity:.35; } }

/* The deck body stacks by default. Given enough width it splits in two — jog
   and tempo on the left, everything you press on the right — which makes the
   deck markedly shorter, so a wide window fills its width instead of scaling
   the whole console down to fit the height. */
.deck-body{ display:flex; flex-direction:column; gap:8px; }
.deck-ops{ display:flex; flex-direction:column; gap:8px; container-type:inline-size; container-name:ops; }
@container deck (min-width:490px){
  .deck-body{ display:grid; grid-template-columns:auto minmax(0,1fr); gap:12px; align-items:start; }
  .deck-ops{ gap:7px; }
}

.deck-mid{ display:grid; grid-template-columns:1fr 108px; gap:10px; align-items:center; }

/* jog wheel */
.jogcol{ display:flex; flex-direction:column; align-items:center; gap:8px; }
.jog{ position:relative; width:168px; max-width:100%; aspect-ratio:1; border-radius:50%; touch-action:none; cursor:grab;
  background:radial-gradient(circle at 50% 42%, #2b3140 0 46%, #1b2029 46% 100%);
  box-shadow:0 12px 30px -14px #000, inset 0 0 0 1px #39435a; user-select:none; }
.jog.grab{ cursor:grabbing; }
.jog-ring{ position:absolute; inset:0; border-radius:50%;
  background:repeating-conic-gradient(from 0deg,#252b38 0 2deg,#1c212b 2deg 4deg);
  -webkit-mask:radial-gradient(circle, transparent 0 74%, #000 74.5%);
  mask:radial-gradient(circle, transparent 0 74%, #000 74.5%); }
.jog-plate{ position:absolute; inset:12%; border-radius:50%;
  background:
    radial-gradient(circle at center, #0d0f14 0 26%, #14171e 26% 28%, #0a0c10 28%),
    repeating-radial-gradient(circle at center, #141821 0 2px, #0d0f14 2px 4px);
  box-shadow:inset 0 0 0 4px #262c39, inset 0 0 30px rgba(0,0,0,.7); display:grid; place-items:center; }
.jog-marker{ position:absolute; left:50%; top:4%; width:3px; height:16%; margin-left:-1.5px; border-radius:2px;
  background:var(--deck-accent); box-shadow:0 0 8px var(--deck-accent); }
.jog-label{ text-align:center; }
.jog-label b{ display:block; font-family:"Fraunces",Georgia,serif; font-size:22px; color:var(--deck-accent); }
.jog-label small{ display:block; font-size:8.5px; letter-spacing:.08em; color:var(--faint); max-width:78px; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
.jog-pos{ position:absolute; inset:-4px; border-radius:50%; pointer-events:none;
  background:conic-gradient(var(--deck-accent) calc(var(--turn,0) * 360deg), transparent 0);
  -webkit-mask:radial-gradient(circle, transparent 0 96%, #000 96.5%);
  mask:radial-gradient(circle, transparent 0 96%, #000 96.5%); opacity:.9; }
.jogmode{ display:flex; gap:4px; flex-wrap:wrap; justify-content:center; }

/* pitch column */
.pitchcol{ display:flex; flex-direction:column; align-items:center; gap:5px; }
.pitchhead{ display:flex; gap:4px; align-items:center; flex-wrap:wrap; justify-content:center; }
.pfader{ position:relative; height:154px; width:44px; display:grid; place-items:center;
  background:linear-gradient(180deg,#0e1117,#131822); border:1px solid var(--edge); border-radius:8px; }
.pfader::before{ content:''; position:absolute; left:50%; top:8px; bottom:8px; width:3px; margin-left:-1.5px;
  background:#080a0f; border-radius:2px; box-shadow:inset 0 0 0 1px #2a3140; }
.pfader::after{ content:''; position:absolute; left:6px; right:6px; top:50%; height:1px; background:var(--accent); opacity:.5; }
.pitch-input{ width:138px; transform:rotate(-90deg); }
.pitchval{ font-size:12px; font-weight:800; font-variant-numeric:tabular-nums; color:var(--accent); }
.pitchbtns{ display:flex; flex-direction:column; gap:5px; align-items:center; }
.bendrow,.keyrow{ display:flex; gap:4px; align-items:center; }
.keyval{ font-size:11px; font-weight:800; min-width:20px; text-align:center; color:var(--green); }

/* transport */
.transport{ display:grid; grid-template-columns:repeat(4,1fr); gap:6px; }
.tbtn{ font:inherit; font-size:12px; font-weight:800; letter-spacing:.06em; padding:10px 4px; border-radius:9px;
  border:1px solid var(--edge2); background:linear-gradient(180deg,var(--panel3),var(--panel2)); color:var(--text); cursor:pointer; }
.tbtn:hover{ border-color:var(--dim); }
.tbtn.play.on{ background:linear-gradient(180deg,#2f8f5c,#1d6b43); border-color:#48c98a; color:#fff; }
.tbtn.cue.on{ background:linear-gradient(180deg,#b86b1e,#8c4f13); border-color:var(--accent); color:#fff; }
.tbtn.sync.on{ background:linear-gradient(180deg,#2f6fd0,#20509b); border-color:var(--a-blue); color:#fff; }
.tbtn.master.on{ background:linear-gradient(180deg,#c1932b,#916d1c); border-color:var(--accent); color:#241a05; }
.tricks{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:5px; }
.tricks .mini{ font-size:9.5px; padding:5px 2px; overflow:hidden; white-space:nowrap; }

/* loop bar */
.loopbar{ display:flex; gap:4px; align-items:center; justify-content:center; flex-wrap:wrap;
  background:var(--panel2); border:1px solid var(--edge); border-radius:9px; padding:5px 6px; }
.loopsize{ font-size:11px; font-weight:800; color:var(--accent); min-width:52px; text-align:center; font-variant-numeric:tabular-nums; flex:1 1 auto; }
.deck.looping .loopbar{ border-color:var(--accent); box-shadow:0 0 0 1px rgba(255,182,46,.25); }

/* pads + fx share a row once the deck is wide enough */
.deck-lower{ display:grid; grid-template-columns:1fr; gap:8px; }
@container ops (min-width:430px){ .deck-lower{ grid-template-columns:minmax(0,1.25fr) minmax(0,1fr); align-items:start; } }
.padblock{ display:flex; flex-direction:column; gap:6px; }
.padmodes{ display:grid; grid-template-columns:repeat(5,1fr); gap:4px; }
.padmode{ font:inherit; font-size:10px; font-weight:800; letter-spacing:.03em; padding:5px 2px; border-radius:7px;
  border:1px solid var(--edge); background:var(--panel2); color:var(--dim); cursor:pointer; }
.padmode.on{ background:var(--panel3); color:var(--text); border-color:var(--edge2); }
.pads{ display:grid; grid-template-columns:repeat(4,1fr); gap:5px; }
.pad{ position:relative; font:inherit; border:1px solid var(--edge); border-radius:9px; padding:9px 4px 7px;
  background:linear-gradient(180deg,var(--panel2),#12161f); color:var(--text); cursor:pointer; min-height:44px;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px; overflow:hidden; }
.pad .pl{ font-size:11.5px; font-weight:800; letter-spacing:.02em; max-width:100%; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
.pad .ps{ font-size:9px; color:var(--faint); }
.pad.set{ border-color:var(--pc,#888); box-shadow:inset 0 -3px 0 var(--pc,#888); }
.pad.on,.pad.hit{ background:var(--pc,var(--accent)); color:#0b0c10; }
.pad.on .ps,.pad.hit .ps{ color:rgba(0,0,0,.6); }

/* deck fx */
.fxblock{ background:var(--panel2); border:1px solid var(--edge); border-radius:9px; padding:7px 8px; display:flex; flex-direction:column; gap:6px; }
.fxhead{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.fxtag{ font-size:10px; font-weight:800; letter-spacing:.14em; color:var(--purple); }
.fxknobs{ display:flex; gap:12px; justify-content:center; flex-wrap:wrap; }

/* ---------------------------------------------------------- drop zone ---
   Only the waveform is meaningless on an empty deck, so the load prompt
   covers exactly that and no more. The jog, transport, pads, loops and FX
   stay on show: what the deck can do is visible before a file is picked.  */
.wavezone{ position:relative; }
.drop{
  position:absolute; inset:0; z-index:4; border-radius:8px;
  display:grid; place-items:center; padding:7px; cursor:pointer;
  background:
    radial-gradient(120% 150% at 16% 0%, color-mix(in srgb, var(--deck-accent) 16%, transparent), transparent 62%),
    linear-gradient(180deg, #151a24, #0c1017);
  border:1px solid var(--edge);
}
.deck.loaded .drop{ display:none; }

.dropinner{
  width:100%; height:100%;
  display:flex; align-items:center; justify-content:center; gap:12px; flex-wrap:wrap;
  padding:8px 12px; border-radius:10px;
  border:1.5px dashed color-mix(in srgb, var(--deck-accent) 40%, var(--edge2));
  background:color-mix(in srgb, var(--deck-accent) 5%, transparent);
  transition:border-color .16s, background .16s;
}
.drop:hover .dropinner{ border-color:color-mix(in srgb, var(--deck-accent) 70%, var(--edge2)); }

/* artwork — a record, drawn rather than an emoji so it matches the console */
.drop-art{ flex:0 0 auto; display:block; width:46px; height:46px; transition:transform .18s ease; }
.drop-art svg{ width:100%; height:100%; }
.drop-art circle,.drop-art path{ fill:none; stroke:var(--deck-accent); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; }
.da-disc{ opacity:.95; }
.da-groove{ opacity:.3; stroke-width:1.1; }
.da-label{ fill:color-mix(in srgb, var(--deck-accent) 28%, transparent); stroke-width:1.6; }
.da-pin{ fill:var(--deck-accent); stroke:none; }
.da-shine{ opacity:.55; stroke-width:2.5; }

/* copy */
/* the copy asks for enough room to stay on one line each; when the deck is too
   narrow for that the buttons take a row of their own rather than squeezing it */
.drop-text{ flex:1 1 215px; min-width:0; display:flex; flex-direction:column; gap:3px; }
.drop-title{ font-size:13.5px; font-weight:700; color:var(--text); line-height:1.3; }
.drop-title b{ color:var(--deck-accent); font-weight:800; }
.drop-title .t-over{ display:none; color:var(--deck-accent); }
.drop-formats{ font-size:9.5px; font-weight:700; letter-spacing:.05em; color:var(--faint); line-height:1.35; }
.drop-actions{ flex:0 0 auto; display:flex; align-items:center; gap:6px; flex-wrap:wrap; justify-content:center; }
.drop-cta{
  font:inherit; font-size:12px; font-weight:800; letter-spacing:.03em; cursor:pointer;
  padding:8px 14px; border-radius:9px; color:#0b0d12;
  border:1px solid color-mix(in srgb, var(--deck-accent) 60%, #fff);
  background:linear-gradient(180deg, color-mix(in srgb, var(--deck-accent) 88%, #fff), var(--deck-accent));
  box-shadow:0 6px 16px -8px var(--deck-accent);
}
.drop-cta:hover{ filter:brightness(1.08); }
.drop-alt{
  font:inherit; font-size:11.5px; font-weight:700; cursor:pointer;
  padding:7px 11px; border-radius:9px; color:var(--text);
  border:1px solid var(--edge2); background:var(--panel2);
}
.drop-alt:hover{ border-color:var(--deck-accent); color:#fff; }
.drop-cta[disabled],.drop-alt[disabled]{ opacity:.6; cursor:progress; }
.drop-cta:focus-visible,.drop-alt:focus-visible{ outline:2px solid #fff; outline-offset:2px; }

/* An empty deck is legible but plainly inert: every control is there to read,
   it just has nothing to act on yet. */
.deck .deck-body{ transition:opacity .2s ease; }
.deck:not(.loaded) .deck-body{ opacity:.62; }

/* dragging a file over the deck */
.deck.over{ outline-color:var(--deck-accent); }
.deck.over .dropinner{
  border-color:var(--deck-accent); border-style:solid;
  background:color-mix(in srgb, var(--deck-accent) 15%, transparent);
}
.deck.over .drop-title .t-idle{ display:none; }
.deck.over .drop-title .t-over{ display:inline; }
.deck.over .drop-art{ transform:scale(1.08) rotate(8deg); }
@media (prefers-reduced-motion:reduce){
  .dropinner,.drop-art,.deck .deck-body{ transition:none; }
  .deck.over .drop-art{ transform:none; }
}

/* narrow decks: the prompt loses its trimmings before it loses its buttons */
@container deck (max-width:430px){
  .drop-art{ display:none; }
  .drop-formats{ display:none; }
  .dropinner{ gap:8px; padding:7px 8px; }
  .drop-title{ font-size:12.5px; }
}
.analysing{ position:absolute; left:10px; bottom:10px; z-index:5; font-size:11px; color:var(--accent);
  background:rgba(10,12,17,.9); border:1px solid var(--edge); border-radius:20px; padding:4px 10px; display:flex; gap:6px; align-items:center; }
.analysing[hidden]{ display:none; }
.spinner{ width:10px; height:10px; border-radius:50%; border:2px solid var(--accent); border-top-color:transparent; animation:spin .8s linear infinite; }
@keyframes spin{ to{ transform:rotate(360deg); } }

/* --------------------------------------------------------------- mixer */
.mixer{ background:var(--panel); border:1px solid var(--edge); border-radius:var(--radius); padding:10px; container-type:inline-size; container-name:mixer;
  display:grid; grid-template-columns:1fr 84px 1fr; gap:8px; }
.strip{ display:flex; flex-direction:column; align-items:center; gap:8px; min-width:0; }
.striphead{ font-size:10px; font-weight:800; letter-spacing:.14em; color:var(--dim); }
.stripknobs{ display:flex; flex-direction:column; align-items:center; gap:7px; }
.faderrow{ display:flex; align-items:flex-end; gap:6px; }
.chmeter{ width:9px; height:150px; background:#080a0f; border:1px solid var(--edge); border-radius:4px; }
.assign{ display:flex; gap:2px; }
.asg{ font:inherit; font-size:9.5px; font-weight:800; width:24px; padding:3px 0; border-radius:5px;
  border:1px solid var(--edge); background:var(--panel2); color:var(--faint); cursor:pointer; }
.asg.on{ background:var(--panel3); color:var(--accent); border-color:var(--edge2); }
.cuebtn.on{ background:linear-gradient(180deg,#b86b1e,#8c4f13); border-color:var(--accent); color:#fff; }

.mixcentre{ display:flex; flex-direction:column; align-items:center; gap:8px; }
.masterbpm{ text-align:center; }
.masterbpm small{ display:block; font-size:8.5px; letter-spacing:.12em; color:var(--faint); }
.masterbpm b{ font-size:17px; color:var(--accent); font-variant-numeric:tabular-nums; }
.phase{ width:100%; height:26px; background:#080a0f; border:1px solid var(--edge); border-radius:5px; }
.mastermeters{ display:flex; gap:4px; }
.mastermeters canvas{ width:9px; height:120px; background:#080a0f; border:1px solid var(--edge); border-radius:4px; }
.mlab{ font-size:9px; letter-spacing:.14em; color:var(--faint); }

.xfhost{ margin-top:10px; background:var(--panel); border:1px solid var(--edge); border-radius:var(--radius); padding:10px 14px;
  display:flex; align-items:center; gap:14px; flex-wrap:wrap; justify-content:center; }
.xfrow{ display:flex; align-items:center; gap:10px; flex:1; min-width:260px; }
.xlab{ font-size:10px; font-weight:800; letter-spacing:.12em; color:var(--dim); }
.fader.horiz{ flex:1; }
.fader.horiz .fader-input{ width:100%; }
.xftools{ display:flex; gap:8px; align-items:center; }

/* --------------------------------------------------------------- knobs */
.knobcell{ display:flex; flex-direction:column; align-items:center; gap:2px; width:58px; }
.knob{ position:relative; width:44px; height:44px; border-radius:50%; cursor:ns-resize; touch-action:none;
  background:radial-gradient(circle at 50% 38%, #39414f, #1b202a 70%);
  box-shadow:0 3px 8px -3px #000, inset 0 0 0 1px #39435a; }
.knob.small{ width:38px; height:38px; }
.knob svg{ position:absolute; inset:-4px; width:calc(100% + 8px); height:calc(100% + 8px); overflow:visible; }
.knob .k-track{ fill:none; stroke:#2a3140; stroke-width:3; stroke-linecap:round; }
.knob .k-val{ fill:none; stroke:var(--accent); stroke-width:3; stroke-linecap:round; }
.knob .k-ind{ position:absolute; left:50%; top:6px; width:2.5px; height:13px; margin-left:-1.25px; border-radius:2px;
  background:var(--text); transform-origin:50% 16px; }
.knob:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; }
.knob.centered .k-val{ stroke:var(--faint); }
.k-label{ font-size:9px; font-weight:800; letter-spacing:.09em; color:var(--dim); }
.k-read{ font-size:9.5px; color:var(--faint); font-variant-numeric:tabular-nums; }

/* -------------------------------------------------------------- faders */
.fader{ position:relative; display:grid; place-items:center; }
.fader.vert{ width:44px; }
.fader.vert .fader-input{ transform:rotate(-90deg); }
.fader-input{ -webkit-appearance:none; appearance:none; background:transparent; height:22px; }
.fader-input::-webkit-slider-runnable-track{ height:5px; border-radius:3px; background:#080a0f; box-shadow:inset 0 0 0 1px #2a3140; }
.fader-input::-moz-range-track{ height:5px; border-radius:3px; background:#080a0f; box-shadow:inset 0 0 0 1px #2a3140; }
.fader-input::-webkit-slider-thumb{ -webkit-appearance:none; width:16px; height:30px; margin-top:-12px; border-radius:4px; cursor:grab;
  background:linear-gradient(180deg,#e9eef6,#9aa4b6); box-shadow:0 2px 6px -1px #000, inset 0 -2px 0 rgba(0,0,0,.25); }
.fader-input::-moz-range-thumb{ width:16px; height:30px; border-radius:4px; border:0; cursor:grab;
  background:linear-gradient(180deg,#e9eef6,#9aa4b6); }
.fader.xf .fader-input::-webkit-slider-thumb{ width:22px; height:34px; }
.pitch-input{ -webkit-appearance:none; appearance:none; background:transparent; height:22px; }
.pitch-input::-webkit-slider-runnable-track{ height:4px; border-radius:3px; background:transparent; }
.pitch-input::-moz-range-track{ height:4px; background:transparent; }
.pitch-input::-webkit-slider-thumb{ -webkit-appearance:none; width:18px; height:34px; margin-top:-15px; border-radius:4px;
  background:linear-gradient(180deg,#f4f7fb,#8e99ab); box-shadow:0 2px 6px -1px #000; cursor:grab; }
.pitch-input::-moz-range-thumb{ width:18px; height:34px; border:0; border-radius:4px; background:linear-gradient(180deg,#f4f7fb,#8e99ab); }

/* ------------------------------------------------------------- buttons */
.btn,.mini,.chip{ font:inherit; cursor:pointer; border-radius:7px; border:1px solid var(--edge);
  background:linear-gradient(180deg,var(--panel3),var(--panel2)); color:var(--text); }
.btn{ font-size:11.5px; font-weight:800; letter-spacing:.05em; padding:7px 11px; }
.mini{ font-size:10.5px; font-weight:700; padding:5px 8px; }
.chip{ font-size:9.5px; font-weight:800; letter-spacing:.08em; padding:4px 7px; color:var(--dim); }
.chip.on{ color:#1a1205; background:linear-gradient(180deg,#ffcb5c,#e0a02a); border-color:#ffcb5c; }
.mini.on{ color:#1a1205; background:linear-gradient(180deg,#ffcb5c,#e0a02a); border-color:#ffcb5c; }
.mini.ghost{ background:none; color:var(--faint); }
.mini.primary{ background:linear-gradient(180deg,#2f8f5c,#1d6b43); border-color:#48c98a; color:#fff; text-decoration:none; display:inline-block; }
.btn:hover,.mini:hover,.chip:hover{ border-color:var(--edge2); }
.recbtn.on{ background:linear-gradient(180deg,#d4413f,#9d2422); border-color:#ff6a68; color:#fff; animation:pulse 1.6s infinite; }
@keyframes pulse{ 50%{ opacity:.72; } }
.sel{ font:inherit; font-size:11px; padding:4px 6px; border-radius:6px; background:var(--panel2);
  color:var(--text); border:1px solid var(--edge); }
.sel.tiny{ font-size:10px; padding:3px 4px; }

/* --------------------------------------------------------------- tabs */
.tabbar{ display:flex; gap:6px; justify-content:center; flex-wrap:wrap; margin:12px 0 8px; }
.tabbar button{ font:inherit; font-size:11.5px; font-weight:800; letter-spacing:.06em; padding:7px 13px; border-radius:20px;
  border:1px solid var(--edge); background:var(--panel2); color:var(--dim); cursor:pointer; }
.tabbar button.on{ background:var(--panel3); color:var(--text); border-color:var(--edge2); }

.panels{ margin-top:4px; }
.panel{ display:none; background:var(--panel); border:1px solid var(--edge); border-radius:var(--radius); padding:12px; color:var(--text); }

/* On a desktop the panels slide over the console as a drawer rather than
   stacking underneath it, so nothing is ever pushed off the window. */
body:not(.dj-stack) .panels{
  position:fixed; left:0; right:0; bottom:0; z-index:40;
  margin:0; padding:0 14px; pointer-events:none;
  display:flex; justify-content:center;
}
body:not(.dj-stack) .panel{
  pointer-events:auto; width:100%; max-width:1100px;
  max-height:min(64vh,540px); overflow:auto;
  border-radius:16px 16px 0 0; border-bottom:0;
  box-shadow:0 -24px 60px -24px rgba(0,0,0,.85);
  animation:drawerUp .18s ease-out;
}
@keyframes drawerUp{ from{ transform:translateY(14px); opacity:.4; } }
@media (prefers-reduced-motion:reduce){ body:not(.dj-stack) .panel{ animation:none; } }
.panelhead{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:10px; }
.panelhead h2{ margin:0; }
.panelclose{ font:inherit; font-size:12px; font-weight:800; cursor:pointer; color:var(--dim);
  background:var(--panel2); border:1px solid var(--edge); border-radius:7px; padding:4px 9px; }
.panelclose:hover{ color:var(--text); border-color:var(--edge2); }
body.dj-stack .panelclose{ display:none; }
body[data-view="master"] .panel[data-panel="master"],
body[data-view="sampler"] .panel[data-panel="sampler"],
body[data-view="library"] .panel[data-panel="library"],
body[data-view="midi"] .panel[data-panel="midi"],
body[data-view="settings"] .panel[data-panel="settings"]{ display:block; }
.panel h2{ font-size:13px; letter-spacing:.1em; text-transform:uppercase; color:var(--dim); margin-bottom:10px; font-weight:800; }
.panel .dim{ color:var(--faint); font-size:12px; }

/* master panel */
.masterknobs{ display:flex; gap:16px; flex-wrap:wrap; align-items:flex-start; }
.outrow,.recrow-top{ display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-top:12px; }
.rectime{ font-size:12px; font-variant-numeric:tabular-nums; color:var(--dim); min-width:44px; }
.reclist{ margin-top:10px; display:flex; flex-direction:column; gap:8px; }
.recrow{ display:flex; gap:8px; align-items:center; flex-wrap:wrap; font-size:12px; }
.recrow audio{ height:30px; max-width:260px; }
.spectrum{ width:100%; height:70px; background:#080a0f; border:1px solid var(--edge); border-radius:8px; margin-top:12px; display:block; }

/* sampler */
.spads{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:7px; }
.spad{ font:inherit; border:1px solid var(--edge); border-radius:10px; padding:14px 6px; cursor:pointer;
  background:linear-gradient(180deg,var(--panel2),#12161f); color:var(--text); display:flex; flex-direction:column; gap:3px; align-items:center; }
.spad .pl{ font-size:12px; font-weight:800; }
.spad .ps{ font-size:9.5px; color:var(--faint); }
.spad.hit{ background:var(--purple); color:#11081f; }
.spad.looping{ border-color:var(--green); box-shadow:inset 0 -3px 0 var(--green); }
.spad.over{ border-color:var(--accent); }
.stools{ display:flex; gap:12px; align-items:center; margin-top:12px; flex-wrap:wrap; }

/* library */
.libtools{ display:flex; gap:8px; margin-bottom:10px; flex-wrap:wrap; }
.libtools input{ font:inherit; font-size:12px; padding:6px 9px; border-radius:7px; background:var(--panel2);
  color:var(--text); border:1px solid var(--edge); flex:1; min-width:160px; }
.lib-row{ display:grid; grid-template-columns:1fr 54px 54px 44px auto; gap:8px; align-items:center;
  padding:7px 8px; border-bottom:1px solid var(--edge); font-size:12px; cursor:grab; }
.lib-row:hover{ background:var(--panel2); }
.lib-row.working{ opacity:.6; }
.lb-name{ overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
.lb-dur,.lb-bpm{ font-variant-numeric:tabular-nums; color:var(--dim); }
.lb-bpm{ color:var(--accent); }
.lb-key{ color:var(--green); font-weight:700; }
.lb-acts{ display:flex; gap:4px; }
.lib-empty{ padding:22px 10px; text-align:center; color:var(--faint); font-size:12.5px; }
#libraryPanel.over{ outline:2px dashed var(--accent); outline-offset:-6px; }
#suggestions{ margin-top:10px; font-size:12px; color:var(--dim); display:flex; gap:6px; align-items:center; flex-wrap:wrap; }

/* midi */
.midirow{ display:grid; grid-template-columns:80px 1fr auto auto; gap:8px; align-items:center;
  padding:6px 4px; border-bottom:1px solid var(--edge); font-size:12px; }
.midirow code{ font-size:11px; color:var(--accent); }
.miditools{ display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-bottom:10px; }
body.midi-learn-mode .knob,body.midi-learn-mode .fader,body.midi-learn-mode .pad,
body.midi-learn-mode .btn,body.midi-learn-mode .spad{ outline:1px dashed rgba(255,182,46,.5); }
.learn-armed{ outline:2px solid var(--accent) !important; animation:pulse 1s infinite; }

/* settings */
.settingrow{ display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-bottom:10px; }

/* ------------------------------------------------------------- overlay */
#help{ position:fixed; inset:0; z-index:60; background:rgba(6,8,12,.86); display:grid; place-items:center; padding:20px; }
#help[hidden]{ display:none; }
.helpcard{ background:var(--panel); border:1px solid var(--edge2); border-radius:16px; padding:20px; max-width:640px; width:100%;
  max-height:80vh; overflow:auto; color:var(--text); }
.helpcard h3{ font-family:"Fraunces",Georgia,serif; font-size:20px; margin-bottom:12px; }
.krow{ display:grid; grid-template-columns:150px 1fr; gap:10px; padding:5px 0; border-bottom:1px solid var(--edge); font-size:13px; }
kbd{ font-family:ui-monospace,Menlo,Consolas,monospace; font-size:11.5px; background:var(--panel3); border:1px solid var(--edge2);
  border-radius:5px; padding:2px 6px; color:var(--accent); }

#toasts{ position:fixed; left:50%; bottom:20px; transform:translateX(-50%); z-index:70; display:flex; flex-direction:column; gap:8px; align-items:center; }
.toast{ background:#11151d; color:#e9eef6; border:1px solid var(--edge2); border-radius:22px; padding:9px 16px; font-size:13px;
  opacity:0; transform:translateY(8px); transition:.22s; box-shadow:0 12px 30px -12px #000; }
.toast.in{ opacity:1; transform:none; }

#orient{ display:none; position:fixed; right:10px; bottom:10px; z-index:50; font:inherit; font-size:12px; font-weight:800;
  padding:9px 13px; border-radius:22px; border:1px solid var(--edge2); background:#11151d; color:var(--text); cursor:pointer; }

/* --------------------------------------------------------------- prose */
.prose{ max-width:1100px; margin:26px auto 0; background:var(--paper); border:1.5px solid var(--line); border-radius:var(--radius); padding:18px; }
.prose h2{ font-family:"Fraunces",Georgia,serif; font-size:20px; margin-bottom:8px; }
.prose h3{ font-size:15px; margin:16px 0 4px; }
.prose p,.prose li{ color:var(--inksoft); font-size:14.5px; }
.prose ul{ margin:6px 0 6px 20px; }
.prose details{ border-top:1.5px solid var(--line); padding:11px 0; }
.prose details summary{ cursor:pointer; font-weight:700; font-size:14.5px; color:var(--ink); }
.prose a{ color:var(--brand); font-weight:700; }
.step-label{ font-size:11px; font-weight:800; letter-spacing:.14em; text-transform:uppercase; color:var(--brand2); }
.featgrid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:12px; margin-top:10px; }
.feat{ border:1.5px solid var(--line); border-radius:12px; padding:12px; }
.feat b{ display:block; font-size:14px; margin-bottom:2px; }
.feat span{ font-size:13px; color:var(--inksoft); }

/* ---------------------------------------------------------- responsive */
/* keep the real three-column console as far down as it will honestly go, by
   narrowing the mixer rather than stacking the decks */
@media (max-width:1180px) and (min-width:960px){
  .console{ grid-template-columns:minmax(0,1fr) 210px minmax(0,1fr); gap:8px; }
  .mixer{ grid-template-columns:1fr 66px 1fr; padding:8px; gap:6px; }
  .knobcell{ width:48px; }
  .jog{ width:126px; }
  .stripknobs{ gap:5px; }
}
@media (max-width:1180px){
  .jog{ width:150px; }
}
@media (max-width:640px){
  main{ padding:10px 8px 30px; }
  h1.title{ font-size:23px; }
  .deck-mid{ grid-template-columns:1fr 96px; }
  .jog{ width:132px; }
  .pfader{ height:150px; width:40px; } .pitch-input{ width:134px; }
  .wave-detail{ height:78px; }
  .chmeter{ height:150px; } .fader.vert{ width:40px; }
  .knobcell{ width:52px; }
}

/* phone: only one section at a time */
body.dj-stack .console{ display:block; }
body.dj-stack .deck,body.dj-stack .mixer,body.dj-stack .xfhost{ display:none; }
body.dj-stack[data-view="deckA"] #deckA,
body.dj-stack[data-view="deckB"] #deckB{ display:flex; }
body.dj-stack[data-view="mixer"] .mixer,
body.dj-stack[data-view="mixer"] .xfhost{ display:grid; }
body.dj-stack[data-view="mixer"] .xfhost{ display:flex; }
body.dj-stack .tabbar button[data-view="deckA"],
body.dj-stack .tabbar button[data-view="deckB"],
body.dj-stack .tabbar button[data-view="mixer"]{ display:inline-block; }
.tabbar button[data-view="deckA"],
.tabbar button[data-view="deckB"],
.tabbar button[data-view="mixer"]{ display:none; }
body.dj-phone #orient{ display:block; }
body.dj-stack main{ display:flex; flex-direction:column; }
body.dj-stack .tabbar{ order:-1; position:sticky; top:0; z-index:20; background:var(--cream); padding:6px 0; margin:0 0 8px; }
body.dj-stack h1.title{ font-size:20px; }
body.dj-stack .sub{ display:none; }
body.dj-stack h1.title{ margin:0 0 6px; }
:fullscreen main{ max-width:none; }
:fullscreen .prose,:fullscreen header.site,:fullscreen footer.site,
:fullscreen h1.title,:fullscreen .sub,:fullscreen #firstrun{ display:none; }

/* ------------------------------------------------- short-window console ---
   A shorter window gets a physically shorter console, so the fit-to-window
   scaling has little left to do and the lettering stays readable. These sit at
   the end of the file so they win over the base sizes.                      */
@media (max-height:1000px){
  .jog{ width:138px; }
  .wave-detail{ height:66px; }
  .wave-over{ height:26px; }
  .pfader{ height:124px; }
  .pitch-input{ width:108px; }
  .pad{ min-height:36px; padding:6px 4px 5px; }
  .tbtn{ padding:7px 4px; }
  .knob{ width:40px; height:40px; }
  .knob.small{ width:34px; height:34px; }
  .knobcell{ width:52px; }
  .chmeter{ height:150px; }
  .mastermeters canvas{ height:96px; }
  .rig{ padding:9px; }
  .deck{ padding:8px; gap:6px; }
  .fxknobs{ gap:8px; }
}
@media (max-height:760px){
  .jog{ width:120px; }
  .wave-detail{ height:58px; }
  .pfader{ height:108px; }
  .pitch-input{ width:92px; }
  .chmeter{ height:150px; }
  .pad{ min-height:32px; }
}

/* the very tightest windows: heading goes to assistive tech only, and the
   tempo buttons share one row */
@media (max-height:880px){
  h1.title{ position:absolute; width:1px; height:1px; margin:-1px; padding:0;
    overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0; }
  main{ padding-top:6px; }
  .pitchbtns{ flex-direction:row; flex-wrap:wrap; justify-content:center; gap:5px; }
}

/* stacked mode shows one deck at full width, so pads and FX can share a row */
@media (min-width:640px){
}

/* ------------------------------------------------ wide-console mixer ---
   With room to spare the channel knobs pair up two-across instead of running
   down a long column — the mixer stops being the tallest thing on screen.  */
@container mixer (min-width:300px){
  .mixer{ grid-template-columns:1fr 92px 1fr; }
  .stripknobs{ display:grid; grid-template-columns:repeat(2,auto); gap:6px 2px; justify-content:center; }
  .stripknobs .knobcell{ width:48px; }
  .stripknobs .knobcell:first-child{ grid-column:1 / -1; }
}

/* Vertical sliders are rotated range inputs. Centring an over-wide child with
   grid alignment leaves the rotated box off to one side (it was overlapping the
   master column), so pin it to the middle explicitly instead. */
.fader.vert{ position:relative; }
.fader.vert .fader-input{ position:absolute; left:50%; top:50%;
  transform:translate(-50%,-50%) rotate(-90deg); transform-origin:center; margin:0; }
.pfader{ position:relative; }
.pfader .pitch-input{ position:absolute; left:50%; top:50%;
  transform:translate(-50%,-50%) rotate(-90deg); transform-origin:center; margin:0; }

/* ==========================================================================
   Touch devices: finger-sized controls.
   Keyed on the pointer, not the screen — a tablet is as much a touch device as
   a phone, and gating this on width left iPads with mouse-sized controls.
   Layout changes for narrow screens live in the phone block further down.
   ========================================================================== */
body.dj-touch{ --tap:44px; }

body.dj-touch .linkbtn{
  min-width:var(--tap); min-height:var(--tap); padding:0 10px;
  border:1px solid var(--edge); border-radius:10px; background:var(--panel2);
  color:var(--text); text-decoration:none; font-size:12px;
}
body.dj-touch .linkbtn.eject{ font-size:17px; padding:0; }
body.dj-touch button.badge.bpm{ min-height:var(--tap); padding:0 12px; font-size:14px; }
body.dj-touch .badge.key{ min-height:var(--tap); display:flex; align-items:center; font-size:13px; }
body.dj-touch .deck-top{ gap:6px; min-height:var(--tap); }
body.dj-touch .dtag{ font-size:11px; }

body.dj-touch .tbtn{ min-height:52px; font-size:13px; border-radius:11px; }
body.dj-touch .pad{ min-height:56px; }
body.dj-touch .pad .pl{ font-size:13px; }
body.dj-touch .padmode{ min-height:40px; font-size:11px; }
body.dj-touch .chip{ min-height:var(--tap); padding:0 9px; font-size:11px;
  display:inline-flex; align-items:center; }
body.dj-touch .mini{ min-height:var(--tap); min-width:var(--tap); padding:0 10px; font-size:12px;
  display:inline-flex; align-items:center; justify-content:center; }
body.dj-touch .tricks .mini{ font-size:11px; padding:0 4px; }
body.dj-touch .sel{ min-height:var(--tap); font-size:13px; padding:0 8px; }
body.dj-touch .sel.tiny{ font-size:12px; }
body.dj-touch .asg{ min-width:var(--tap); min-height:38px; font-size:12px; }
body.dj-touch .knob{ width:56px; height:56px; }
body.dj-touch .knob.small{ width:48px; height:48px; }
body.dj-touch .knobcell{ width:66px; }
body.dj-touch .k-label{ font-size:10px; }
body.dj-touch .k-read{ font-size:10.5px; }
body.dj-touch .spad{ min-height:64px; }
body.dj-touch .panelclose{ min-height:var(--tap); }
body.dj-touch .drop-cta{ min-height:var(--tap); padding:0 20px; }
body.dj-touch .tabbar button{ min-height:40px; padding:8px 14px; font-size:12px; }
body.dj-touch .opstabs button{ min-height:42px; }

/* sliders need a thicker grab area than a mouse does */
body.dj-touch .fader-input{ height:var(--tap); }
body.dj-touch .fader.vert{ width:56px; }
body.dj-touch .pitch-input{ height:var(--tap); }
body.dj-touch .pfader{ width:56px; }
body.dj-touch .fader-input::-webkit-slider-thumb{ width:22px; height:38px; margin-top:-16px; }
body.dj-touch .fader-input::-moz-range-thumb{ width:22px; height:38px; }
body.dj-touch .pitch-input::-webkit-slider-thumb{ width:24px; height:40px; margin-top:-18px; }
body.dj-touch .pitch-input::-moz-range-thumb{ width:24px; height:40px; }

/* ==========================================================================
   Phone: layout changes for a screen too narrow to show a whole deck at
   finger size — the lower half takes turns, and every row is kept to one line.
   ========================================================================== */
.opstabs{ display:none; }

body.dj-phone .tabbar{
  flex-wrap:nowrap; overflow-x:auto; overscroll-behavior-x:contain;
  justify-content:flex-start; gap:6px; padding:6px 2px;
  scrollbar-width:none; -ms-overflow-style:none;
}
body.dj-phone .tabbar::-webkit-scrollbar{ display:none; }
body.dj-phone .tabbar button{ flex:0 0 auto; }

body.dj-phone .opstabs{
  display:grid; grid-template-columns:repeat(3,1fr); gap:5px;
  background:var(--panel2); border:1px solid var(--edge); border-radius:10px; padding:4px;
}
body.dj-phone .opstabs button{
  font:inherit; font-size:11.5px; font-weight:800; letter-spacing:.08em;
  border:0; border-radius:7px; background:transparent; color:var(--dim); cursor:pointer;
}
body.dj-phone .opstabs button.on{ background:var(--panel3); color:var(--text); }
body.dj-phone .deck[data-ops="pads"] .loopbar,
body.dj-phone .deck[data-ops="pads"] .tricks,
body.dj-phone .deck[data-ops="pads"] .fxblock,
body.dj-phone .deck[data-ops="loop"] .padblock,
body.dj-phone .deck[data-ops="loop"] .fxblock,
body.dj-phone .deck[data-ops="fx"] .padblock,
body.dj-phone .deck[data-ops="fx"] .loopbar,
body.dj-phone .deck[data-ops="fx"] .tricks{ display:none; }
body.dj-phone .deck-lower{ grid-template-columns:1fr; }
body.dj-phone .fxknobs{ gap:18px; }

/* every wrapped row costs another ~48px of deck height, so keep them single */
body.dj-phone .deck-mid{ grid-template-columns:minmax(0,1fr) 160px; gap:8px; }
body.dj-phone .pfader{ height:96px; }
body.dj-phone .pitch-input{ width:80px; }
body.dj-phone .wave-over{ height:20px; }
body.dj-phone .deck{ gap:6px; }
body.dj-phone .pitchcol{ gap:4px; }
body.dj-phone .jogcol{ gap:6px; }
body.dj-phone .jogmode{ flex-wrap:nowrap; gap:5px; }
body.dj-phone .jogmode .chip{ padding:0 6px; font-size:10px; letter-spacing:.03em; flex:1 1 0; min-width:0; }
body.dj-phone .pitchhead{ flex-wrap:nowrap; gap:4px; }
body.dj-phone .pitchhead .chip{ padding:0 7px; font-size:10px; letter-spacing:.03em; }
body.dj-phone .pitchhead .sel{ padding:0 4px; }

/* the clock rides on the waveform, as it does on most hardware */
body.dj-phone .timebar{ position:absolute; left:7px; right:7px; bottom:3px; z-index:2;
  pointer-events:none; font-size:11px; text-shadow:0 1px 3px #000; }
body.dj-phone .wave-detail{ height:74px; }
body.dj-phone .pad{ min-height:50px; }

/* a 108px tempo column cannot hold 44px buttons — give it room on touch */
body.dj-touch .deck-mid{ grid-template-columns:minmax(0,1fr) 160px; }
body.dj-touch .bendrow,
body.dj-touch .keyrow{ flex-wrap:wrap; justify-content:center; }
body.dj-touch .pitchhead{ justify-content:center; }

/* a big touch screen keeps both decks, but touch-sized knobs need a wider mixer */
body.dj-touch .console{ grid-template-columns:minmax(0,1fr) 380px minmax(0,1fr); }
body.dj-touch .mixer{ grid-template-columns:1fr 100px 1fr; }
body.dj-touch .stripknobs{ gap:6px 0; }
body.dj-touch .stripknobs .knobcell{ width:60px; }
body.dj-touch .assign{ flex-wrap:wrap; justify-content:center; }
body.dj-touch .asg{ min-width:34px; }

/* a beat grid the analyser had little evidence for — advisory, not an error:
   the tempo may well be right, but it is worth a glance before trusting sync */
button.badge.bpm.unsure{
  color:var(--accent); border-color:var(--accent);
  border-style:dashed; background:color-mix(in srgb, var(--accent) 12%, var(--panel3));
}
button.badge.bpm.unsure::after{ content:'?'; margin-left:3px; font-size:10px; opacity:.85; }
