// Smooth scroll for nav links document.querySelectorAll('a[href^="#"]').forEach((anchor) => { anchor.addEventListener("click", function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute("href")); if (target) { target.scrollIntoView({ behavior: "smooth" }); } }); }); // ─── Parallax ─── function initParallax() { const sections = document.querySelectorAll(".bg-image-section:not(#hero)"); const heroLayer = document.getElementById("hero-slideshow"); function update() { sections.forEach((section) => { const rect = section.getBoundingClientRect(); const yPos = -(rect.top * 0.4); section.style.backgroundPositionY = `${yPos}px`; }); if (heroLayer) { const hero = document.getElementById("hero"); if (hero) { const rect = hero.getBoundingClientRect(); const yPos = -(rect.top * 0.4); heroLayer.style.transform = `translateY(${yPos}px) scale(1.1)`; } } } window.addEventListener("scroll", update, { passive: true }); update(); } // ─── Hero Slideshow ─── let currentBackdrop = null; const NEAR_TOP_THRESHOLD = 1800; function checkDestructiveTheme() { if (!currentBackdrop) return; const nearTop = window.scrollY < NEAR_TOP_THRESHOLD; if (currentBackdrop.destructive && nearTop) { document.body.classList.add("destructive-mode"); } else { document.body.classList.remove("destructive-mode"); } } function initHeroSlideshow(allBackdrops, usedNames) { const hero = document.getElementById("hero"); const layer = document.getElementById("hero-slideshow"); if (!hero || !layer) return; const slides = allBackdrops.filter((b) => !usedNames.includes(b.name)); if (slides.length === 0) { console.warn("No unused backdrops for hero slideshow"); return; } let idx = 0; function pickRandomSlide(exclude) { if (slides.length === 1) return slides[0]; let pick; do { pick = slides[Math.floor(Math.random() * slides.length)]; } while (pick.name === exclude?.name); return pick; } function showSlide() { const backdrop = pickRandomSlide(currentBackdrop); currentBackdrop = backdrop; layer.style.opacity = "0"; setTimeout(() => { layer.style.backgroundImage = `url('/assets/${backdrop.name}.png')`; layer.style.opacity = "1"; checkDestructiveTheme(); }, 600); const delayMs = (backdrop.time || 6) * 1000; setTimeout(showSlide, delayMs); } const first = pickRandomSlide(); currentBackdrop = first; layer.style.backgroundImage = `url('/assets/${first.name}.png')`; layer.style.opacity = "1"; checkDestructiveTheme(); setTimeout(showSlide, (first.time || 6) * 1000); } // ─── Load Backdrops ─── async function loadBackdrops() { try { const response = await fetch("/api/backdrops.json"); const backdrops = await response.json(); const safeBackdrops = backdrops.filter((b) => !b.destructive); const sections = document.querySelectorAll(".bg-image-section:not(#hero)"); const used = []; sections.forEach((section) => { let pick; let safety = 0; do { pick = safeBackdrops[Math.floor(Math.random() * safeBackdrops.length)]; safety++; } while ( used.includes(pick.name) && used.length < safeBackdrops.length && safety < 50 ); used.push(pick.name); section.style.backgroundImage = `url('/assets/${pick.name}.png')`; }); initParallax(); initHeroSlideshow(backdrops, used); window.addEventListener("scroll", checkDestructiveTheme, { passive: true }); } catch (err) { console.error("Failed to load backdrops:", err); } } // ─── Load Staff ─── async function loadStaff() { try { const response = await fetch("/api/staff.json"); const staff = await response.json(); const container = document.getElementById("staff-grid"); if (!container) return; container.innerHTML = staff .map( (member) => `
${ member.icon ? `${member.name}` : '
' }
${member.name}
${member.role}
`, ) .join(""); } catch (err) { console.error("Failed to load staff:", err); } } // ─── Load Teams ─── async function loadTeams() { try { const response = await fetch("/api/teams.json"); const teams = await response.json(); const container = document.getElementById("teams-grid"); if (!container) return; container.innerHTML = teams .map((team) => { const acronym = team.acronym || ""; const vips = team.vips || ""; const hasDiscord = team.discord && team.discord.trim() !== ""; return `
${team.title}
${acronym ? `
${acronym}
` : ""}
${team.leader}
${ vips ? `
${vips}
` : "" }

${team.description}

${ hasDiscord ? ` Discord ` : "" }
`; }) .join(""); } catch (err) { console.error("Failed to load teams:", err); } } // ─── Load Posts ─── async function loadPosts() { try { const response = await fetch("/api/posts.json"); const posts = await response.json(); const container = document.getElementById("posts-grid"); if (!container) return; container.innerHTML = posts .map( (post) => `
${post.date}
${post.title}
${post.description}
`, ) .join(""); } catch (err) { console.error("Failed to load posts:", err); } } // ─── Video Play/Pause ─── function initVideo() { const playBtn = document.getElementById("play-btn"); const video = document.getElementById("trailer-video"); const container = document.querySelector(".video-container"); if (!playBtn || !video || !container) return; playBtn.addEventListener("click", () => { if (video.paused) { video.play(); container.classList.add("playing"); } else { video.pause(); container.classList.remove("playing"); } }); video.addEventListener("ended", () => { container.classList.remove("playing"); }); } // ─── Scroll Effects ─── function initScrollEffects() { const header = document.querySelector("header"); const footer = document.querySelector("footer"); const scrollThreshold = 200; function update() { const scrollY = window.scrollY; const docHeight = document.documentElement.scrollHeight; const winHeight = window.innerHeight; const nearBottom = scrollY + winHeight >= docHeight - 80; const shortPage = docHeight <= winHeight + 100; if (scrollY > 10) { header.classList.add("scrolled"); } else { header.classList.remove("scrolled"); } if (scrollY < scrollThreshold && !shortPage) { footer.classList.remove("visible"); } else { footer.classList.add("visible"); if (nearBottom || shortPage) { footer.classList.remove("glass"); footer.classList.add("solid"); } else { footer.classList.add("glass"); footer.classList.remove("solid"); } } } window.addEventListener("scroll", update, { passive: true }); update(); } // ─── Initialize ─── document.addEventListener("DOMContentLoaded", () => { loadBackdrops(); loadStaff(); loadTeams(); loadPosts(); initVideo(); initScrollEffects(); });