// Shared JavaScript across all pages console.log('LightStream Dashboard loaded'); // Mobile detection helper function isMobile() { return window.innerWidth <= 768; } // Toggle mobile menu function toggleMobileMenu() { const menu = document.getElementById('mobile-menu'); menu.classList.toggle('hidden'); } // Close mobile menu when clicking outside document.addEventListener('click', (e) => { const mobileMenu = document.getElementById('mobile-menu'); const menuButton = document.getElementById('menu-button'); if (mobileMenu && !mobileMenu.contains(e.target) && !menuButton.contains(e.target)) { mobileMenu.classList.add('hidden'); } }); // Add scroll animations function handleScrollAnimations() { const elements = document.querySelectorAll('.fade-in, .slide-up, .bounce-in'); elements.forEach(element => { const elementTop = element.getBoundingClientRect().top; const elementVisible = 150; if (elementTop < window.innerHeight - elementVisible) { element.style.opacity = '1'; element.style.transform = 'translateY(0)'; } }); } // Initialize animations on load and scroll window.addEventListener('load', handleScrollAnimations); window.addEventListener('scroll', handleScrollAnimations); // Add typing animation effect function typeWriter(element, text, speed = 50) { let i = 0; element.innerHTML = ''; function type() { if (i < text.length) { element.innerHTML += text.charAt(i); i++; setTimeout(type, speed); } } type(); } // Add ripple effect to buttons function addRippleEffect() { const buttons = document.querySelectorAll('.login-btn, .logout-btn'); buttons.forEach(button => { button.addEventListener('click', function(e) { const ripple = document.createElement('span'); const rect = button.getBoundingClientRect(); const size = Math.max(rect.width, rect.height); const x = e.clientX - rect.left - size / 2; const y = e.clientY - rect.top - size / 2; ripple.style.width = ripple.style.height = size + 'px'; ripple.style.left = x + 'px'; ripple.style.top = y + 'px'; ripple.style.position = 'absolute'; ripple.style.borderRadius = '50%'; ripple.style.background = 'rgba(255, 255, 255, 0.6); ripple.style.transform = 'scale(0)'; ripple.style.transition = 'transform 0.6s ease, opacity 0.6s ease'; ripple.style.opacity = '1'; ripple.style.transform = 'scale(4)'; ripple.style.opacity = '0'; button.style.position = 'relative'; button.style.overflow = 'hidden'; button.appendChild(ripple); setTimeout(() => { ripple.remove(); }, 600); }); }); } // Initialize effects when DOM is loaded document.addEventListener('DOMContentLoaded', function() { addRippleEffect(); // Add staggered animation delays to grid items const gridItems = document.querySelectorAll('.grid > div'); gridItems.forEach((item, index) => { item.style.animationDelay = (index * 0.1) + 's'; }); });