Spaces:
Running
Running
| // PRELOADER | |
| window.addEventListener('load', () => { | |
| const fill = document.getElementById('preloader-fill'); | |
| const preloader = document.getElementById('preloader'); | |
| fill.style.width = '100%'; | |
| setTimeout(() => { | |
| preloader.classList.add('hidden'); | |
| }, 1800); | |
| }); | |
| // CUSTOM CURSOR | |
| const cursor = document.getElementById('cursor'); | |
| const follower = document.getElementById('cursor-follower'); | |
| let mouseX = 0, mouseY = 0, follX = 0, follY = 0; | |
| document.addEventListener('mousemove', (e) => { | |
| mouseX = e.clientX; | |
| mouseY = e.clientY; | |
| cursor.style.left = mouseX + 'px'; | |
| cursor.style.top = mouseY + 'px'; | |
| }); | |
| function animateFollower() { | |
| follX += (mouseX - follX) * 0.12; | |
| follY += (mouseY - follY) * 0.12; | |
| follower.style.left = follX + 'px'; | |
| follower.style.top = follY + 'px'; | |
| requestAnimationFrame(animateFollower); | |
| } | |
| animateFollower(); | |
| // Scale cursor on interactive elements | |
| document.querySelectorAll('a, button, .work-card, .service-card').forEach(el => { | |
| el.addEventListener('mouseenter', () => { | |
| cursor.style.transform = 'translate(-50%, -50%) scale(2)'; | |
| follower.style.width = '60px'; | |
| follower.style.height = '60px'; | |
| follower.style.borderColor = 'rgba(201,243,29,0.6)'; | |
| }); | |
| el.addEventListener('mouseleave', () => { | |
| cursor.style.transform = 'translate(-50%, -50%) scale(1)'; | |
| follower.style.width = '36px'; | |
| follower.style.height = '36px'; | |
| follower.style.borderColor = 'rgba(201,243,29,0.5)'; | |
| }); | |
| }); | |
| // NAV SCROLL | |
| const nav = document.getElementById('nav'); | |
| window.addEventListener('scroll', () => { | |
| nav.classList.toggle('scrolled', window.scrollY > 50); | |
| }); | |
| // MOBILE MENU | |
| const toggle = document.getElementById('nav-toggle'); | |
| const mobileMenu = document.getElementById('mobile-menu'); | |
| toggle.addEventListener('click', () => { | |
| mobileMenu.classList.toggle('open'); | |
| document.body.style.overflow = mobileMenu.classList.contains('open') ? 'hidden' : ''; | |
| }); | |
| document.querySelectorAll('.mobile-link').forEach(link => { | |
| link.addEventListener('click', () => { | |
| mobileMenu.classList.remove('open'); | |
| document.body.style.overflow = ''; | |
| }); | |
| }); | |
| // SCROLL REVEAL | |
| const revealElements = document.querySelectorAll('.work-card, .service-card, .testi-card, .about-text, .about-img-wrap, .contact-left, .contact-right'); | |
| revealElements.forEach(el => el.classList.add('reveal')); | |
| const observer = new IntersectionObserver((entries) => { | |
| entries.forEach((entry, i) => { | |
| if (entry.isIntersecting) { | |
| setTimeout(() => entry.target.classList.add('visible'), 100); | |
| } | |
| }); | |
| }, { threshold: 0.1 }); | |
| revealElements.forEach(el => observer.observe(el)); | |
| // CONTACT FORM | |
| document.getElementById('contact-form').addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| const btn = e.target.querySelector('button'); | |
| btn.textContent = 'Sending...'; | |
| btn.style.opacity = '0.7'; | |
| setTimeout(() => { | |
| btn.textContent = 'Message Sent! ✓'; | |
| btn.style.opacity = '1'; | |
| btn.style.background = '#22c55e'; | |
| e.target.reset(); | |
| setTimeout(() => { | |
| btn.textContent = 'Send Message →'; | |
| btn.style.background = ''; | |
| }, 3000); | |
| }, 1500); | |
| }); | |
| // PARALLAX ORBS | |
| window.addEventListener('mousemove', (e) => { | |
| const x = (e.clientX / window.innerWidth - 0.5) * 20; | |
| const y = (e.clientY / window.innerHeight - 0.5) * 20; | |
| document.querySelector('.orb-1').style.transform = `translate(${x}px, ${y}px)`; | |
| document.querySelector('.orb-2').style.transform = `translate(${-x * 0.7}px, ${-y * 0.7}px)`; | |
| document.querySelector('.orb-3').style.transform = `translate(${x * 0.5}px, ${y * 0.5}px)`; | |
| }); | |
| // STAGGER work cards | |
| document.querySelectorAll('.work-card').forEach((card, i) => { | |
| card.style.transitionDelay = (i * 0.1) + 's'; | |
| }); | |
| document.querySelectorAll('.service-card').forEach((card, i) => { | |
| card.style.transitionDelay = (i * 0.08) + 's'; | |
| }); | |