68d29ae532
- Fix mobile nav: all 3 dropdowns now get click handlers (was only first) - Remove Our Work from nav - Add Google Maps embed to homepage footer - Update title and meta description/keywords/canonical - Unique hero image per page (14 pages updated) - Remove technician clip from hero reel - Add .cpanel.yml for cPanel Git deployment - Add hero image generation script (ComfyUI SDXL) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
74 lines
2.6 KiB
JavaScript
74 lines
2.6 KiB
JavaScript
const mobileToggle = document.querySelector('.mobile-menu-toggle');
|
|
const navLinks = document.querySelector('.nav-links');
|
|
const navContact = document.querySelector('.nav-contact');
|
|
if (mobileToggle) {
|
|
mobileToggle.addEventListener('click', () => {
|
|
navLinks.classList.toggle('active');
|
|
navContact.classList.toggle('active');
|
|
mobileToggle.classList.toggle('active');
|
|
});
|
|
}
|
|
|
|
// Mobile dropdowns — wire ALL dropdown labels, not just the first
|
|
document.querySelectorAll('.nav-dropdown').forEach(function(dropdown) {
|
|
var label = dropdown.querySelector('.dropdown-label');
|
|
if (!label) return;
|
|
label.addEventListener('click', function(e) {
|
|
if (window.innerWidth <= 768) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
// Close all other open dropdowns
|
|
document.querySelectorAll('.nav-dropdown.open').forEach(function(other) {
|
|
if (other !== dropdown) other.classList.remove('open');
|
|
});
|
|
dropdown.classList.toggle('open');
|
|
}
|
|
});
|
|
});
|
|
|
|
document.addEventListener('click', function(e) {
|
|
if (!e.target.closest('.nav-dropdown')) {
|
|
document.querySelectorAll('.nav-dropdown.open').forEach(function(d) {
|
|
d.classList.remove('open');
|
|
});
|
|
}
|
|
});
|
|
const form = document.getElementById('quoteForm');
|
|
if (form) {
|
|
form.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
alert('Thank you for your quote request! We will contact you shortly.');
|
|
this.reset();
|
|
});
|
|
}
|
|
|
|
// How It Works — scroll-triggered step reveal
|
|
(function () {
|
|
function initProcess() {
|
|
var track = document.querySelector('.process-track');
|
|
if (!track) return;
|
|
var steps = track.querySelectorAll('.process-step');
|
|
var observer = new IntersectionObserver(function (entries) {
|
|
entries.forEach(function (entry) {
|
|
if (entry.isIntersecting) {
|
|
track.classList.add('animated');
|
|
steps.forEach(function (step, i) {
|
|
setTimeout(function () {
|
|
step.classList.add('visible');
|
|
}, i * 220);
|
|
});
|
|
observer.disconnect();
|
|
}
|
|
});
|
|
}, { threshold: 0.25 });
|
|
observer.observe(track);
|
|
}
|
|
// components.js runs before main.js, but process section is injected synchronously
|
|
// so it's available immediately
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initProcess);
|
|
} else {
|
|
initProcess();
|
|
}
|
|
}());
|