// Dark Mode System class DarkModeManager { constructor() { this.isDark = localStorage.getItem('darkMode') === 'true' || (!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches); this.init(); } init() { this.applyTheme(); this.setupToggle(); this.setupSystemThemeListener(); } applyTheme() { if (this.isDark) { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } this.updateToggleUI(); } toggle() { this.isDark = !this.isDark; localStorage.setItem('darkMode', this.isDark); this.applyTheme(); } setupToggle() { const toggles = document.querySelectorAll('.dark-mode-toggle'); toggles.forEach(toggle => { toggle.addEventListener('click', () => this.toggle()); }); } updateToggleUI() { const toggles = document.querySelectorAll('.dark-mode-toggle'); toggles.forEach(toggle => { if (this.isDark) { toggle.classList.add('active'); } else { toggle.classList.remove('active'); } }); } setupSystemThemeListener() { window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { if (!localStorage.getItem('darkMode')) { this.isDark = e.matches; this.applyTheme(); } }); } } // Smooth scroll for internal links function initSmoothScroll() { 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' }); } }); }); } // Intersection Observer for animations function initScrollAnimations() { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-fade-in'); } }); }, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }); // Observe all sections and cards document.querySelectorAll('section, .group').forEach(el => { observer.observe(el); }); } // Add CSS animation class const style = document.createElement('style'); style.textContent = ` @keyframes fade-in-up { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } .animate-fade-in { animation: fade-in-up 0.8s ease-out forwards; } `; document.head.appendChild(style); // Navigation scroll effect function initNavigationEffects() { let lastScroll = 0; const header = document.querySelector('header'); window.addEventListener('scroll', () => { const currentScroll = window.pageYOffset; if (header) { if (currentScroll > 100) { header.classList.add('backdrop-blur-lg', 'bg-white/80', 'dark:bg-slate-900/80'); header.classList.remove('bg-white', 'dark:bg-slate-900'); } else { header.classList.remove('backdrop-blur-lg', 'bg-white/80', 'dark:bg-slate-900/80'); header.classList.add('bg-white', 'dark:bg-slate-900'); } } lastScroll = currentScroll; }); } // Initialize all features document.addEventListener('DOMContentLoaded', () => { new DarkModeManager(); initSmoothScroll(); initScrollAnimations(); initNavigationEffects(); // Add loading state removal document.body.classList.add('loaded'); }); // Export for use in components window.DarkModeManager = DarkModeManager;