diff --git a/game.js b/game.js
index c186b2b..79079c1 100644
--- a/game.js
+++ b/game.js
@@ -1828,7 +1828,16 @@ function renderProgress() {
const progress = Math.min(1, (G.totalCode - prevThreshold) / range);
if (bar) bar.style.width = (progress * 100).toFixed(1) + '%';
if (label) label.textContent = (progress * 100).toFixed(1) + '%';
- if (target) target.textContent = `Next: Phase ${currentPhase + 1} (${fmt(nextThreshold)} code)`;
+ // ETA to next phase
+ let etaStr = '';
+ if (G.codeRate > 0) {
+ const remaining = nextThreshold - G.totalCode;
+ const secs = remaining / G.codeRate;
+ if (secs < 60) etaStr = ` — ${Math.ceil(secs)}s`;
+ else if (secs < 3600) etaStr = ` — ${Math.floor(secs / 60)}m ${Math.floor(secs % 60)}s`;
+ else etaStr = ` — ${Math.floor(secs / 3600)}h ${Math.floor((secs % 3600) / 60)}m`;
+ }
+ if (target) target.textContent = `Next: Phase ${currentPhase + 1} (${fmt(nextThreshold)} code)${etaStr}`;
} else {
// Max phase reached
if (bar) bar.style.width = '100%';
@@ -1854,7 +1863,14 @@ function renderProgress() {
}
// Next milestone gets pulse animation
if (shown === 0) {
- chips += `${fmt(ms)} (${((G.totalCode / ms) * 100).toFixed(0)}%)`;
+ let etaStr = '';
+ if (G.codeRate > 0) {
+ const secs = (ms - G.totalCode) / G.codeRate;
+ if (secs < 60) etaStr = ` ~${Math.ceil(secs)}s`;
+ else if (secs < 3600) etaStr = ` ~${Math.floor(secs / 60)}m`;
+ else etaStr = ` ~${Math.floor(secs / 3600)}h`;
+ }
+ chips += `${fmt(ms)} (${((G.totalCode / ms) * 100).toFixed(0)}%)${etaStr}`;
} else {
chips += `${fmt(ms)}`;
}