async function hydrateMetrics() { try { const response = await fetch("/api/bootstrap"); if (!response.ok) return; const payload = await response.json(); const submissions = payload.submissions || []; const providers = payload.providers || []; const knowledge = payload.knowledgeEntries || []; const evidenceCount = submissions.reduce((total, submission) => total + (submission.evidence || []).length, 0); const activeProviders = providers.filter((provider) => provider.enabled).length; setText("metric-submissions", submissions.length); setText("metric-evidence", evidenceCount); setText("metric-knowledge", knowledge.length); setText("metric-providers", `${activeProviders}/${providers.length || 0}`); } catch { // The page still works as a static artifact if the API is unavailable. } } function setText(id, value) { const target = document.getElementById(id); if (target) target.textContent = String(value); } function mountRevealObserver() { const targets = document.querySelectorAll(".reveal"); if (!("IntersectionObserver" in window)) { targets.forEach((target) => target.classList.add("visible")); return; } const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (!entry.isIntersecting) return; entry.target.classList.add("visible"); observer.unobserve(entry.target); }); }, { rootMargin: "0px 0px -10% 0px", threshold: 0.12 }, ); targets.forEach((target) => observer.observe(target)); } document.addEventListener("DOMContentLoaded", () => { mountRevealObserver(); hydrateMetrics(); });