document.addEventListener("DOMContentLoaded", function () { const pages = Array.from(document.querySelectorAll(".page")); const navLinks = Array.from(document.querySelectorAll("[data-route]")); const dropdowns = Array.from(document.querySelectorAll(".nav-dropdown")); const siteNav = document.querySelector(".site-nav"); const mobileNavToggle = document.querySelector(".mobile-nav-toggle"); function closeMobileNav() { if (!siteNav || !mobileNavToggle) return; siteNav.classList.remove("open"); mobileNavToggle.setAttribute("aria-expanded", "false"); } function openMobileNav() { if (!siteNav || !mobileNavToggle) return; siteNav.classList.add("open"); mobileNavToggle.setAttribute("aria-expanded", "true"); } function toggleMobileNav() { if (!siteNav || !mobileNavToggle) return; const willOpen = !siteNav.classList.contains("open"); if (willOpen) { openMobileNav(); } else { closeMobileNav(); closeAllDropdowns(); } } function closeAllDropdowns(exceptDropdown = null) { if (mobileNavToggle) { mobileNavToggle.addEventListener("click", (e) => { e.preventDefault(); toggleMobileNav(); }); } dropdowns.forEach((dropdown) => { if (dropdown === exceptDropdown) return; dropdown.classList.remove("open"); const toggle = dropdown.querySelector(".nav-dropdown-toggle"); if (toggle) { toggle.setAttribute("aria-expanded", "false"); } }); } function syncDropdownState() { dropdowns.forEach((dropdown) => { const toggle = dropdown.querySelector(".nav-dropdown-toggle"); if (!toggle) return; const expanded = dropdown.classList.contains("open") ? "true" : "false"; toggle.setAttribute("aria-expanded", expanded); }); } dropdowns.forEach((dropdown) => { const toggle = dropdown.querySelector(".nav-dropdown-toggle"); const dropdownMenuLinks = Array.from(dropdown.querySelectorAll(".nav-dropdown-menu [data-route]")); if (!toggle) return; toggle.addEventListener("click", (e) => { e.preventDefault(); const parentRoute = toggle.dataset.route || "home"; if (window.innerWidth <= 900) { closeAllDropdowns(); window.location.hash = parentRoute === "eightx8" ? "8x8" : parentRoute; setActive(parentRoute); return; } const willOpen = !dropdown.classList.contains("open"); closeAllDropdowns(dropdown); dropdown.classList.toggle("open", willOpen); toggle.setAttribute("aria-expanded", willOpen ? "true" : "false"); if (willOpen) { window.location.hash = parentRoute === "eightx8" ? "8x8" : parentRoute; setActive(parentRoute); } }); dropdownMenuLinks.forEach((link) => { link.addEventListener("click", () => { closeAllDropdowns(); window.setTimeout(() => { if (document.activeElement) { document.activeElement.blur(); } }, 0); }); }); }); document.addEventListener("click", (e) => { const clickedInsideDropdown = dropdowns.some((dropdown) => dropdown.contains(e.target)); const clickedInsideNav = siteNav ? siteNav.contains(e.target) : false; const clickedMobileToggle = mobileNavToggle ? mobileNavToggle.contains(e.target) : false; if (!clickedInsideDropdown) { closeAllDropdowns(); } if (window.innerWidth <= 900 && !clickedInsideNav && !clickedMobileToggle) { closeMobileNav(); } }); document.addEventListener("keydown", (e) => { if (e.key === "Escape") { closeAllDropdowns(); closeMobileNav(); } }); const serviceRoutes = new Set([ "services", "unified-communications", "contact-center", "managed-support", "consulting-training", "infrastructure-cabling", "wireless-access", "local-networking" ]); const industryRoutes = new Set([ "industries", "healthcare", "retail", "manufacturing", "education-finance" ]); function setActive(route) { const requested = route || "home"; const hasRoute = pages.some((p) => p.dataset.page === requested); const target = hasRoute ? requested : "home"; pages.forEach((p) => { const isActive = p.dataset.page === target; p.classList.toggle("active", isActive); p.setAttribute("aria-hidden", isActive ? "false" : "true"); }); navLinks.forEach((a) => { const routeName = a.dataset.route; const isServiceParent = routeName === "services" && serviceRoutes.has(target); const isIndustryParent = routeName === "industries" && industryRoutes.has(target); const isActive = routeName === target || isServiceParent || isIndustryParent; a.classList.toggle("active", isActive); if (isActive) { a.setAttribute("aria-current", "page"); } else { a.removeAttribute("aria-current"); } }); syncDropdownState(); window.scrollTo({ top: 0, behavior: "instant" }); if (target === "home") { startHeroMotion(); } else { stopHeroMotion(); } } function routeFromHash() { const hash = (window.location.hash || "#home").replace("#", "").trim(); if (hash === "8x8") return "eightx8"; return hash || "home"; } navLinks.forEach((a) => { a.addEventListener("click", (e) => { const route = a.dataset.route; if (!route) return; e.preventDefault(); window.location.hash = route === "eightx8" ? "8x8" : route; setActive(route); if (window.innerWidth <= 900) { closeMobileNav(); closeAllDropdowns(); } }); }); const cta = document.getElementById("cta-consultation"); if (cta) { cta.addEventListener("click", () => { window.location.hash = "contact"; setActive("contact"); closeMobileNav(); closeAllDropdowns(); }); } window.addEventListener("hashchange", () => { setActive(routeFromHash()); }); window.addEventListener("resize", () => { if (window.innerWidth <= 900) { closeAllDropdowns(); } }); const yearSpan = document.getElementById("year"); if (yearSpan) yearSpan.textContent = new Date().getFullYear(); const rotatorEl = document.getElementById("hero-rotator-text"); const lockupEl = document.getElementById("hero-lockup"); const phrases = [ "Technical Precision", "Operational Clarity", "Human-Centered Support" ]; const phraseFadeIn = 1100; const phraseHold = 1900; const phraseFadeOut = 1100; const betweenGap = 500; const lockupFadeIn = 1200; const lockupHold = 6500; const loopGap = 800; let heroTimer = null; let heroRunId = 0; function showEl(el) { if (!el) return; el.classList.add("is-visible"); el.classList.remove("is-hidden"); } function hideEl(el) { if (!el) return; el.classList.remove("is-visible"); el.classList.add("is-hidden"); } function setText(el, text) { if (!el) return; el.textContent = text; } function sleep(ms) { return new Promise((resolve) => { heroTimer = window.setTimeout(resolve, ms); }); } function clearHeroTimer() { if (heroTimer) { window.clearTimeout(heroTimer); heroTimer = null; } } async function heroLoop(runId) { if (!rotatorEl || !lockupEl) return; hideEl(lockupEl); hideEl(rotatorEl); while (runId === heroRunId) { for (let i = 0; i < phrases.length; i++) { if (runId !== heroRunId) return; setText(rotatorEl, phrases[i]); rotatorEl.style.setProperty("--hero-fade-ms", `${phraseFadeIn}ms`); rotatorEl.style.setProperty("--hero-drift-ms", `${phraseFadeIn + phraseHold + phraseFadeOut}ms`); showEl(rotatorEl); await sleep(phraseFadeIn); await sleep(phraseHold); hideEl(rotatorEl); await sleep(phraseFadeOut); await sleep(betweenGap); } if (runId !== heroRunId) return; lockupEl.style.setProperty("--hero-lockup-fade-ms", `${lockupFadeIn}ms`); showEl(lockupEl); await sleep(lockupFadeIn); await sleep(lockupHold); hideEl(lockupEl); await sleep(loopGap); } } function startHeroMotion() { if (!rotatorEl || !lockupEl) return; heroRunId += 1; clearHeroTimer(); hideEl(lockupEl); hideEl(rotatorEl); heroLoop(heroRunId); } function stopHeroMotion() { heroRunId += 1; clearHeroTimer(); hideEl(lockupEl); hideEl(rotatorEl); } window.addEventListener("resize", () => { if (window.innerWidth > 900) { closeMobileNav(); } }); setActive(routeFromHash()); });