// Logic to handle navigation active state based on scroll position document.addEventListener('DOMContentLoaded', () => { const sections = document.querySelectorAll('section[id]'); const navLinks = document.querySelectorAll('.nav-link'); const observerOptions = { root: null, rootMargin: '0px', threshold: 0.3 }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const id = entry.target.getAttribute('id'); navLinks.forEach(link => { link.classList.remove('active'); if (link.getAttribute('href') === `#${id}`) { link.classList.add('active'); } }); } }); }, observerOptions); sections.forEach(section => observer.observe(section)); // Scroll reveal animation const revealElements = document.querySelectorAll('.reveal, .reveal-left, .reveal-right'); const revealObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('active'); } }); }, { threshold: 0.1 }); revealElements.forEach(el => revealObserver.observe(el)); // Initialize components when DOM is ready const initComponents = () => { // Initialize Terminal const terminal = document.querySelector('custom-terminal'); if (terminal && terminal.initTerminal) { setTimeout(() => terminal.initTerminal(), 3000); } // Initialize Projects scroll const projects = document.querySelector('custom-projects'); if (projects && projects.initScrollNavigation) { projects.initScrollNavigation(); } // Initialize Skills filter const skills = document.querySelector('custom-skills'); if (skills && skills.initFilter) { skills.initFilter(); } }; // Dispatch event to notify components that the DOM is ready window.dispatchEvent(new Event('app-ready')); // Initialize components initComponents(); // Parallax effect for hero section window.addEventListener('scroll', () => { const scrolled = window.pageYOffset; const hero = document.querySelector('custom-hero'); if (hero) { const shapes = hero.shadowRoot?.querySelector('.floating-shapes'); if (shapes) { shapes.style.transform = `translateY(${scrolled * 0.3}px)`; } } }); // Magnetic button effect const magneticBtns = document.querySelectorAll('.magnetic-btn'); magneticBtns.forEach(btn => { btn.addEventListener('mousemove', (e) => { const rect = btn.getBoundingClientRect(); const x = e.clientX - rect.left - rect.width / 2; const y = e.clientY - rect.top - rect.height / 2; btn.style.transform = `translate(${x * 0.3}px, ${y * 0.3}px)`; }); btn.addEventListener('mouseleave', () => { btn.style.transform = 'translate(0, 0)'; }); }); // Smooth scroll for anchor links 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 reveal classes to skill cards const skillCards = document.querySelectorAll('.skill-card'); skillCards.forEach((card, index) => { card.classList.add('reveal'); card.style.transitionDelay = `${index * 0.1}s`; }); // Add reveal classes to project containers const projectContainers = document.querySelectorAll('.project-container'); projectContainers.forEach((card, index) => { card.classList.add('reveal'); card.style.transitionDelay = `${index * 0.15}s`; }); }); // Typing effect for hero 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(); }