// Get Well Physio — Main JS // ── Active Nav Link ────────────────────────────────────────────────────────── function setActiveNavLink(): void { const path = window.location.pathname; document.querySelectorAll('.site-navbar .nav-link').forEach(link => { link.classList.remove('active'); const href = link.getAttribute('href') ?? ''; // Match root → index.html / "/" if ( (path.endsWith('/') || path.endsWith('index.html')) && (href === '/' || href === 'index.html' || href === './index.html') ) { link.classList.add('active'); } else if (href !== '/' && href !== 'index.html' && path.includes(href.replace('.html', ''))) { link.classList.add('active'); } }); } // ── Back to Top ────────────────────────────────────────────────────────────── function initBackToTop(): void { const btn = document.getElementById('backToTop'); if (!btn) return; window.addEventListener('scroll', () => { btn.classList.toggle('visible', window.scrollY > 400); }); btn.addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' })); } // ── Counter Animation ──────────────────────────────────────────────────────── function animateCounters(): void { const els = document.querySelectorAll('[data-count]'); if (!els.length) return; const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (!entry.isIntersecting) return; const el = entry.target as HTMLElement; const target = parseInt(el.dataset['count'] ?? '0', 10); const duration = 2200; const step = Math.ceil(target / (duration / 16)); let current = 0; const tick = () => { current = Math.min(current + step, target); el.textContent = current.toLocaleString(); if (current < target) requestAnimationFrame(tick); }; requestAnimationFrame(tick); observer.unobserve(el); }); }, { threshold: 0.3 }); els.forEach(el => observer.observe(el)); } // ── Scroll Reveal ──────────────────────────────────────────────────────────── function initScrollReveal(): void { const items = document.querySelectorAll('.reveal'); if (!items.length) return; const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { (entry.target as HTMLElement).classList.add('revealed'); observer.unobserve(entry.target); } }); }, { threshold: 0.12 }); items.forEach(el => observer.observe(el)); } // ── Gallery Filter ─────────────────────────────────────────────────────────── function initGalleryFilter(): void { const filterBtns = document.querySelectorAll('.filter-btn'); const items = document.querySelectorAll('.gallery-item'); if (!filterBtns.length || !items.length) return; filterBtns.forEach(btn => { btn.addEventListener('click', () => { filterBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); const cat = btn.dataset['filter'] ?? 'all'; items.forEach(item => { const show = cat === 'all' || item.dataset['category'] === cat; item.style.display = show ? 'block' : 'none'; if (show) { item.style.animation = 'fadeInUp 0.4s ease both'; } }); }); }); } // ── Contact Form ───────────────────────────────────────────────────────────── function initContactForm(): void { const form = document.getElementById('contactForm') as HTMLFormElement | null; if (!form) return; form.addEventListener('submit', (e) => { e.preventDefault(); const btn = form.querySelector('[type=submit]'); if (!btn) return; const original = btn.innerHTML; btn.disabled = true; btn.innerHTML = 'Sending...'; setTimeout(() => { btn.disabled = false; btn.innerHTML = original; form.reset(); const successMsg = document.getElementById('formSuccess'); if (successMsg) { successMsg.style.display = 'block'; setTimeout(() => { successMsg.style.display = 'none'; }, 5000); } }, 1800); }); } // ── Sticky Navbar Shadow ───────────────────────────────────────────────────── function initNavbarScroll(): void { const nav = document.querySelector('.site-navbar'); if (!nav) return; window.addEventListener('scroll', () => { nav.style.boxShadow = window.scrollY > 10 ? '0 4px 24px rgba(21,101,192,0.14)' : '0 2px 16px rgba(21,101,192,0.10)'; }); } // ── Lightbox (simple) ──────────────────────────────────────────────────────── function initGalleryLightbox(): void { const items = document.querySelectorAll('.gallery-item'); if (!items.length) return; // Create modal const modal = document.createElement('div'); modal.id = 'galleryModal'; modal.style.cssText = ` display:none;position:fixed;inset:0;background:rgba(0,0,0,0.9);z-index:9999; align-items:center;justify-content:center;cursor:zoom-out; `; modal.innerHTML = ``; document.body.appendChild(modal); items.forEach(item => { item.addEventListener('click', () => { const img = item.querySelector('img'); if (!img) return; const modalImg = document.getElementById('galleryModalImg') as HTMLImageElement; modalImg.src = img.src; modal.style.display = 'flex'; }); }); modal.addEventListener('click', () => { modal.style.display = 'none'; }); document.addEventListener('keydown', (e) => { if (e.key === 'Escape') modal.style.display = 'none'; }); } // ── Init All ───────────────────────────────────────────────────────────────── document.addEventListener('DOMContentLoaded', () => { setActiveNavLink(); initBackToTop(); animateCounters(); initScrollReveal(); initGalleryFilter(); initContactForm(); initNavbarScroll(); initGalleryLightbox(); });