// Custom Cursor const cursor = document.querySelector('.cursor'); const cursorFollower = document.querySelector('.cursor-follower'); if (cursor && cursorFollower) { let mouseX = 0; let mouseY = 0; let followerX = 0; let followerY = 0; document.addEventListener('mousemove', (e) => { mouseX = e.clientX; mouseY = e.clientY; cursor.style.left = mouseX + 'px'; cursor.style.top = mouseY + 'px'; }); function animateFollower() { followerX += (mouseX - followerX) * 0.15; followerY += (mouseY - followerY) * 0.15; cursorFollower.style.left = followerX + 'px'; cursorFollower.style.top = followerY + 'px'; requestAnimationFrame(animateFollower); } animateFollower(); const hoverElements = document.querySelectorAll('a, button, .work-card'); hoverElements.forEach(el => { el.addEventListener('mouseenter', () => { cursor.classList.add('hover'); cursorFollower.classList.add('hover'); }); el.addEventListener('mouseleave', () => { cursor.classList.remove('hover'); cursorFollower.classList.remove('hover'); }); }); } // Navigation const nav = document.querySelector('.nav'); const menuToggle = document.querySelector('.menu-toggle'); const mobileMenu = document.querySelector('.mobile-menu'); const mobileLinks = document.querySelectorAll('.mobile-link'); window.addEventListener('scroll', () => { if (window.scrollY > 50) { nav.classList.add('scrolled'); } else { nav.classList.remove('scrolled'); } }); function toggleMobileMenu() { const isOpen = mobileMenu.classList.contains('active'); menuToggle.classList.toggle('active'); mobileMenu.classList.toggle('active'); // Update ARIA attributes menuToggle.setAttribute('aria-expanded', !isOpen); mobileMenu.setAttribute('aria-hidden', isOpen); document.body.style.overflow = !isOpen ? 'hidden' : ''; } function closeMobileMenu() { menuToggle.classList.remove('active'); mobileMenu.classList.remove('active'); menuToggle.setAttribute('aria-expanded', 'false'); mobileMenu.setAttribute('aria-hidden', 'true'); document.body.style.overflow = ''; } menuToggle.addEventListener('click', toggleMobileMenu); mobileLinks.forEach(link => { link.addEventListener('click', closeMobileMenu); }); // Reveal on Scroll const reveals = document.querySelectorAll('.reveal'); const revealObserver = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add('visible'); revealObserver.unobserve(entry.target); } }); }, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }); reveals.forEach(reveal => { revealObserver.observe(reveal); }); // Stats Counter const stats = document.querySelectorAll('.stat-number'); let statsAnimated = false; const statsObserver = new IntersectionObserver((entries) => { if (entries[0].isIntersecting && !statsAnimated) { statsAnimated = true; stats.forEach(stat => { const target = parseInt(stat.dataset.count); let current = 0; const duration = 2000; const increment = target / (duration / 16); const counter = setInterval(() => { current += increment; if (current >= target) { stat.textContent = target; clearInterval(counter); } else { stat.textContent = Math.floor(current); } }, 16); }); } }, { threshold: 0.5 }); const statsSection = document.querySelector('.stats-section'); if (statsSection) { statsObserver.observe(statsSection); } // Form Handling with actual submission const contactForm = document.getElementById('contactForm'); if (contactForm) { const submitBtn = contactForm.querySelector('button[type="submit"]'); const originalBtnHTML = submitBtn.innerHTML; // Client-side validation function validateForm() { let isValid = true; const requiredFields = contactForm.querySelectorAll('[required]'); requiredFields.forEach(field => { const errorSpan = field.parentElement.querySelector('.form-error'); field.classList.remove('error'); if (errorSpan) errorSpan.textContent = ''; if (!field.value.trim()) { isValid = false; field.classList.add('error'); if (errorSpan) errorSpan.textContent = 'שדה חובה'; } else if (field.type === 'email' && !isValidEmail(field.value)) { isValid = false; field.classList.add('error'); if (errorSpan) errorSpan.textContent = 'כתובת אימייל לא תקינה'; } }); return isValid; } function isValidEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } contactForm.addEventListener('submit', (e) => { if (!validateForm()) { e.preventDefault(); return; } // Show loading state but let the form submit naturally submitBtn.innerHTML = 'שולח...'; submitBtn.disabled = true; }); // Real-time validation on blur contactForm.querySelectorAll('input, textarea').forEach(field => { field.addEventListener('blur', () => { if (field.hasAttribute('required')) { const errorSpan = field.parentElement.querySelector('.form-error'); field.classList.remove('error'); if (errorSpan) errorSpan.textContent = ''; if (!field.value.trim()) { field.classList.add('error'); if (errorSpan) errorSpan.textContent = 'שדה חובה'; } else if (field.type === 'email' && !isValidEmail(field.value)) { field.classList.add('error'); if (errorSpan) errorSpan.textContent = 'כתובת אימייל לא תקינה'; } } }); }); } // Smooth Scroll for Navigation Links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { const href = this.getAttribute('href'); if (href === '#') return; e.preventDefault(); const target = document.querySelector(href); if (target) { const navHeight = nav.offsetHeight; const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - navHeight; window.scrollTo({ top: targetPosition, behavior: 'smooth' }); } }); }); // Parallax effect on hero orbs const orbs = document.querySelectorAll('.hero-bg .gradient-orb'); if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) { window.addEventListener('scroll', () => { const scrollY = window.scrollY; orbs.forEach((orb, index) => { const speed = (index + 1) * 0.1; orb.style.transform = `translateY(${scrollY * speed}px)`; }); }); } // Work card hover effect const workCards = document.querySelectorAll('.work-card'); workCards.forEach(card => { card.addEventListener('mousemove', (e) => { if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) { 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 = ''; }); }); // Marquee pause on hover const marquee = document.querySelector('.marquee'); if (marquee) { marquee.addEventListener('mouseenter', () => { marquee.querySelector('.marquee-track').style.animationPlayState = 'paused'; }); marquee.addEventListener('mouseleave', () => { marquee.querySelector('.marquee-track').style.animationPlayState = 'running'; }); }