// --- 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 & Speed Fix --- // Helper: Debounce function prevents the code from running too often // (e.g. while scrolling on mobile which triggers resize events) function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } function adjustMarqueeWidth() { const track = document.getElementById('marquee-track'); if (!track) return; // 1. Get the rendered width of the single list of partners const currentWidth = track.scrollWidth; // 2. Calculate how many times we need to repeat the list // Target: We want the track to be at least 3x the screen width // so it scrolls smoothly without running out of items before looping. const targetWidth = window.innerWidth * 3; const repeats = Math.max(2, Math.ceil(targetWidth / currentWidth)); // 3. Store the original HTML (the first run of the loop) const originalContent = track.innerHTML; // 4. Rebuild the track with the repeated content track.innerHTML = ''; for (let i = 0; i < repeats; i++) { track.innerHTML += originalContent; } // --- NEW: Calculate Constant Speed --- // The animation moves -50% of the track width. const totalWidth = track.scrollWidth; const distanceToMove = totalWidth / 2; // Desired speed in pixels per second (Adjust this number to make it faster/slower) // 50 = Relaxed/Easy reading speed // 100 = Faster const pixelsPerSecond = 50; // Duration = Distance / Speed const durationInSeconds = distanceToMove / pixelsPerSecond; // Apply the calculated duration track.style.animationDuration = `${durationInSeconds}s`; } // Run on load window.addEventListener('load', adjustMarqueeWidth); // Run on resize (Debounced by 200ms to prevent flickering during scroll) window.addEventListener('resize', debounce(adjustMarqueeWidth, 200));