// --- Toggle Mobile Menu --- // --- Mobile Navigation --- function toggleMenu() { document.getElementById('mobile-nav').classList.toggle('open'); } // --- Intersection Observer for Scroll Animations --- const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) entry.target.classList.add('active'); }); }, { threshold: 0.1 }); document.querySelectorAll('.reveal').forEach(el => observer.observe(el)); // --- Generic Horizontal Scroll Logic (Services, Team, Testimonials) --- function scrollCarousel(trackId, direction) { const track = document.getElementById(trackId); if (!track) return; const firstItem = track.querySelector('.carousel-item'); if (!firstItem) return; const itemWidth = firstItem.offsetWidth; const gap = 24; const scrollAmount = itemWidth + gap; // Adjust direction for RTL let scrollDir = direction; if (document.dir === 'rtl') { scrollDir = direction * -1; } if (scrollDir === -1) { track.scrollBy({ left: -scrollAmount, behavior: 'smooth' }); } else { track.scrollBy({ left: scrollAmount, behavior: 'smooth' }); } } // --- Product Slider Logic (Fade) --- const slides = document.querySelectorAll('.product-slide'); const indicators = document.querySelectorAll('.indicator'); const prevBtn = document.getElementById('prev-btn'); const nextBtn = document.getElementById('next-btn'); const productWrapper = document.querySelector('.product-slider-wrapper'); let currentSlide = 0; const totalSlides = slides.length; let slideInterval; if(totalSlides > 0) { function showSlide(index) { if (index >= totalSlides) currentSlide = 0; else if (index < 0) currentSlide = totalSlides - 1; else currentSlide = index; slides.forEach(slide => slide.classList.remove('active')); indicators.forEach(ind => ind.classList.remove('active')); slides[currentSlide].classList.add('active'); indicators[currentSlide].classList.add('active'); } function nextSlide() { showSlide(currentSlide + 1); } function prevSlide() { showSlide(currentSlide - 1); } if(nextBtn) { nextBtn.addEventListener('click', () => { nextSlide(); resetTimer(); }); } if(prevBtn) { prevBtn.addEventListener('click', () => { prevSlide(); resetTimer(); }); } indicators.forEach((ind, index) => { ind.addEventListener('click', () => { showSlide(index); resetTimer(); }); }); function startTimer() { slideInterval = setInterval(nextSlide, 5000); } function resetTimer() { clearInterval(slideInterval); startTimer(); } if(productWrapper) { productWrapper.addEventListener('mouseenter', () => clearInterval(slideInterval)); productWrapper.addEventListener('mouseleave', startTimer); startTimer(); } } // --- Form Submission (AJAX) --- function showToast(message) { const toast = document.getElementById('toast'); toast.textContent = message; toast.style.transform = 'translateY(0)'; setTimeout(() => { toast.style.transform = 'translateY(150%)'; }, 3000); } document.getElementById('contactForm').addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); const submitBtn = this.querySelector('button[type="submit"]'); const originalText = submitBtn.textContent; submitBtn.textContent = '{% trans "Sending..." %}'; submitBtn.disabled = true; fetch("{% url 'submit_inquiry' %}", { method: 'POST', body: formData, headers: { 'X-Requested-With': 'XMLHttpRequest' } }) .then(response => response.json()) .then(data => { if(data.status === 'success') { showToast(data.message); document.getElementById('contactForm').reset(); } else { showToast('Error: ' + (data.message || 'Something went wrong')); } }) .catch(error => { showToast('Error: Could not submit form.'); console.error('Error:', error); }) .finally(() => { submitBtn.textContent = originalText; submitBtn.disabled = false; }); }); // --- Marquee Width Fix --- // Ensures the partner list is always wide enough to scroll smoothly function adjustMarqueeWidth() { const track = document.getElementById('marquee-track'); if (!track) return; // Get the rendered width of the single list const currentWidth = track.scrollWidth; // Target width: We want the track to be at least 200% of screen width // so it has enough room to scroll off-screen before resetting. const targetWidth = window.innerWidth * 2.0; // Calculate how many times we need to repeat the list to reach target width const repeats = Math.max(2, Math.ceil(targetWidth / currentWidth)); // Get the raw HTML content (the first run of the loop) const originalContent = track.innerHTML; // Rebuild the track with the repeated content track.innerHTML = ''; for (let i = 0; i < repeats; i++) { track.innerHTML += originalContent; } } // Run on load and resize window.addEventListener('load', adjustMarqueeWidth); window.addEventListener('resize', adjustMarqueeWidth);