Your important emails hide between newsletters.
-Your tasks live in three different apps.
-Meeting notes sit in a doc you'll never open again.
-You don't need another tool.
You need a secretary.
The product
-© 2026 adiuvAI. All rights reserved. @@ -1080,22 +1330,64 @@ }); }); - // ─── Problem: scroll-driven line reveals ─── - const lines = gsap.utils.toArray('.problem-line, .problem-conclusion'); - lines.forEach((el) => { - gsap.set(el, { opacity: 0, y: 28 }); - gsap.to(el, { - opacity: 1, - y: 0, - ease: 'power2.out', + // ─── Walkthrough: sticky scroll with progressive app reveal ─── + const wtSection = document.getElementById('walkthrough'); + const wtSteps = gsap.utils.toArray('.wt-step'); + const wtSidebar = document.getElementById('wt-sidebar'); + const wtGreeting = document.getElementById('wt-greeting'); + const wtBrief = document.getElementById('wt-brief'); + const wtChat = document.getElementById('wt-chat'); + const wtSuggestions = document.getElementById('wt-suggestions'); + const wtPillars = document.getElementById('wt-pillars'); + + if (wtSection) { + // Set initial states + gsap.set(wtSteps, { opacity: 0, y: 40 }); + gsap.set(wtSteps[0], { opacity: 1, y: 0 }); + gsap.set([wtSidebar], { opacity: 0, x: -30 }); + gsap.set([wtGreeting], { opacity: 0, y: -20 }); + gsap.set([wtBrief], { opacity: 0, y: 20 }); + gsap.set([wtChat], { opacity: 0, y: 30 }); + gsap.set([wtSuggestions], { opacity: 0, y: 30 }); + gsap.set([wtPillars], { opacity: 0, y: 20 }); + + const wtTl = gsap.timeline({ scrollTrigger: { - trigger: el, - start: 'top 82%', - end: 'top 58%', - scrub: 0.5, + trigger: wtSection, + start: 'top top', + end: () => '+=' + (window.innerHeight * 3), + scrub: 0.6, + pin: true, + anticipatePin: 1, + invalidateOnRefresh: true, }, }); - }); + + // Use normalized 0-1 positions so timing scales with any scroll distance + wtTl + // Step 0 visible at start → sidebar flies in + .to(wtSidebar, { opacity: 1, x: 0, duration: 0.15, ease: 'power2.out' }, 0) + .to(wtSteps[0], { opacity: 0, y: -30, duration: 0.08 }, 0.13) + // Step 1: greeting + .to(wtSteps[1], { opacity: 1, y: 0, duration: 0.1, ease: 'power2.out' }, 0.18) + .to(wtGreeting, { opacity: 1, y: 0, duration: 0.1, ease: 'power2.out' }, 0.18) + // Hold step 1 + .to({}, { duration: 0.08 }, 0.28) + // Step 2: brief + .to(wtSteps[1], { opacity: 0, y: -30, duration: 0.08 }, 0.36) + .to(wtSteps[2], { opacity: 1, y: 0, duration: 0.1, ease: 'power2.out' }, 0.42) + .to(wtBrief, { opacity: 1, y: 0, duration: 0.1, ease: 'power2.out' }, 0.42) + // Hold step 2 + .to({}, { duration: 0.08 }, 0.52) + // Step 3: chat + suggestions + pillars + .to(wtSteps[2], { opacity: 0, y: -30, duration: 0.08 }, 0.60) + .to(wtSteps[3], { opacity: 1, y: 0, duration: 0.1, ease: 'power2.out' }, 0.66) + .to(wtChat, { opacity: 1, y: 0, duration: 0.08, ease: 'power2.out' }, 0.66) + .to(wtSuggestions, { opacity: 1, y: 0, duration: 0.08, ease: 'power2.out' }, 0.72) + .to(wtPillars, { opacity: 1, y: 0, duration: 0.08, ease: 'power2.out' }, 0.78) + // Hold step 3 visible + .to({}, { duration: 0.14 }, 0.86); + } // ─── Generic scroll reveals for gs-reveal ─── gsap.utils.toArray('.gs-reveal').forEach((el, i) => { @@ -1125,6 +1417,32 @@ scrub: true, }, }); + + + + // ─── 3D tilt on feature cards ─── + document.querySelectorAll('.feature-card').forEach((card) => { + card.addEventListener('mousemove', (e) => { + const r = card.getBoundingClientRect(); + const x = (e.clientX - r.left) / r.width - 0.5; + const y = (e.clientY - r.top) / r.height - 0.5; + gsap.to(card, { + rotateY: x * 10, + rotateX: y * -10, + transformPerspective: 600, + duration: 0.4, + ease: 'power2.out', + }); + }); + card.addEventListener('mouseleave', () => { + gsap.to(card, { + rotateY: 0, + rotateX: 0, + duration: 0.6, + ease: 'elastic.out(1, 0.5)', + }); + }); + }); }); // ─── Waitlist Form Handler ───