// Changemaker Lite - Minimal Interactions document.addEventListener('DOMContentLoaded', function() { // Terminal copy functionality const terminals = document.querySelectorAll('.terminal-box'); terminals.forEach(terminal => { terminal.addEventListener('click', function() { const code = this.textContent.trim(); navigator.clipboard.writeText(code).then(() => { // Quick visual feedback this.style.background = '#0a0a0a'; setTimeout(() => { this.style.background = '#000'; }, 200); }); }); }); // Smooth scroll for anchors 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' }); } }); }); // Reduced motion support if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { document.documentElement.style.scrollBehavior = 'auto'; const style = document.createElement('style'); style.textContent = '*, *::before, *::after { animation: none !important; transition: none !important; }'; document.head.appendChild(style); } }); // Changemaker Lite - Smooth Grid Interactions document.addEventListener('DOMContentLoaded', function() { // Smooth scroll for anchors 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' }); } }); }); // Add stagger animation to grid cards on scroll const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach((entry, index) => { if (entry.isIntersecting) { setTimeout(() => { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; }, index * 50); observer.unobserve(entry.target); } }); }, observerOptions); // Observe all grid cards document.querySelectorAll('.grid-card').forEach((card, index) => { card.style.opacity = '0'; card.style.transform = 'translateY(20px)'; card.style.transition = 'opacity 0.5s ease, transform 0.5s ease'; observer.observe(card); }); // Neon hover effect for service cards document.querySelectorAll('.service-card').forEach(card => { card.addEventListener('mouseenter', function(e) { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const ripple = document.createElement('div'); ripple.style.position = 'absolute'; ripple.style.left = x + 'px'; ripple.style.top = y + 'px'; ripple.style.width = '0'; ripple.style.height = '0'; ripple.style.borderRadius = '50%'; ripple.style.background = 'rgba(91, 206, 250, 0.3)'; ripple.style.transform = 'translate(-50%, -50%)'; ripple.style.pointerEvents = 'none'; ripple.style.transition = 'width 0.6s, height 0.6s, opacity 0.6s'; this.appendChild(ripple); setTimeout(() => { ripple.style.width = '200px'; ripple.style.height = '200px'; ripple.style.opacity = '0'; }, 10); setTimeout(() => { ripple.remove(); }, 600); }); }); // Animated counter for stats const animateValue = (element, start, end, duration) => { const range = end - start; const increment = range / (duration / 16); let current = start; const timer = setInterval(() => { current += increment; if (current >= end) { current = end; clearInterval(timer); } element.textContent = Math.round(current); }, 16); }; // Animate stat numbers on scroll const statObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const statNumber = entry.target.querySelector('.stat-number'); if (statNumber && !statNumber.animated) { statNumber.animated = true; const value = parseInt(statNumber.textContent); if (!isNaN(value)) { statNumber.textContent = '0'; animateValue(statNumber, 0, value, 1000); } } statObserver.unobserve(entry.target); } }); }, observerOptions); document.querySelectorAll('.stat-item').forEach(stat => { statObserver.observe(stat); }); // Add parallax effect to hero section let ticking = false; function updateParallax() { const scrolled = window.pageYOffset; const hero = document.querySelector('.hero-grid'); if (hero) { hero.style.transform = `translateY(${scrolled * 0.3}px)`; } ticking = false; } function requestTick() { if (!ticking) { window.requestAnimationFrame(updateParallax); ticking = true; } } // Only add parallax on desktop if (window.innerWidth > 768) { window.addEventListener('scroll', requestTick); } // Button ripple effect document.querySelectorAll('.btn').forEach(button => { button.addEventListener('click', function(e) { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const ripple = document.createElement('span'); ripple.style.position = 'absolute'; ripple.style.left = x + 'px'; ripple.style.top = y + 'px'; ripple.className = 'btn-ripple'; this.appendChild(ripple); setTimeout(() => { ripple.remove(); }, 600); }); }); // Reduced motion support if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { document.documentElement.style.scrollBehavior = 'auto'; window.removeEventListener('scroll', requestTick); } }); // Add CSS for button ripple const style = document.createElement('style'); style.textContent = ` .btn-ripple { position: absolute; width: 20px; height: 20px; border-radius: 50%; background: rgba(111, 66, 193, 0.5); /* mkdocs purple */ transform: translate(-50%, -50%) scale(0); animation: ripple-animation 0.6s ease-out; pointer-events: none; } @keyframes ripple-animation { to { transform: translate(-50%, -50%) scale(10); opacity: 0; } } `; document.head.appendChild(style);