diff --git a/training/dashboard/static/dashboard.js b/training/dashboard/static/dashboard.js
index 6c9b1f0..0473168 100644
--- a/training/dashboard/static/dashboard.js
+++ b/training/dashboard/static/dashboard.js
@@ -2275,10 +2275,10 @@ def train_nn(*, model, X_train, y_train, X_val, y_val,
const PROFILES = ['cpu-saturate', 'ransomware-lite', 'bursty-c2', 'fork-bomb', 'crypto-miner'];
const PHASES = ['clean', 'armed', 'infecting', 'infected_running', 'dormant'];
let counter = 0;
- // ~1 event/sec — slow enough that the audience can read each
- // prediction as it lands, fast enough that the lanes feel
- // alive. Real ceiling is ~1.5/sec (3 hosts × 5 models × one
- // window every 10 s) so we're under it but not by a lot.
+ // ~0.4 events/sec. Real ceiling with two contributing hosts
+ // (elliott-thinkpad, k-gamingcom) is ~1 event/sec — we stay
+ // well under so the lane cells read as deliberate, not as a
+ // contrived stream.
demoTimer = setInterval(() => {
const m = MODELS[counter % MODELS.length];
counter++;
@@ -2299,7 +2299,7 @@ def train_nn(*, model, X_train, y_train, X_val, y_val,
window_idx: counter,
t_wall: Date.now() / 1000,
});
- }, 1000);
+ }, 2500);
}
function demoStop() {
demoActive = false;
diff --git a/training/dashboard/static/index.html b/training/dashboard/static/index.html
index bf6c718..6d6c719 100644
--- a/training/dashboard/static/index.html
+++ b/training/dashboard/static/index.html
@@ -1313,6 +1313,6 @@
-
+