// Tiny shared harness for challenge pages. // Each page calls Challenge.init({id, instructions}) then Challenge.pass()/fail() // based on its own listeners. (function () { const events = []; const state = { id: null, verdict: "PENDING", reason: [], events, }; function render() { const el = document.getElementById("__verdict"); if (!el) return; el.textContent = state.verdict; el.dataset.verdict = state.verdict; el.style.background = state.verdict === "PASS" ? "#1f7a1f" : state.verdict === "FAIL" ? "#a11" : "#444"; el.style.color = "#fff"; const r = document.getElementById("__reason"); if (r) r.textContent = state.reason.join("\n"); } function log(name, detail) { events.push({ t: performance.now(), name, ...detail }); if (events.length > 500) events.shift(); } const Challenge = { init({ id, instructions }) { state.id = id; document.title = `[${state.verdict}] ${id}`; const root = document.body; const bar = document.createElement("div"); bar.style.cssText = "position:sticky;top:0;background:#111;color:#eee;padding:8px 12px;font:13px monospace;border-bottom:1px solid #333;z-index:9999"; bar.innerHTML = ` ${id} PENDING ${instructions}
`; root.insertBefore(bar, root.firstChild); window.__challenge = id; window.__verdict = state.verdict; window.__reason = state.reason; window.__events = state.events; render(); }, pass(...reasons) { if (state.verdict === "FAIL") return; // sticky state.verdict = "PASS"; state.reason.push(...reasons.map((r) => "✓ " + r)); window.__verdict = state.verdict; document.title = `[PASS] ${state.id}`; persist(); render(); }, fail(...reasons) { state.verdict = "FAIL"; state.reason.push(...reasons.map((r) => "✗ " + r)); window.__verdict = state.verdict; document.title = `[FAIL] ${state.id}`; persist(); render(); }, log, state, }; function persist() { try { localStorage.setItem( "pi-chrome-suite:" + state.id, JSON.stringify({ verdict: state.verdict, reason: state.reason, ts: Date.now() }) ); } catch {} } window.Challenge = Challenge; })();