1/** 2 * INTRO ANIMATION 3 * Sequential multi-phase sequence (same as preloader): 4 * 1. "Hello, I'm Prem" word reveal, stay 2s, reverse out 5 * 2. "Welcome to" word reveal, stay 2s, reverse out 6 * 3. Hero headline falls from top with physics acceleration 7 * 4. Logo moves to final position 8 */ 9 10(function() { 11 'use strict'; 12 13 console.log('[intro] Script loaded'); 14 15 const CONFIG = { 16 // Word reveal timing 17 wordRevealDuration: 0.5, 18 wordStayDuration: 2.0, 19 20 // Falling phase 21 wordFallDuration: 1.2, 22 23 // Final positioning 24 logoScaleDuration: 0.6, 25 logoMoveDuration: 0.6, 26 }; 27 28 class IntroAnimation { 29 constructor() { 30 console.log('[intro] Initializing...'); 31 this.intro = document.getElementById('intro'); 32 this.greeting = document.querySelector('.intro-greeting'); 33 this.welcome = document.querySelector('.intro-welcome'); 34 this.headline = document.querySelector('.intro-headline'); 35 36 if (!this.intro || !this.headline) { 37 console.error('[intro] Missing elements'); 38 return; 39 } 40 41 // Hide welcome and headline initially 42 if (this.welcome) this.welcome.style.display = 'none'; 43 if (this.headline) this.headline.style.display = 'none'; 44 45 this.isLoaded = false; 46 this.mainTimeline = gsap.timeline(); 47 48 this.init(); 49 console.log('[intro] Animation starting'); 50 } 51 52 init() { 53 this.animateSequence(); 54 } 55 56 animateSequence() { 57 const tl = this.mainTimeline; 58 59 // âââââââââââââââââââââââââââââââââââââââââââââââââââââ 60 // PHASE 1: "Hello, I'm Prem" word reveal sequence 61 // âââââââââââââââââââââââââââââââââââââââââââââââââââââ 62 if (this.greeting) { 63 // Show greeting 64 tl.add(() => { 65 console.log('[intro] Phase 1: Showing greeting'); 66 this.greeting.style.display = 'inline-flex'; 67 }, 0); 68 69 const greetingSpans = this.greeting.querySelectorAll('span'); 70 71 // Reveal words (staggered) 72 greetingSpans.forEach((span, i) => { 73 tl.fromTo( 74 span, 75 { opacity: 0 }, 76 { 77 opacity: 1, 78 duration: CONFIG.wordRevealDuration, 79 ease: 'power2.out', 80 }, 81 i * 0.08 82 ); 83 }); 84 85 // Stay visible for 2 seconds 86 tl.to({}, { duration: CONFIG.wordStayDuration }); 87 88 // Reverse animation (fade out) 89 greetingSpans.forEach((span, i) => { 90 tl.to( 91 span, 92 { 93 opacity: 0, 94 duration: CONFIG.wordRevealDuration, 95 ease: 'power2.in', 96 }, 97 i * 0.08 98 ); 99 }); 100 101 // Hide greeting 102 tl.add(() => { 103 this.greeting.style.display = 'none'; 104 }); 105 } 106 107 // Transition gap 108 tl.to({}, { duration: 0.2 }); 109 110 // âââââââââââââââââââââââââââââââââââââââââââââââââââââ 111 // PHASE 2: "Welcome to" word reveal sequence 112 // âââââââââââââââââââââââââââââââââââââââââââââââââââââ 113 if (this.welcome) { 114 // Show welcome 115 tl.add(() => { 116 console.log('[intro] Phase 2: Showing welcome'); 117 this.welcome.style.display = 'inline-flex'; 118 }); 119 120 const welcomeSpans = this.welcome.querySelectorAll('span'); 121 122 // Reveal words (staggered) 123 welcomeSpans.forEach((span, i) => { 124 tl.fromTo( 125 span, 126 { opacity: 0 }, 127 { 128 opacity: 1, 129 duration: CONFIG.wordRevealDuration, 130 ease: 'power2.out', 131 }, 132 i * 0.08 133 ); 134 }); 135 136 // Stay visible for 2 seconds 137 tl.to({}, { duration: CONFIG.wordStayDuration }); 138 139 // Reverse animation (fade out) 140 welcomeSpans.forEach((span, i) => { 141 tl.to( 142 span, 143 { 144 opacity: 0, 145 duration: CONFIG.wordRevealDuration, 146 ease: 'power2.in', 147 }, 148 i * 0.08 149 ); 150 }); 151 152 // Hide welcome 153 tl.add(() => { 154 this.welcome.style.display = 'none'; 155 }); 156 } 157 158 // Transition gap 159 tl.to({}, { duration: 0.2 }); 160 161 // âââââââââââââââââââââââââââââââââââââââââââââââââââââ 162 // PHASE 3: Headline falls from top 163 // âââââââââââââââââââââââââââââââââââââââââââââââââââââ 164 if (this.headline) { 165 // Show headline 166 tl.add(() => { 167 console.log('[intro] Phase 3: Showing headline and falling'); 168 this.headline.style.display = 'block'; 169 }); 170 171 // Headline falls from off-screen top 172 tl.fromTo( 173 this.headline, 174 { 175 opacity: 0, 176 y: -window.innerHeight, 177 }, 178 { 179 y: 0, 180 opacity: 1, 181 duration: CONFIG.wordFallDuration, 182 ease: 'power1.in', 183 } 184 // No position â add to end of timeline 185 ); 186 } 187 188 // Mark as complete 189 tl.add(() => { 190 this.intro.classList.add('loaded'); 191 console.log('[intro] â Animation sequence complete'); 192 }); 193 } 194 } 195 196 // Initialize intro animation 197 console.log('[intro] Ready to initialize, document.readyState:', document.readyState); 198 if (document.readyState === 'loading') { 199 document.addEventListener('DOMContentLoaded', () => { 200 console.log('[intro] DOMContentLoaded, creating instance'); 201 new IntroAnimation(); 202 }); 203 } else { 204 console.log('[intro] Document already loaded, creating instance immediately'); 205 new IntroAnimation(); 206 } 207})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.