// Page transition functionality document.addEventListener("DOMContentLoaded", function () { // Top/Bottom curtain transition system const curtainTop = document.getElementById("pageCurtainTop") || (() => { const div = document.createElement("div"); div.id = "pageCurtainTop"; div.className = "fixed inset-x-0 top-0 h-1/2 z-50 transform -translate-y-full transition-transform duration-600 ease-in-out"; div.style.background = "linear-gradient(0deg, #b03037, #8a252a)"; document.body.appendChild(div); return div; })(); const curtainBottom = document.getElementById("pageCurtainBottom") || (() => { const div = document.createElement("div"); div.id = "pageCurtainBottom"; div.className = "fixed inset-x-0 bottom-0 h-1/2 z-50 transform translate-y-full transition-transform duration-600 ease-in-out"; div.style.background = "linear-gradient(180deg, #b03037, #8a252a)"; document.body.appendChild(div); return div; })(); // Add entrance animation class document.body.style.animation = "pageEnter 0.6s ease-out"; document.querySelectorAll("a[data-trans]").forEach((a) => { a.addEventListener("click", (e) => { const href = a.getAttribute("href"); if (!href || href.startsWith("#")) return; e.preventDefault(); // Collect elements that had delayed entrance and fade them out in reverse order const animatedEls = Array.from( document.querySelectorAll('[style*="animation-delay"]') ).map((el) => { const m = (el.getAttribute("style") || "").match( /animation-delay:\s*([0-9.]+)s/ ); const delay = m ? parseFloat(m[1]) : 0; return { el, delay }; }); const sorted = animatedEls .sort((a, b) => b.delay - a.delay) .map((item, idx) => ({ ...item, order: idx })); sorted.forEach((item) => { setTimeout(() => { item.el.style.animation = "staggerFadeOut 260ms ease-out forwards"; }, item.order * 50); }); const totalStaggerTime = (sorted.length - 1) * 50 + 260 + 130; setTimeout(() => { // Crossfade + tiny zoom of the whole page (longer) document.body.style.animation = "pageExit 900ms ease forwards"; setTimeout(() => { location.href = href; }, 920); }, totalStaggerTime); }); }); // Hide curtains and close nav just before page is cached (prevents blank back step) window.addEventListener("pagehide", () => { if (curtainTop) curtainTop.style.transform = "translateY(-100%)"; if (curtainBottom) curtainBottom.style.transform = "translateY(100%)"; const navEl = document.getElementById("navMenu"); const gridEl = document.getElementById("menuGrid"); if (navEl) navEl.classList.add("hidden"); const wrapEl = document.getElementById("menuWrap"); if (wrapEl) wrapEl.classList.remove("open"); }); // Handle back/forward navigation window.addEventListener("pageshow", function (event) { if (event.persisted) { // Page was loaded from cache (back/forward) window.location.reload(); } }); // Ensure back/forward navigation (bfcache) shows a clean page window.addEventListener("pageshow", () => { const loadingScreen = document.getElementById("loadingScreen"); if (loadingScreen) { loadingScreen.style.display = "none"; loadingScreen.style.opacity = "0"; } const ct = document.getElementById("pageCurtainTop"); const cb = document.getElementById("pageCurtainBottom"); if (ct) ct.style.transform = "translateY(-100%)"; if (cb) cb.style.transform = "translateY(100%)"; // Close nav if it was left open and reset grid icon const navMenuEl = document.getElementById("navMenu"); const wrapEl2 = document.getElementById("menuWrap"); if (navMenuEl) navMenuEl.classList.add("hidden"); if (wrapEl2) wrapEl2.classList.remove("open"); }); });