| |
| const observerOptions = { |
| root: null, |
| rootMargin: '0px', |
| threshold: 0.1 |
| }; |
|
|
| const observer = new IntersectionObserver((entries) => { |
| entries.forEach(entry => { |
| if (entry.isIntersecting) { |
| entry.target.classList.add('opacity-100', 'translate-y-0'); |
| entry.target.classList.remove('opacity-0', 'translate-y-10'); |
| } |
| }); |
| }, observerOptions); |
|
|
| |
| document.addEventListener('DOMContentLoaded', () => { |
| const elements = document.querySelectorAll('section > div, .group'); |
| elements.forEach((el, index) => { |
| el.classList.add('transition-all', 'duration-700', 'opacity-0', 'translate-y-10'); |
| el.style.transitionDelay = `${index * 50}ms`; |
| observer.observe(el); |
| }); |
| |
| |
| const form = document.querySelector('form'); |
| if (form) { |
| |
| const inputs = form.querySelectorAll('input, textarea, select'); |
| inputs.forEach(input => { |
| input.addEventListener('focus', () => { |
| input.parentElement.classList.add('focused'); |
| }); |
| input.addEventListener('blur', () => { |
| input.parentElement.classList.remove('focused'); |
| if (input.value.trim()) { |
| input.classList.add('field-valid'); |
| input.classList.remove('field-invalid'); |
| } else if (input.hasAttribute('required')) { |
| input.classList.add('field-invalid'); |
| input.classList.remove('field-valid'); |
| } |
| }); |
| |
| input.addEventListener('input', () => { |
| if (input.tagName === 'TEXTAREA') { |
| const remaining = 500 - input.value.length; |
| let counter = input.parentElement.querySelector('.char-counter'); |
| if (!counter) { |
| counter = document.createElement('div'); |
| counter.className = 'char-counter text-xs font-mono text-slate-500 text-right mt-1'; |
| input.parentElement.appendChild(counter); |
| } |
| counter.textContent = `${remaining} caractères restants`; |
| counter.style.color = remaining < 50 ? '#f59e0b' : remaining < 0 ? '#ef4444' : '#64748b'; |
| } |
| }); |
| }); |
|
|
| form.addEventListener('submit', (e) => { |
| e.preventDefault(); |
| const btn = form.querySelector('button[type="submit"]'); |
| const originalText = btn.innerText; |
| const originalClasses = btn.className; |
| |
| btn.innerHTML = '<span class="inline-flex items-center gap-2"><svg class="animate-spin h-4 w-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg> ENVOI EN COURS...</span>'; |
| btn.disabled = true; |
| btn.style.opacity = '0.8'; |
| |
| setTimeout(() => { |
| btn.innerHTML = '✓ DEMANDE ENVOYÉE'; |
| btn.className = btn.className.replace('from-primary', 'from-green-500').replace('to-cyan-600', 'to-green-600'); |
| btn.style.opacity = '1'; |
| |
| |
| form.style.transition = 'all 0.3s ease'; |
| form.style.boxShadow = '0 0 30px rgba(34, 197, 94, 0.2)'; |
| setTimeout(() => { form.style.boxShadow = ''; }, 2000); |
| |
| setTimeout(() => { |
| form.reset(); |
| inputs.forEach(input => { |
| input.classList.remove('field-valid', 'field-invalid'); |
| }); |
| |
| form.querySelectorAll('.char-counter').forEach(c => c.remove()); |
| btn.textContent = originalText; |
| btn.disabled = false; |
| btn.className = originalClasses; |
| }, 3000); |
| }, 1500); |
| }); |
| } |
|
|
| |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { |
| anchor.addEventListener('click', function (e) { |
| e.preventDefault(); |
| const targetId = this.getAttribute('href'); |
| const target = document.querySelector(targetId); |
| if (target) { |
| const navHeight = 80; |
| const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - navHeight; |
| window.scrollTo({ |
| top: targetPosition, |
| behavior: 'smooth' |
| }); |
| } |
| }); |
| }); |
|
|
| |
| const heroSection = document.querySelector('section'); |
| if (heroSection) { |
| window.addEventListener('scroll', () => { |
| const scrolled = window.pageYOffset; |
| const bgElements = heroSection.querySelectorAll('.absolute'); |
| bgElements.forEach((el, i) => { |
| const speed = 0.1 + (i * 0.05); |
| el.style.transform = `translateY(${scrolled * speed}px)`; |
| }); |
| }, { passive: true }); |
| } |
| }); |