// PEN Landing — Live console mock for hero section. // Shows a compact "operations" panel with live-feel: // - scan progress bar that loops // - threat feed where rows reveal one-by-one then animate "containment" // - tabular numeric KPIs const { useState: useStateLC, useEffect: useEffectLC, useRef: useRefLC } = React; function LiveConsole({ copy }) { // ── Scan progress loop ───────────────────────────────────── const [scan, setScan] = useStateLC(0.12); useEffectLC(() => { const t = setInterval(() => { setScan((p) => p >= 0.98 ? 0.08 : p + 0.018); }, 220); return () => clearInterval(t); }, []); // ── Clock ticks (for the "ts" col + status) ──────────────── const [tick, setTick] = useStateLC(0); useEffectLC(() => { const t = setInterval(() => setTick((x) => x + 1), 1000); return () => clearInterval(t); }, []); // ── Threat feed: reveal rows, then mark them contained ───── const baseFeed = copy.threats; const [revealed, setRevealed] = useStateLC(2); // start with 2 rows visible const [contained, setContained] = useStateLC({}); // index -> true useEffectLC(() => { let r = 2; setRevealed(2); setContained({}); const revealTimer = setInterval(() => { r++; if (r > baseFeed.length) { clearInterval(revealTimer); } else { setRevealed(r); } }, 1100); // After 4s start containing the criticals one-by-one const containTimer = setTimeout(() => { let idx = 0; const ct = setInterval(() => { setContained((prev) => ({ ...prev, [idx]: true })); idx++; if (idx >= 2) clearInterval(ct); }, 1600); }, 4200); return () => {clearInterval(revealTimer);clearTimeout(containTimer);}; }, [copy]); // ── KPI nudges (animated count) ──────────────────────────── const kpis = copy.kpis; const hostsScanned = Math.round(scan * 217); const eta = String(Math.max(2, Math.round((1 - scan) * 90))).padStart(2, "0"); return (