diff --git a/web/app.js b/web/app.js index 0c17348..ecccef3 100644 --- a/web/app.js +++ b/web/app.js @@ -239,8 +239,16 @@ function updateStepPlates() { endT = forecastFinalT; } if (startT !== undefined && endT !== undefined) { - const total = Math.max(0, endT - startT); - plate.remaining.textContent = formatDuration(Math.max(0, Math.min(total, endT - currentElapsed))); + const stepTotal = Math.max(0, endT - startT); + const holdDurS = (sudSchedule[i] && sudSchedule[i].hold) + ? (sudSchedule[i].hold.duration || 0) * 60 : 0; + const rampTotal = Math.max(0, stepTotal - holdDurS); + const rampVal = formatDuration( + Math.max(0, Math.min(rampTotal, endT - currentElapsed - holdDurS))); + // Active step in ramp phase gets the "ramp" prefix; hold branch + // overwrites remaining below with hold time instead. + plate.remaining.textContent = + (sudStepIndex === i && sudStepType === 'ramp') ? 'Ramp ' + rampVal : rampVal; } else { plate.remaining.textContent = '-:--:--'; } @@ -260,6 +268,11 @@ function updateStepPlates() { plate.actual.textContent = `Actual ${plotTempIst !== null ? plotTempIst.toFixed(1) + ' °C' : '—'}`; plate.stirrer.textContent = `Stirrer ${stirrerSpeedIst.toFixed(0)} rpm`; plate.energy.textContent = `Energy ${energyCurrent.toFixed(0)} Wh`; + // Active step: ramp prefix when ramping; bare hold time when holding + // (reuses the same digit area). PAUSED/WAIT_USER keep the last phase. + if (sudStepType === 'hold') { + plate.remaining.textContent = 'Hold ' + formatDuration(Math.max(0, sudHoldRemaining)); + } } else if (i in stepActualFrozen) { plate.actual.textContent = `Actual ${stepActualFrozen[i].toFixed(1)} °C`; plate.stirrer.textContent = `Stirrer ${plate.configuredSpeed.toFixed(0)} rpm (cfg)`; @@ -276,24 +289,32 @@ function updateStepPlates() { function updateHeaderCountdown() { const currentElapsed = (elapsed !== null) ? elapsed : 0; const n = sudSchedule.length; - let stepText = '-:--:--'; + let rampText = '-:--:--'; let totalText = '-:--:--'; let visible = false; if (n > 0 && sudStepIndex !== null) { visible = true; + const startT = forecastStepStarts[sudStepIndex]; let endT = forecastStepStarts[sudStepIndex + 1]; if (endT === undefined && sudStepIndex === n - 1 && forecastFinished) { endT = forecastFinalT; } - if (endT !== undefined) { - stepText = formatDuration(Math.max(0, endT - currentElapsed)); + if (startT !== undefined && endT !== undefined) { + const stepTotal = Math.max(0, endT - startT); + const step = sudSchedule[sudStepIndex]; + const holdDurS = (step && step.hold) ? (step.hold.duration || 0) * 60 : 0; + const rampTotal = Math.max(0, stepTotal - holdDurS); + rampText = formatDuration(Math.max(0, Math.min(rampTotal, endT - currentElapsed - holdDurS))); } if (forecastFinalT !== null && elapsed !== null) { totalText = formatDuration(Math.max(0, forecastFinalT - currentElapsed)); } } - document.getElementById('hdr-step-remaining').textContent = stepText; + const holdText = (sudStepType === 'hold' && sudHoldRemaining > 0) + ? formatDuration(Math.max(0, sudHoldRemaining)) : '-:--:--'; + document.getElementById('hdr-step-remaining').textContent = rampText; document.getElementById('hdr-total-remaining').textContent = totalText; + document.getElementById('hdr-hold-remaining').textContent = holdText; document.getElementById('header-countdown').classList.toggle('hidden', !visible); } diff --git a/web/index.html b/web/index.html index ded092d..9db36e1 100644 --- a/web/index.html +++ b/web/index.html @@ -21,7 +21,8 @@ diff --git a/web/style.css b/web/style.css index 2805bc0..55fc136 100644 --- a/web/style.css +++ b/web/style.css @@ -106,13 +106,15 @@ header#connection-bar { width: 2.8em; } #hdr-step-remaining, -#hdr-total-remaining { +#hdr-total-remaining, +#hdr-hold-remaining { font-family: 'Courier New', 'Lucida Console', monospace; font-weight: bold; font-size: 1.35em; color: var(--accent); } + /* --- Transport buttons (circular, coloured) --- */ .transport-btn { @@ -327,7 +329,7 @@ header#connection-bar { font-weight: bold; text-align: right; font-family: 'Courier New', monospace; - color: var(--accent); + color: #4ade80; } .step-plate .field { color: var(--text-muted);