diff --git a/index.html b/index.html
index 62d098d..d6eb0b9 100644
--- a/index.html
+++ b/index.html
@@ -55,6 +55,7 @@
.card h2 { font-size:11px; text-transform:uppercase; letter-spacing:1.4px; color:var(--muted); margin:0 0 14px; }
.display { background:#0a0d11; border:1px solid #000; border-radius:8px; padding:8px 14px; text-align:center; box-shadow:inset 0 2px 10px rgba(0,0,0,.7); }
.display .big { font-family:"Courier New",monospace; font-weight:700; font-size:40px; color:#ffd166; letter-spacing:3px; text-shadow:0 0 12px rgba(255,209,102,.5); }
+ .display .dtimers { font-family:"Courier New",monospace; font-size:13px; color:#4dd0e1; margin:3px 0; display:flex; gap:14px; justify-content:center; flex-wrap:wrap; }
.display .ctx { font-family:"Courier New",monospace; font-size:12px; color:#4dd0e1; min-height:15px; line-height:1.3; }
.display .ctx.muted-cue { color:#ffb454; }
.knob { margin-bottom:10px; }
@@ -183,6 +184,10 @@
120
+
+ ⏱ 0:00
+ ⏳ 0:00
+
@@ -213,13 +218,11 @@
Timersrun while playing
-
- 0:00
-
+
+
-
- 5:00
+
@@ -951,8 +954,18 @@ function drawLoop() {
/* =========================================================================
PRACTICE TIMERS — advance only while the metronome is running
========================================================================= */
-const timers = { elapsedMs: 0, totalMs: 5 * 60000, remainingMs: 5 * 60000, last: 0 };
+const timers = { elapsedMs: 0, totalMs: 0, remainingMs: 0, last: 0 }; // countdown off by default
function fmtClock(ms) { const neg = ms < 0; const s = Math.round(Math.abs(ms) / 1000); return (neg ? "-" : "") + Math.floor(s / 60) + ":" + String(s % 60).padStart(2, "0"); }
+// Parse a countdown duration: blank = off; "h:mm:ss" / "m:ss" (seconds-last); a plain number = minutes.
+function parseTime(str) {
+ str = (str || "").trim(); if (!str) return 0;
+ if (!str.includes(":")) { const m = parseFloat(str); return isFinite(m) && m > 0 ? Math.round(m * 60000) : 0; }
+ const p = str.split(":").map((x) => parseInt(x, 10) || 0);
+ let h = 0, m = 0, s = 0;
+ if (p.length >= 3) { h = p[0]; m = p[1]; s = p[2]; } else { m = p[0]; s = p[1]; }
+ const ms = ((h * 60 + m) * 60 + s) * 1000;
+ return ms > 0 ? ms : 0;
+}
function tickTimers() {
const now = Date.now();
const dt = timers.last ? Math.min(now - timers.last, 1000) : 0; // clamp so backgrounded gaps don't jump
@@ -965,8 +978,10 @@ function tickTimers() {
}
function renderTimers() {
$("elapsedVal").textContent = fmtClock(timers.elapsedMs);
+ const off = timers.totalMs <= 0;
+ $("countWrap").hidden = off; // hide countdown when off
+ if (off) return;
const cd = $("countVal");
- if (timers.totalMs <= 0) { cd.textContent = "off"; cd.className = "tval"; return; }
cd.textContent = fmtClock(timers.remainingMs);
cd.classList.toggle("over", timers.remainingMs <= 0); // overtime
cd.classList.toggle("low", timers.remainingMs > 0 && timers.remainingMs <= 10000); // almost up
@@ -1037,7 +1052,7 @@ $("rampStart").addEventListener("input", (e) => ramp.startBpm = +e.target.value)
$("rampAmt").addEventListener("input", (e) => ramp.amount = +e.target.value);
$("rampEvery").addEventListener("input", (e) => ramp.everyBars = +e.target.value);
$("addMeterBtn").addEventListener("click", () => addMeter("4", 1, "claves"));
-$("countMin").addEventListener("input", (e) => { timers.totalMs = (+e.target.value || 0) * 60000; timers.remainingMs = timers.totalMs; renderTimers(); });
+$("countTime").addEventListener("input", (e) => { timers.totalMs = parseTime(e.target.value); timers.remainingMs = timers.totalMs; renderTimers(); });
$("elapsedReset").addEventListener("click", () => { timers.elapsedMs = 0; renderTimers(); });
$("countReset").addEventListener("click", () => { timers.remainingMs = timers.totalMs; renderTimers(); });
$("trayMenuBtn").addEventListener("click", (e) => { e.stopPropagation(); $("trayMenu").hidden = !$("trayMenu").hidden; });