/** * Gestoría LP — Main JavaScript * Handles: mobile menu, smooth scroll, navbar scroll effect, scroll animations */ document.addEventListener('DOMContentLoaded', function () { // ---- DOM References ---- const navbar = document.getElementById('navbar'); const navToggle = document.getElementById('navToggle'); const navMenu = document.getElementById('navMenu'); const body = document.body; // Create overlay element for mobile menu backdrop const overlay = document.createElement('div'); overlay.classList.add('navbar__overlay'); document.body.appendChild(overlay); // ================================================================ // 1. Mobile Hamburger Menu Toggle // ================================================================ function openMenu() { navToggle.classList.add('active'); navMenu.classList.add('active'); overlay.classList.add('active'); navToggle.setAttribute('aria-expanded', 'true'); body.style.overflow = 'hidden'; } function closeMenu() { navToggle.classList.remove('active'); navMenu.classList.remove('active'); overlay.classList.remove('active'); navToggle.setAttribute('aria-expanded', 'false'); body.style.overflow = ''; } if (navToggle) { navToggle.addEventListener('click', function () { if (navMenu.classList.contains('active')) { closeMenu(); } else { openMenu(); } }); } // Close menu when clicking overlay overlay.addEventListener('click', closeMenu); // Close menu when pressing Escape document.addEventListener('keydown', function (e) { if (e.key === 'Escape' && navMenu.classList.contains('active')) { closeMenu(); } }); // ================================================================ // 2. Dropdown Toggle (mobile + touch devices) // ================================================================ var dropdownItems = document.querySelectorAll('.navbar__item--dropdown'); dropdownItems.forEach(function (item) { var link = item.querySelector('.navbar__link--dropdown'); if (link) { link.addEventListener('click', function (e) { // Always prevent default on the dropdown parent link e.preventDefault(); e.stopPropagation(); item.classList.toggle('active'); }); } }); // Close dropdown when clicking outside (desktop) document.addEventListener('click', function (e) { dropdownItems.forEach(function (item) { if (!item.contains(e.target)) { item.classList.remove('active'); } }); }); // ================================================================ // 3. Smooth Scroll for Anchor Links // ================================================================ var anchorLinks = document.querySelectorAll('a[href^="#"]'); anchorLinks.forEach(function (link) { // Skip dropdown toggle links — they have their own handler if (link.classList.contains('navbar__link--dropdown')) return; link.addEventListener('click', function (e) { var targetId = this.getAttribute('href'); if (targetId === '#') return; var target = document.querySelector(targetId); if (target) { e.preventDefault(); closeMenu(); var navHeight = navbar ? navbar.offsetHeight : 0; var targetPos = target.getBoundingClientRect().top + window.pageYOffset - navHeight; window.scrollTo({ top: targetPos, behavior: 'smooth' }); } }); }); // ================================================================ // 4. Navbar Background/Shadow on Scroll // ================================================================ var lastScrollY = 0; function handleNavbarScroll() { var scrollY = window.pageYOffset || document.documentElement.scrollTop; if (scrollY > 20) { navbar.classList.add('navbar--scrolled'); } else { navbar.classList.remove('navbar--scrolled'); } lastScrollY = scrollY; } if (navbar) { window.addEventListener('scroll', handleNavbarScroll, { passive: true }); // Run once on load handleNavbarScroll(); } // ================================================================ // 5. Scroll Animations (Testimonials & fade-up elements) // ================================================================ function animateOnScroll() { // Testimonial cards var testimonialCards = document.querySelectorAll('.testimonial-card:not(.animate-in)'); testimonialCards.forEach(function (card, index) { var rect = card.getBoundingClientRect(); var windowHeight = window.innerHeight; if (rect.top < windowHeight * 0.88) { // Stagger the animation setTimeout(function () { card.classList.add('animate-in'); }, index * 120); } }); // Generic fade-up elements var fadeElements = document.querySelectorAll('.fade-up:not(.visible)'); fadeElements.forEach(function (el) { var rect = el.getBoundingClientRect(); var windowHeight = window.innerHeight; if (rect.top < windowHeight * 0.88) { el.classList.add('visible'); } }); } window.addEventListener('scroll', animateOnScroll, { passive: true }); // Run once on load to catch elements already in viewport animateOnScroll(); // ================================================================ // 6. Close mobile dropdown on window resize to desktop // ================================================================ window.addEventListener('resize', function () { if (window.innerWidth > 768) { closeMenu(); dropdownItems.forEach(function (item) { item.classList.remove('active'); }); } }); // ================================================================ // 7. Dark / Light Theme Toggle // ================================================================ var themeToggle = document.getElementById('themeToggle'); var themeIcon = document.getElementById('themeIcon'); function setTheme(theme) { document.documentElement.setAttribute('data-theme', theme); localStorage.setItem('theme', theme); if (themeIcon) { themeIcon.className = theme === 'light' ? 'fas fa-sun' : 'fas fa-moon'; } // Update theme-color meta tag var metaTheme = document.querySelector('meta[name="theme-color"]'); if (metaTheme) { metaTheme.setAttribute('content', theme === 'light' ? '#f5f5f5' : '#0a0a0a'); } } // Determine initial theme: localStorage > system preference > dark var savedTheme = localStorage.getItem('theme'); if (savedTheme) { setTheme(savedTheme); } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) { setTheme('light'); } // else: default is dark (no data-theme attribute needed) if (themeToggle) { themeToggle.addEventListener('click', function () { var current = document.documentElement.getAttribute('data-theme'); setTheme(current === 'light' ? 'dark' : 'light'); }); } });