PageSourceSearch

https://prems.me/assets/js/intro.js?v=sXJ9fxPJHMrh8yt-

js prems.me collected 2026-10-04 08:10:12 UTC 6,254 bytes, 207 lines download raw bytes

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.