// Smooth scrolling document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); // Mobile menu toggle const menuToggle = document.querySelector('.menu-toggle'); const navLinks = document.querySelector('.nav-links'); let menuOpen = false; menuToggle?.addEventListener('click', () => { menuOpen = !menuOpen; if (menuOpen) { navLinks.style.display = 'flex'; navLinks.style.position = 'absolute'; navLinks.style.top = '100%'; navLinks.style.left = '0'; navLinks.style.right = '0'; navLinks.style.background = 'rgba(0, 0, 0, 0.98)'; navLinks.style.flexDirection = 'column'; navLinks.style.padding = '1rem'; navLinks.style.borderTop = '2px solid #E8A625'; // Animate menu toggle menuToggle.children[0].style.transform = 'rotate(45deg) translateY(8px)'; menuToggle.children[1].style.opacity = '0'; menuToggle.children[2].style.transform = 'rotate(-45deg) translateY(-8px)'; } else { navLinks.style.display = 'none'; // Reset menu toggle menuToggle.children[0].style.transform = ''; menuToggle.children[1].style.opacity = '1'; menuToggle.children[2].style.transform = ''; } }); // Close mobile menu when clicking outside document.addEventListener('click', (e) => { if (menuOpen && !menuToggle.contains(e.target) && !navLinks.contains(e.target)) { menuOpen = false; navLinks.style.display = 'none'; menuToggle.children[0].style.transform = ''; menuToggle.children[1].style.opacity = '1'; menuToggle.children[2].style.transform = ''; } }); // Scroll animations const observerOptions = { threshold: 0.15, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-in'); observer.unobserve(entry.target); } }); }, observerOptions); // Observe all cards document.querySelectorAll('.service-card, .project-card, .value-card, .partner-card').forEach(el => { el.classList.add('fade-in-element'); observer.observe(el); }); // Navbar scroll effect let lastScroll = 0; const nav = document.querySelector('nav'); window.addEventListener('scroll', () => { const currentScroll = window.pageYOffset; if (currentScroll > 100) { nav.style.background = 'rgba(0, 0, 0, 0.98)'; nav.style.boxShadow = '0 2px 20px rgba(232, 166, 37, 0.3)'; } else { nav.style.background = 'rgba(0, 0, 0, 0.95)'; nav.style.boxShadow = ''; } // Hide/show navbar on scroll if (currentScroll > lastScroll && currentScroll > 500) { nav.style.transform = 'translateY(-100%)'; } else { nav.style.transform = 'translateY(0)'; } lastScroll = currentScroll; }); // Network animation enhancement function createNetworkLine() { const nodes = document.querySelectorAll('.node'); const networkBg = document.querySelector('.network-bg'); if (nodes.length > 1 && networkBg) { for (let i = 0; i < nodes.length - 1; i++) { const line = document.createElement('div'); line.style.position = 'absolute'; line.style.height = '1px'; line.style.background = 'linear-gradient(90deg, transparent, #E8A625, transparent)'; line.style.opacity = '0.2'; line.style.animation = `pulse 4s infinite ${i * 0.5}s`; const node1 = nodes[i]; const node2 = nodes[i + 1]; // Calculate line position and angle const x1 = parseFloat(node1.style.left); const y1 = parseFloat(node1.style.top); const x2 = parseFloat(node2.style.left); const y2 = parseFloat(node2.style.top); const distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); const angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI; line.style.width = distance + '%'; line.style.left = x1 + '%'; line.style.top = y1 + '%'; line.style.transform = `rotate(${angle}deg)`; line.style.transformOrigin = '0 0'; networkBg.appendChild(line); } } } // Initialize network lines createNetworkLine(); // Dynamic typing effect for hero subtitle const subtitle = document.querySelector('.hero-subtitle'); if (subtitle) { const text = subtitle.textContent; subtitle.textContent = ''; let index = 0; function typeWriter() { if (index < text.length) { subtitle.textContent += text.charAt(index); index++; setTimeout(typeWriter, 100); } } setTimeout(typeWriter, 800); } // Add hover effect to project cards with tilt document.querySelectorAll('.project-card, .service-card').forEach(card => { card.addEventListener('mousemove', (e) => { const rect = card.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const centerX = rect.width / 2; const centerY = rect.height / 2; const rotateX = (y - centerY) / 20; const rotateY = (centerX - x) / 20; card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateY(-5px)`; }); card.addEventListener('mouseleave', () => { card.style.transform = ''; }); }); // Easter egg: Konami code const konamiCode = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'b', 'a']; let konamiIndex = 0; document.addEventListener('keydown', (e) => { if (e.key === konamiCode[konamiIndex]) { konamiIndex++; if (konamiIndex === konamiCode.length) { document.body.style.animation = 'pulse 1s'; setTimeout(() => { alert('🎮 Félicitations! Vous avez trouvé le code secret! Bienvenue dans la résistance numérique!'); document.body.style.animation = ''; }, 1000); konamiIndex = 0; } } else { konamiIndex = 0; } }); // Progressive enhancement: Add loading states // Disabled - not needed for external links // document.querySelectorAll('.service-link, .project-card').forEach(link => { // link.addEventListener('click', function(e) { // if (this.href && this.href !== '#') { // this.style.opacity = '0.6'; // this.innerHTML += ' ⌛'; // } // }); // }); // Custom donation handler function handleCustomDonation(type) { const input = document.getElementById(type === 'oneTime' ? 'customAmountOneTime' : 'customAmountMonthly'); const amount = input.value; if (!amount || amount < 1) { alert('Veuillez entrer un montant valide'); return; } // Redirect to custom amount Stripe URL const stripeUrl = type === 'oneTime' ? 'https://don.o-k-i.net/b/6oE2aO94P88X9u8eV4' // Custom one-time donation : 'https://don.o-k-i.net/b/6oE2aO94P88X9u8eV4'; // Uses same link for custom amounts window.location.href = stripeUrl; }