// ============================================================================ // Project : localvm-research // File : web/public/app.js // Purpose : Client-side interactivity (chart hover tooltips) // Author : Simon-Pierre Boucher // Contact : contact@spboucher.ai // Created : 2026-08-12 // Modified : 2026-08-12 // Platform : Web (deployed from macOS / Apple Silicon) // License : All rights reserved (research code) // ============================================================================ "use strict"; // mobile hamburger menu (function () { const toggle = document.getElementById("nav-toggle"); const nav = document.getElementById("site-nav"); if (!toggle || !nav) return; toggle.addEventListener("click", () => { const open = nav.classList.toggle("open"); toggle.classList.toggle("open", open); toggle.setAttribute("aria-expanded", String(open)); }); nav.addEventListener("click", (e) => { if (e.target.tagName === "A") { nav.classList.remove("open"); toggle.classList.remove("open"); } }); })(); // chart hover tooltips (function () { const fig = document.querySelector(".chart-fig"); if (!fig) return; const tip = fig.querySelector(".chart-tip"); if (!tip) return; fig.querySelectorAll(".pt").forEach((pt) => { pt.addEventListener("mouseenter", () => { tip.textContent = pt.getAttribute("data-tip"); tip.hidden = false; }); pt.addEventListener("mousemove", (ev) => { const r = fig.getBoundingClientRect(); tip.style.left = Math.min(ev.clientX - r.left + 14, r.width - tip.offsetWidth - 4) + "px"; tip.style.top = ev.clientY - r.top - 34 + "px"; }); pt.addEventListener("mouseleave", () => { tip.hidden = true; }); }); })();