diff --git a/web_realart/public/control/control.css b/web_realart/public/control/control.css
index 9189d4a..136f2f1 100644
--- a/web_realart/public/control/control.css
+++ b/web_realart/public/control/control.css
@@ -254,3 +254,7 @@ button.queued { animation: queued-blink 600ms ease-in-out infinite alternate; }
.morceau-fists { display: flex; flex-direction: column; gap: 4px; }
.morceau-fist { position: relative; font-size: 12px; color: #ccc; padding: 2px 4px;
background: #1c1c1c; border-radius: 4px; }
+
+/* Tempo -/+ steppers (1 BPM per tap) + live value */
+.tempo-step { width: 44px; padding: 8px 0; font-size: 18px; flex-shrink: 0; }
+#tempo-val { min-width: 3ch; text-align: right; font-variant-numeric: tabular-nums; }
diff --git a/web_realart/public/control/index.html b/web_realart/public/control/index.html
index 697625a..c46352a 100644
--- a/web_realart/public/control/index.html
+++ b/web_realart/public/control/index.html
@@ -37,7 +37,7 @@
-
+
Quant
diff --git a/web_realart/public/control/js/transport.js b/web_realart/public/control/js/transport.js
index 93f0cf0..26bf4e6 100644
--- a/web_realart/public/control/js/transport.js
+++ b/web_realart/public/control/js/transport.js
@@ -24,9 +24,23 @@ export function init() {
if (bar) bar.style.width = `${rms * 100}%`;
});
- // Tempo
+ // Tempo: slider + -/+ steppers (1 BPM per click), value label kept in sync
const tempo = document.getElementById("tempo");
- tempo && tempo.addEventListener("input", () => send("/launch/tempo", +tempo.value));
+ const tempoVal = document.getElementById("tempo-val");
+ const pushTempo = () => {
+ if (tempoVal) tempoVal.textContent = tempo.value;
+ send("/launch/tempo", +tempo.value);
+ };
+ tempo && tempo.addEventListener("input", pushTempo);
+ const stepTempo = (d) => {
+ if (!tempo) return;
+ tempo.value = Math.max(+tempo.min, Math.min(+tempo.max, +tempo.value + d));
+ pushTempo();
+ };
+ const tMinus = document.getElementById("tempo-minus");
+ const tPlus = document.getElementById("tempo-plus");
+ tMinus && tMinus.addEventListener("click", () => stepTempo(-1));
+ tPlus && tPlus.addEventListener("click", () => stepTempo(1));
// Filter
const filt = document.getElementById("filter");