diff --git a/index.html b/index.html index 2be92d1..86f454c 100644 --- a/index.html +++ b/index.html @@ -30,6 +30,7 @@ + diff --git a/script.js b/script.js index 49b9f3a..c50d8f0 100644 --- a/script.js +++ b/script.js @@ -461,12 +461,11 @@ var si = 0, cards.push({ el: card, server: s, idx: idx }); }); - /* Stagger the card entrance animation */ - cards.forEach(function(c, i) { - setTimeout(function() { - c.el.classList.add('visible'); - }, 80 + i * 70); - }); + /* GSAP stagger entrance for cards */ + gsap.fromTo('.server-card', + { opacity: 0, y: 20 }, + { opacity: 1, y: 0, duration: 0.6, stagger: 0.09, ease: 'power2.out' } + ); function pingServer(host) { return new Promise(function(resolve) { @@ -523,7 +522,7 @@ var si = 0, c.el.classList.add('server-best'); } }); - /* Preload city image and carousel-slide */ + /* Preload city image and carousel-slide with GSAP */ var hero = document.querySelector('.hero'); var bestCard = cards.filter(function(c) { return c.server.host === best.host; })[0]; if (hero && bestCard && heroImages[best.host]) { @@ -546,21 +545,23 @@ var si = 0, newEl.className = 'hero-bg-slide new'; newEl.style.backgroundImage = "url('" + heroImages[best.host] + "')"; bg.appendChild(newEl); - /* Fire both animations together */ - requestAnimationFrame(function() { - oldEl.classList.add('out'); - newEl.classList.add('in'); - }); /* Label slides in from right */ var label = document.createElement('div'); label.className = 'hero-city-label'; label.innerHTML = 'Our ' + bestCard.server.city + ' server fits your location'; hero.appendChild(label); - requestAnimationFrame(function() { - label.classList.add('visible'); + + /* GSAP timeline — 3x slower */ + gsap.set(oldEl, { x: '0%' }); + gsap.set(newEl, { x: '100%' }); + gsap.set(label, { x: '150%' }); + + var tl = gsap.timeline({ + onComplete: function() { oldEl.remove(); } }); - /* Clean up old slide after animation done */ - setTimeout(function() { oldEl.remove(); }, 1200); + tl.to(oldEl, { x: '100%', duration: 3, ease: 'power2.out' }, 0) + .to(newEl, { x: '0%', duration: 3, ease: 'power2.out' }, 0) + .to(label, { x: '0%', duration: 2.5, ease: 'power2.out' }, 0.3); }; img.src = heroImages[best.host]; } diff --git a/style.css b/style.css index 5fc868f..61cdef2 100644 --- a/style.css +++ b/style.css @@ -112,8 +112,8 @@ img { max-width: 100%; height: auto; vertical-align: middle; } content: ''; position: absolute; inset: 0; - background: var(--midnight); - opacity: 0.6; + background: linear-gradient(135deg, var(--midnight) 50%, rgba(13,27,46,0.4) 100%); + opacity: 0.5; z-index: 0; } .hero-bg { @@ -128,21 +128,8 @@ img { max-width: 100%; height: auto; vertical-align: middle; } background-size: cover; background-position: center; background-repeat: no-repeat; - opacity: 0.12; - transition: transform 1s cubic-bezier(0.16, 1, 0.3, 1); - will-change: transform; -} -.hero-bg-slide.old { - transform: translateX(0); -} -.hero-bg-slide.old.out { - transform: translateX(100%); -} -.hero-bg-slide.new { - transform: translateX(100%); -} -.hero-bg-slide.new.in { - transform: translateX(0); + opacity: 0.25; + filter: brightness(1.15) saturate(1.1); } .hero .container { position: relative; z-index: 1; flex: 1; display: flex; flex-direction: column; justify-content: center; } .hero-kicker { @@ -417,14 +404,10 @@ img { max-width: 100%; height: auto; vertical-align: middle; } font-size: 0.9rem; z-index: 2; transform: translateX(150%); - transition: transform 0.85s cubic-bezier(0.16, 1, 0.3, 1); white-space: nowrap; backdrop-filter: blur(6px); pointer-events: none; } -.hero-city-label.visible { - transform: translateX(0); -} .hero-city-label strong { color: var(--brass-bright); font-weight: 400;