/* ============================================================
   JAMRACK — "hardware synth rack" design
   Palette: warm charcoal + amber LEDs + teal accents
   ============================================================ */

:root {
  --bg: #0d0b09;
  --bg-deep: #080706;
  --panel: #1b1713;
  --panel-hi: #241f19;
  --panel-lo: #141110;
  --line: #383026;
  --line-soft: #2a241d;
  --txt: #ece3d3;
  --dim: #94876fcc;
  --amber: #ffb454;
  --amber-hot: #ffd9a0;
  --amber-dim: #7a5626;
  --teal: #3ad0c4;
  --red: #ff5040;
  --lcd-bg: #201807;
  --lcd-txt: #ffc46b;
  --white-key: linear-gradient(180deg, #faf5ea 0%, #efe8d8 78%, #d8d0bd 100%);
  --black-key: linear-gradient(180deg, #2b2721 0%, #16130f 70%, #0a0806 100%);
  --f-brand: 'Unbounded', sans-serif;
  --f-label: 'Barlow Condensed', sans-serif;
  --f-mono: 'Spline Sans Mono', monospace;
  --knob-size: 46px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  height: 100%;
  background: var(--bg);
  color: var(--txt);
  font-family: var(--f-label);
  overscroll-behavior: none;
  /* panning allowed, pinch-zoom and double-tap suppressed (two-handed jamming) */
  touch-action: pan-x pan-y;
}

body {
  /* film grain + stage glow */
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.035 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(120% 60% at 50% -10%, #2b2118 0%, transparent 60%),
    radial-gradient(90% 50% at 50% 115%, #191510 0%, transparent 55%),
    var(--bg);
  -webkit-tap-highlight-color: transparent;
}

#app {
  height: 100vh;   /* fallback when dvh is unsupported */
  height: 100dvh;
  display: flex;
  flex-direction: column;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 14px env(safe-area-inset-bottom);
  /* notched iPhone in landscape: keep content clear of the notch */
  padding-left: max(14px, env(safe-area-inset-left));
  padding-right: max(14px, env(safe-area-inset-right));
}
body { overflow: hidden; }

button { font-family: inherit; color: inherit; }
::selection { background: var(--amber); color: #14100a; }

.mono { font-family: var(--f-mono); font-size: 12px; letter-spacing: 0; }

/* ---------------- LEDs ---------------- */

.led {
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: #3a3128;
  box-shadow: inset 0 1px 2px #0009;
  transition: background .15s, box-shadow .15s;
  flex: none;
}
.led.on {
  background: var(--amber);
  box-shadow: 0 0 8px 2px #ffb45480, inset 0 0 2px #fff8;
}
.led.on.teal { background: var(--teal); box-shadow: 0 0 8px 2px #3ad0c480, inset 0 0 2px #fff8; }
.led.on.red  { background: var(--red);  box-shadow: 0 0 9px 3px #ff504080, inset 0 0 2px #fff8; }
.led.blink { animation: ledblink .5s steps(1) infinite; }
@keyframes ledblink { 50% { background: #3a3128; box-shadow: inset 0 1px 2px #0009; } }

/* ---------------- Topbar ---------------- */

#topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 14px 4px 12px;
}

.brand-name {
  font-family: var(--f-brand);
  font-weight: 800;
  font-size: clamp(22px, 4vw, 30px);
  letter-spacing: .02em;
  line-height: 1;
  color: var(--txt);
  text-shadow: 0 0 24px #ffb45426;
}
.brand-name span { color: var(--amber); }
.brand-sub {
  font-size: 13px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--dim);
  margin-top: 4px;
}

.topbar-controls {
  display: flex;
  align-items: stretch;
  gap: 10px;
  flex-wrap: wrap;
}

.tb-group {
  display: flex;
  align-items: center;
  gap: 8px;
  background: linear-gradient(180deg, var(--panel-hi), var(--panel-lo));
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px 10px;
  box-shadow: 0 2px 6px #0006, inset 0 1px 0 #ffffff0d;
}
.tb-label { font-size: 13px; letter-spacing: .14em; color: var(--dim); }
.tb-unit { font-size: 11px; letter-spacing: .1em; color: var(--dim); }

.tb-btn {
  background: linear-gradient(180deg, #2e2820, #1c1813);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--txt);
  font-family: var(--f-label);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: .12em;
  padding: 6px 11px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  transition: transform .05s, border-color .15s, background .15s;
}
.tb-btn:hover { border-color: #55483a; }
.tb-btn:active { transform: translateY(1px); }
.tb-btn[aria-pressed="true"] { background: linear-gradient(180deg, #3a2f1e, #262015); border-color: var(--amber-dim); }
.tb-btn.rec[aria-pressed="true"] { border-color: #7a2c26; background: linear-gradient(180deg, #3a201c, #241512); }

.lang-select {
  background: linear-gradient(180deg, #2e2820, #1c1813);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--txt);
  font-family: var(--f-label);
  font-size: 13px;
  letter-spacing: .04em;
  padding: 6px 6px;
  max-width: 110px;
  cursor: pointer;
}
.lang-select:hover { border-color: #55483a; }
.lang-select:focus { outline: 1px solid var(--amber-dim); }
.lang-select option { background: #1c1813; color: var(--txt); }

#bpmInput {
  width: 52px;
  background: var(--lcd-bg);
  border: 1px solid #000;
  border-radius: 4px;
  box-shadow: inset 0 2px 6px #000c, 0 1px 0 #ffffff10;
  color: var(--lcd-txt);
  font-family: var(--f-mono);
  font-size: 14px;
  text-align: center;
  padding: 4px 2px;
}
#bpmInput:focus { outline: 1px solid var(--amber-dim); }
#recTime { color: var(--dim); min-width: 38px; text-align: right; }

#audioHint {
  position: fixed;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  max-width: min(92vw, 480px);
  white-space: nowrap;
  box-shadow: 0 8px 30px #000c;
  backdrop-filter: blur(4px);
  padding: 9px 14px;
  border: 1px dashed var(--amber-dim);
  border-radius: 8px;
  background: #241c10ee;
  color: var(--amber-hot);
  font-size: 15px;
  letter-spacing: .04em;
  display: flex;
  align-items: center;
  gap: 8px;
  animation: hintpulse 2.2s ease-in-out infinite;
}
@keyframes hintpulse { 50% { background: #33260fee; } }
#audioHint[hidden] { display: none; }

/* ---------------- Rack ---------------- */

#rack {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 2px 0 14px;
  min-height: 0;
  overflow-y: auto;
}

.module {
  position: relative;
  background:
    linear-gradient(180deg, #ffffff08, transparent 30%),
    repeating-linear-gradient(90deg, transparent 0 3px, #ffffff02 3px 4px),
    linear-gradient(180deg, var(--panel-hi), var(--panel));
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 4px 14px #0008, inset 0 1px 0 #ffffff0f;
  padding: 10px 26px;
}

/* rack screws */
.module::before, .module::after {
  content: '';
  position: absolute;
  top: 50%;
  width: 11px; height: 11px;
  margin-top: -5px;
  border-radius: 50%;
  background:
    linear-gradient(135deg, transparent 44%, #0008 46%, #0008 54%, transparent 56%),
    radial-gradient(circle at 35% 30%, #6a5f4e, #2c2620 65%, #171310);
  box-shadow: 0 1px 2px #000a, inset 0 0 2px #000;
}
.module::before { left: 7px; }
.module::after { right: 7px; }

.mod-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.mod-power {
  width: 26px; height: 26px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, #2e2820, #1c1813);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex: none;
}

.mod-lcd {
  flex: 1 1 200px;
  min-width: 150px;
  background: var(--lcd-bg);
  border: 1px solid #000;
  border-radius: 5px;
  box-shadow: inset 0 2px 8px #000d, 0 1px 0 #ffffff12;
  color: var(--lcd-txt);
  font-family: var(--f-mono);
  font-size: 13px;
  padding: 6px 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 0 6px #ffc46b55;
}
.mod-lcd.err { color: #ff8a7a; text-shadow: 0 0 6px #ff504055; }

.mod-selects { display: flex; gap: 8px; flex: 2 1 300px; flex-wrap: wrap; }

.mod-selects select, .dlg-body select {
  background: linear-gradient(180deg, #2e2820, #1c1813);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--txt);
  font-family: var(--f-label);
  font-size: 14px;
  padding: 6px 8px;
  max-width: 100%;
  cursor: pointer;
}
.mod-selects select.sel-bank { flex: 1 1 110px; min-width: 0; }
.mod-selects select.sel-inst { flex: 2 1 170px; min-width: 0; }
.mod-selects select:focus { outline: 1px solid var(--amber-dim); }

.mod-btns { display: flex; gap: 6px; margin-left: auto; }

.sq-btn {
  width: 30px; height: 30px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, #2e2820, #1c1813);
  color: var(--dim);
  font-family: var(--f-label);
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
  transition: transform .05s, color .15s, border-color .15s;
}
.sq-btn:hover { border-color: #55483a; color: var(--txt); }
.sq-btn:active { transform: translateY(1px); }
.sq-btn.active-amber { color: #14100a; background: var(--amber); border-color: var(--amber); box-shadow: 0 0 10px #ffb45466; }
.sq-btn.active-teal  { color: #08211f; background: var(--teal); border-color: var(--teal); box-shadow: 0 0 10px #3ad0c466; }

.mod-body {
  display: flex;
  gap: 14px 20px;
  flex-wrap: wrap;
  align-items: flex-start;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
}
.module.collapsed .mod-body { display: none; }

.mod-sec {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.mod-sec-title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .22em;
  color: var(--dim);
  border-bottom: 1px solid var(--line-soft);
  padding-bottom: 3px;
}
.mod-sec-row { display: flex; gap: 10px; align-items: flex-end; }

/* octave and transpose steppers */
.stepper { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.stepper-ctl { display: flex; align-items: center; gap: 4px; }
.stepper-ctl .sq-btn { width: 24px; height: 24px; font-size: 14px; }
.stepper-read {
  font-family: var(--f-mono);
  font-size: 13px;
  color: var(--lcd-txt);
  background: var(--lcd-bg);
  border-radius: 4px;
  border: 1px solid #000;
  box-shadow: inset 0 1px 4px #000c;
  min-width: 34px;
  text-align: center;
  padding: 2px 4px;
}
.stepper-lab { font-size: 11px; letter-spacing: .14em; color: var(--dim); }

/* keyboard toggle switch */
.toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 13px;
  letter-spacing: .1em;
  color: var(--dim);
  -webkit-user-select: none;
  user-select: none;
}
.toggle input { display: none; }
.toggle .sw {
  width: 34px; height: 18px;
  border-radius: 10px;
  background: #131009;
  border: 1px solid var(--line);
  box-shadow: inset 0 2px 4px #000b;
  position: relative;
  transition: background .15s;
}
.toggle .sw::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: linear-gradient(180deg, #7a6c58, #4a4136);
  transition: left .15s, background .15s;
}
.toggle input:checked + .sw { background: #3d2c12; }
.toggle input:checked + .sw::after { left: 18px; background: var(--amber); box-shadow: 0 0 7px #ffb45499; }

.range-selects { display: flex; align-items: center; gap: 4px; }
.range-selects select { font-size: 12px; padding: 3px 4px; }

/* "add module" button */
#addModule {
  border: 1px dashed var(--line);
  border-radius: 10px;
  background: transparent;
  color: var(--dim);
  font-family: var(--f-label);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: .2em;
  padding: 13px;
  cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}
#addModule:hover { color: var(--amber); border-color: var(--amber-dim); background: #ffb45408; }

/* master module */
.module.master {
  background:
    linear-gradient(180deg, #ffffff0a, transparent 30%),
    linear-gradient(180deg, #262019, #1d1812);
}
.master-row { display: flex; align-items: center; gap: 14px 22px; flex-wrap: wrap; }
.master-title {
  font-family: var(--f-brand);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .3em;
  color: var(--dim);
  writing-mode: initial;
}
#vuCanvas {
  width: 90px; height: 26px;
  background: var(--lcd-bg);
  border: 1px solid #000;
  border-radius: 4px;
  box-shadow: inset 0 2px 6px #000c;
}

/* ---------------- Knobs ---------------- */

.knob {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  width: calc(var(--knob-size) + 16px);
  -webkit-user-select: none;
  user-select: none;
  touch-action: none;
}
.knob:focus-visible { outline: 1px solid var(--amber-dim); border-radius: 8px; }

.k-dial {
  width: var(--knob-size);
  height: var(--knob-size);
  border-radius: 50%;
  position: relative;
  cursor: ns-resize;
  background: conic-gradient(from 225deg,
    var(--amber) calc(var(--t, .5) * 270deg),
    #37302699 calc(var(--t, .5) * 270deg) 270deg,
    transparent 270deg);
  -webkit-mask: radial-gradient(closest-side, transparent 66%, #000 67%);
  mask: radial-gradient(closest-side, transparent 66%, #000 67%);
}
.k-dial::before {
  /* knob body is drawn by .k-cap, outside the mask */
  content: '';
}
.k-cap {
  position: absolute;
  inset: 6px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 28%, #4d4335, #241f18 60%, #15110d);
  box-shadow: 0 3px 6px #000a, inset 0 1px 1px #ffffff22;
  cursor: ns-resize;
}
.k-ind {
  position: absolute;
  left: 50%; top: 50%;
  width: 2.5px; height: 38%;
  margin-left: -1.25px;
  transform-origin: 50% 0%;
  transform: rotate(calc(var(--ang, 0) * 1deg + 180deg));
  border-radius: 2px;
  background: var(--amber-hot);
  box-shadow: 0 0 5px #ffb45488;
  pointer-events: none;
}
/* cap and pointer live outside the mask */
.k-wrap { position: relative; width: var(--knob-size); height: var(--knob-size); }
.k-wrap .k-dial { position: absolute; inset: 0; }

.k-val {
  font-family: var(--f-mono);
  font-size: 10.5px;
  color: var(--amber-hot);
  opacity: .85;
  min-height: 13px;
}
.k-lab {
  font-size: 11px;
  letter-spacing: .12em;
  color: var(--dim);
  text-align: center;
  white-space: nowrap;
}
.knob.small { --knob-size: 36px; width: 46px; }
.knob.small .k-cap { inset: 5px; }

/* ---------------- Keyboard zone ---------------- */

#kbZone {
  position: sticky;
  bottom: 0;
  background: linear-gradient(180deg, transparent, var(--bg-deep) 26%);
  padding: 8px 0 10px;
  z-index: 5;
}

#kbCtl {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 6px 4px 10px;
}
.kb-group {
  display: flex;
  align-items: center;
  gap: 7px;
  background: linear-gradient(180deg, var(--panel-hi), var(--panel-lo));
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px 10px;
}
.kb-group.grow { flex: 1 1 160px; }
.kb-label { font-size: 12px; letter-spacing: .14em; color: var(--dim); white-space: nowrap; }
.kb-hint { opacity: .6; letter-spacing: .05em; text-transform: lowercase; }
.kb-read { color: var(--lcd-txt); background: var(--lcd-bg); border-radius: 4px; padding: 2px 7px; box-shadow: inset 0 1px 4px #000c; }
.kb-btn {
  width: 28px; height: 28px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, #2e2820, #1c1813);
  color: var(--txt);
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
}
.kb-btn:active { transform: translateY(1px); }

#velSlider {
  flex: 1;
  min-width: 70px;
  appearance: none;
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--amber-dim), var(--amber));
  outline: none;
}
#velSlider::-webkit-slider-thumb {
  appearance: none;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #5c5142, #2a241d);
  border: 1px solid #55483a;
  box-shadow: 0 2px 4px #000a;
  cursor: pointer;
}
#velSlider::-moz-range-thumb {
  width: 16px; height: 16px;
  border-radius: 50%;
  background: #3a332a;
  border: 1px solid #55483a;
  cursor: pointer;
}

/* ---------------- Piano ---------------- */

#piano {
  position: relative;
  height: clamp(150px, 24vh, 230px);
  display: flex;
  border-radius: 8px 8px 10px 10px;
  background: #060504;
  border: 1px solid #000;
  box-shadow: 0 -1px 0 #ffffff14, 0 10px 24px #000b;
  padding: 5px 4px 6px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.pk {
  position: relative;
  border-radius: 0 0 5px 5px;
  cursor: pointer;
}
.pk.w {
  flex: 1;
  background: var(--white-key);
  border: 1px solid #9a927e;
  border-top: none;
  box-shadow: inset 0 -7px 10px #b6ad9755, inset 0 2px 4px #fff, 0 3px 3px #0007;
  margin: 0 1px;
  z-index: 1;
}
.pk.w.active {
  background: linear-gradient(180deg, #ffe9c4, #ffcf8e 85%);
  box-shadow: inset 0 -4px 8px #d8a75f88, inset 0 3px 9px #b9822e66, 0 0 14px #ffb45455;
  transform: translateY(1px);
}
.pk.b {
  position: absolute;
  top: 5px;
  width: var(--bkw, 30px);
  height: 60%;
  background: var(--black-key);
  border: 1px solid #000;
  border-radius: 0 0 4px 4px;
  box-shadow: inset 0 -5px 7px #00000088, inset 0 2px 2px #ffffff2e, 0 5px 7px #000c;
  z-index: 2;
}
.pk.b.active {
  background: linear-gradient(180deg, #4d3a1e, #2b2010 80%);
  box-shadow: inset 0 -3px 5px #000a, 0 0 12px #ffb45466;
  transform: translateY(1px);
}

.pk .keycap {
  position: absolute;
  bottom: 7px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--f-mono);
  font-size: 11px;
  color: #6f6552;
  background: #00000010;
  border: 1px solid #00000022;
  border-radius: 4px;
  padding: 1px 4px;
  pointer-events: none;
}
.pk.b .keycap { color: #b9a887; background: #ffffff12; border-color: #ffffff1c; bottom: 6px; }
.pk .notename {
  position: absolute;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 10px;
  color: #a99e86;
  pointer-events: none;
  font-family: var(--f-label);
  letter-spacing: .05em;
}
.pk.b .notename { display: none; }

/* ---------------- Dialogs ---------------- */

dialog {
  background: linear-gradient(180deg, var(--panel-hi), var(--panel));
  color: var(--txt);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 20px 60px #000d;
  padding: 0;
  width: min(560px, calc(100vw - 32px));
  max-height: min(80vh, 640px);  /* fallback when dvh is unsupported */
  max-height: min(80dvh, 640px);
}
/* fallback without native <dialog>: centre it and lift it above the app */
dialog[open] {
  display: block;
  position: fixed;
  inset: 0;
  margin: auto;
  height: fit-content;
  z-index: 100;
}
dialog::backdrop { background: #060504cc; backdrop-filter: blur(3px); }

.dlg-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line-soft);
}
.dlg-head h2 {
  font-family: var(--f-brand);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.dlg-close {
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--dim);
  width: 28px; height: 28px;
  cursor: pointer;
}
.dlg-close:hover { color: var(--txt); border-color: #55483a; }

.dlg-body {
  padding: 16px 18px 20px;
  overflow-y: auto;
  max-height: calc(80vh - 60px);  /* fallback when dvh is unsupported */
  max-height: calc(80dvh - 60px);
  font-size: 15px;
  line-height: 1.5;
}
.dlg-body h3 {
  font-size: 12px;
  letter-spacing: .22em;
  color: var(--dim);
  text-transform: uppercase;
  margin: 18px 0 8px;
  border-bottom: 1px solid var(--line-soft);
  padding-bottom: 4px;
}
.dlg-body h3:first-child { margin-top: 0; }
.dlg-body p { color: #c9bda7; margin-bottom: 8px; }
.dlg-body .small { font-size: 13px; color: var(--dim); }
.dlg-body code {
  font-family: var(--f-mono);
  font-size: 12.5px;
  background: #00000055;
  border: 1px solid var(--line-soft);
  border-radius: 4px;
  padding: 1px 5px;
  color: var(--amber-hot);
}
.dlg-body a { color: var(--teal); }

.bank-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  margin-bottom: 6px;
  background: #00000022;
}
.bank-row .bank-name { font-weight: 600; font-size: 15px; }
.bank-row .bank-url { font-family: var(--f-mono); font-size: 11px; color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.bank-row .tag {
  font-size: 11px;
  letter-spacing: .1em;
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 1px 6px;
  color: var(--dim);
}

.bank-form { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.bank-form input {
  background: #00000055;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--txt);
  font-family: var(--f-mono);
  font-size: 13px;
  padding: 8px 10px;
}
.bank-form input:focus { outline: 1px solid var(--amber-dim); }
.bank-form .form-row { display: flex; gap: 8px; }
.bank-form .form-row input { flex: 1; }
.form-msg { font-size: 13px; min-height: 18px; }
.form-msg.ok { color: var(--teal); }
.form-msg.err { color: var(--red); }

/* help dialog key map diagram */
.helpkb { display: flex; flex-direction: column; gap: 5px; margin: 10px 0 4px; }
.helpkb-row { display: flex; gap: 5px; }
.helpkb-row.offset { padding-left: 22px; }
.cap {
  min-width: 34px;
  text-align: center;
  font-family: var(--f-mono);
  font-size: 13px;
  padding: 6px 4px 5px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, #2e2820, #1c1813);
  box-shadow: 0 2px 0 #00000088;
  position: relative;
  color: var(--txt);
}
.cap small { display: block; font-size: 9px; color: var(--dim); letter-spacing: .04em; }
.cap.black { background: linear-gradient(180deg, #191512, #0d0b09); color: var(--amber-hot); }
.cap.unused { opacity: .28; }
.layout-switch { display: flex; gap: 6px; margin: 6px 0; }
.layout-switch button {
  font-family: var(--f-label);
  font-size: 12px;
  letter-spacing: .1em;
  padding: 4px 10px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--dim);
  cursor: pointer;
}
.layout-switch button.on { color: #14100a; background: var(--amber); border-color: var(--amber); }

table.shortcuts { border-collapse: collapse; width: 100%; }
table.shortcuts td { padding: 5px 8px; border-bottom: 1px solid var(--line-soft); color: #c9bda7; font-size: 14px; }
table.shortcuts td:first-child { font-family: var(--f-mono); font-size: 12.5px; color: var(--amber-hot); white-space: nowrap; }

/* ---------------- RTL (Arabic, Urdu) ---------------- */
/* Text and layout flip, but musical objects must not: a piano always runs
   bass-to-treble left-to-right, and the VU meter fills the same way. */

[dir="rtl"] #piano,
[dir="rtl"] .helpkb,
[dir="rtl"] .helpkb-row,
[dir="rtl"] .stepper-ctl,
[dir="rtl"] .range-selects,
[dir="rtl"] #velSlider,
[dir="rtl"] .master-row,
[dir="rtl"] .mod-sec-row {
  direction: ltr;
}
[dir="rtl"] .mod-lcd,
[dir="rtl"] .stepper-read,
[dir="rtl"] .kb-read {
  direction: ltr;
  text-align: center;
}
[dir="rtl"] .mod-lcd { text-align: start; }
[dir="rtl"] .mod-btns { margin-left: 0; margin-right: auto; }
[dir="rtl"] .helpkb-row.offset { padding-left: 0; padding-right: 22px; }
[dir="rtl"] table.shortcuts td:first-child { direction: ltr; text-align: right; }
[dir="rtl"] .bank-url { direction: ltr; text-align: right; }
[dir="rtl"] .brand-name,
[dir="rtl"] .brand-sub { direction: ltr; text-align: left; }

/* ---------------- Responsive ---------------- */

@media (max-width: 780px) {
  :root { --knob-size: 42px; }
  #app {
    padding: 0 8px env(safe-area-inset-bottom);
    padding-left: max(8px, env(safe-area-inset-left));
    padding-right: max(8px, env(safe-area-inset-right));
  }
  #topbar { padding: 10px 2px 8px; gap: 8px; }
  .brand-sub { display: none; }
  .module { padding: 9px 22px; }
  .mod-btns { margin-left: 0; }
  .mod-body { gap: 12px 16px; }
  #kbCtl .kb-hint { display: none; }
  #piano { height: clamp(160px, 30vh, 240px); }
  .pk .notename { display: none; }
}

/* short viewports (phone in landscape, small windows): everything must fit */
@media (max-height: 560px) {
  #topbar { padding: 6px 2px 4px; gap: 8px; }
  .brand-name { font-size: 19px; }
  .brand-sub { display: none; }
  .tb-btn { padding: 4px 8px; font-size: 12px; }
  .tb-group { padding: 3px 7px; }
  #rack { min-height: 64px; gap: 6px; padding: 2px 0 6px; }
  .module { padding: 6px 22px; }
  #kbZone { padding: 2px 0 6px; }
  #kbCtl { padding: 2px 2px 6px; gap: 6px; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  #kbCtl::-webkit-scrollbar { display: none; }
  .kb-group { flex: none; }
  .kb-group.grow { flex: 1 1 120px; min-width: 110px; }
  .kb-group { padding: 3px 8px; }
  .kb-label { font-size: 11px; }
  .kb-hint { display: none; }
  #piano { height: clamp(110px, 42vh, 170px); }
  .pk .notename { display: none; }
}

@media (max-width: 480px) {
  .tb-btn { font-size: 12px; padding: 5px 8px; letter-spacing: .08em; }
  .tb-group { padding: 5px 7px; gap: 6px; }
  #recTime { display: none; }
  .pk .keycap { display: none; }
}

/* ================================================================
   Mobile views: PLAY / EDIT
   On a phone the rack needs ~800px but only gets ~270px between the
   topbar and the sticky keyboard, which makes the modules unusable.
   Below 780px the two areas become dedicated full-height views,
   switched by the tabs in the topbar. Desktop is untouched.
   ================================================================ */

/* Tabs are a mobile affordance only. */
#viewTabs { display: none; }

@media (max-width: 780px) {
  #viewTabs {
    display: flex;
    gap: 6px;
    width: 100%;
    order: 3;
    padding: 2px 2px 0;
  }
  .vt-btn {
    flex: 1;
    padding: 9px 10px;
    min-height: 40px;                 /* comfortable touch target */
    font-family: var(--f-label);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .14em;
    color: var(--dim);
    background: linear-gradient(180deg, #241f19, #17130f);
    border: 1px solid var(--line);
    border-radius: 8px;
    cursor: pointer;
    transition: color .15s, background .15s, box-shadow .15s;
  }
  .vt-btn.is-on {
    color: var(--amber);
    background: linear-gradient(180deg, #3a3024, #241d15);
    box-shadow: inset 0 0 0 1px var(--amber-dim), 0 0 10px #f5a94722;
  }

  /* --- PLAY view: the keyboard owns the screen (previous behaviour) --- */
  body.m-play #rack { display: none; }

  /* --- EDIT view: the rack owns the screen --- */
  body.m-edit #kbZone { display: none; }
  body.m-edit #rack {
    flex: 1;
    padding-bottom: 18px;
  }

  /* Roomier modules once the rack has the full height. */
  body.m-edit .module { padding: 12px 14px; }
  /* The decorative rack screws eat 26px of side padding we now need. */
  body.m-edit .module::before,
  body.m-edit .module::after { display: none; }

  body.m-edit .mod-body { gap: 16px 18px; }

  /* Readable instrument menus: they were ~75px wide, far too narrow for
     names like "Electric piano 1 (Rhodes)". One per line, full width. */
  body.m-edit .mod-selects { flex: 1 1 100%; flex-direction: column; gap: 8px; }
  body.m-edit .mod-selects select.sel-bank,
  body.m-edit .mod-selects select.sel-inst {
    flex: 1 1 auto;
    width: 100%;
    min-height: 40px;
    font-size: 15px;
  }

  /* Sections span the width so knobs spread out instead of cramming. */
  body.m-edit .mod-sec { flex: 1 1 100%; }
  body.m-edit .mod-sec-row { flex-wrap: wrap; gap: 12px 14px; }

  /* Finger-sized hit targets. The desktop sizes (24-30px) are fine with a
     mouse but too small to hit reliably on a touchscreen. */
  body.m-edit .mod-selects select.sel-engine { min-height: 40px; font-size: 15px; }

  body.m-edit .mod-power { width: 34px; height: 34px; }
  body.m-edit .mod-btns .sq-btn { width: 38px; height: 38px; font-size: 15px; }

  /* Octave / transpose steppers. */
  body.m-edit .stepper-ctl .sq-btn { width: 38px; height: 38px; font-size: 17px; }
  body.m-edit .stepper-ctl { gap: 8px; }
  body.m-edit .stepper-read { font-size: 15px; padding: 6px 10px; }

  /* Split range selects. */
  body.m-edit select.sel-lo,
  body.m-edit select.sel-hi { min-height: 38px; font-size: 14px; }

  /* Advanced synth panel: same finger-sized rule as the rest. */
  body.m-edit .synth-toggle { min-height: 40px; font-size: 12px; }
  body.m-edit .synth-panel select { min-height: 38px; font-size: 14px; }
  body.m-edit .synth-panel { gap: 14px 16px; }
}

/* ---------------- Advanced synth panel ---------------- */
/* Presets cover the common case; these two dozen knobs stay folded so the
   module keeps a sane height (and remains usable on a phone). */
.synth-sec { flex: 1 1 100%; }

.synth-toggle {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  padding: 7px 2px;
  margin-top: 2px;
  font-family: var(--f-label);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .22em;
  color: var(--dim);
  background: none;
  border: none;
  border-top: 1px solid var(--line-soft);
  cursor: pointer;
  text-align: left;
}
.synth-toggle:hover { color: var(--amber); }
.synth-caret { font-size: 10px; }

.synth-panel {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 18px;
  padding: 6px 0 2px;
}
.synth-panel .mod-sec { flex: 0 1 auto; }
.synth-panel select {
  align-self: flex-end;
  min-width: 92px;
}
