| |
| (function() { |
| 'use strict'; |
|
|
| |
| const mouseGlow = document.getElementById('mouseGlow'); |
| if (mouseGlow) { |
| document.addEventListener('mousemove', (e) => { |
| if (mouseGlow) { |
| mouseGlow.style.left = e.clientX + 'px'; |
| mouseGlow.style.top = e.clientY + 'px'; |
| } |
| }); |
| } |
|
|
| |
| const scrambleEl = document.getElementById('scrambleText'); |
| if (scrambleEl && typeof scrambleEl.innerText === 'string') { |
| class TextScramble { |
| constructor(el) { |
| if (!el) throw new Error('Element required'); |
| this.el = el; |
| this.chars = '!<>-_\\/[]{}—=+*^?#________'; |
| this.update = this.update.bind(this); |
| this.frame = 0; |
| this.queue = []; |
| this.frameRequest = null; |
| this.resolve = null; |
| } |
| |
| setText(newText) { |
| if (!this.el || typeof newText !== 'string') return Promise.resolve(); |
| |
| const oldText = this.el.innerText || ''; |
| const length = Math.max(oldText.length, newText.length); |
| |
| |
| this.queue = []; |
| |
| for (let i = 0; i < length; i++) { |
| const from = oldText[i] || ''; |
| const to = newText[i] || ''; |
| const start = Math.floor(Math.random() * 40); |
| const end = start + Math.floor(Math.random() * 40); |
| this.queue.push({ from, to, start, end, char: '' }); |
| } |
| |
| if (this.frameRequest) { |
| cancelAnimationFrame(this.frameRequest); |
| } |
| |
| this.frame = 0; |
| |
| return new Promise((resolve) => { |
| this.resolve = resolve; |
| this.update(); |
| }); |
| } |
| |
| update() { |
| if (!this.el || !this.queue || !Array.isArray(this.queue)) return; |
| |
| let output = ''; |
| let complete = 0; |
| |
| for (let i = 0; i < this.queue.length; i++) { |
| const item = this.queue[i]; |
| if (!item) continue; |
| |
| const from = item.from || ''; |
| const to = item.to || ''; |
| const start = item.start || 0; |
| const end = item.end || 0; |
| let char = item.char || ''; |
| |
| if (this.frame >= end) { |
| complete++; |
| output += to; |
| } else if (this.frame >= start) { |
| if (!char || Math.random() < 0.28) { |
| char = this.randomChar() || ''; |
| this.queue[i].char = char; |
| } |
| output += char; |
| } else { |
| output += from; |
| } |
| } |
| |
| |
| if (typeof output === 'string') { |
| this.el.innerText = output; |
| } |
| |
| if (complete === this.queue.length) { |
| if (this.resolve) this.resolve(); |
| } else { |
| this.frameRequest = requestAnimationFrame(this.update); |
| this.frame++; |
| } |
| } |
| |
| randomChar() { |
| if (!this.chars || this.chars.length === 0) return ''; |
| return this.chars[Math.floor(Math.random() * this.chars.length)]; |
| } |
| } |
|
|
| |
| const phrases = ['FUTURE', 'INTELLIGENCE', 'POSSIBILITIES', 'EVOLUTION', 'TOMORROW']; |
| let counter = 0; |
| |
| try { |
| const fx = new TextScramble(scrambleEl); |
| |
| const next = () => { |
| if (!fx.el) return; |
| const nextPhrase = phrases[counter]; |
| if (typeof nextPhrase === 'string') { |
| fx.setText(nextPhrase).then(() => { |
| setTimeout(next, 3000); |
| }); |
| } |
| counter = (counter + 1) % phrases.length; |
| }; |
| |
| setTimeout(next, 2000); |
| } catch (e) { |
| console.error('Scramble effect error:', e); |
| } |
| } |
|
|
| |
| const mobileMenuBtn = document.getElementById('mobileMenuBtn'); |
| const mobileMenu = document.getElementById('mobileMenu'); |
|
|
| if (mobileMenuBtn && mobileMenu) { |
| mobileMenuBtn.addEventListener('click', () => { |
| mobileMenu.classList.toggle('hidden'); |
| }); |
| |
| |
| mobileMenu.querySelectorAll('a').forEach(link => { |
| link.addEventListener('click', () => { |
| mobileMenu.classList.add('hidden'); |
| }); |
| }); |
| } |
|
|
| |
| const newsletterForm = document.getElementById('newsletterForm'); |
| const submitBtn = document.getElementById('submitBtn'); |
|
|
| if (newsletterForm && submitBtn) { |
| newsletterForm.addEventListener('submit', (e) => { |
| e.preventDefault(); |
| |
| const originalContent = submitBtn.innerHTML; |
| submitBtn.innerHTML = '<span class="animate-spin inline-block w-4 h-4 border-2 border-white border-t-transparent rounded-full mr-2"></span>Subscribing...'; |
| submitBtn.disabled = true; |
| |
| setTimeout(() => { |
| submitBtn.innerHTML = '<i data-lucide="check" class="w-4 h-4 mr-2"></i>Subscribed!'; |
| submitBtn.classList.remove('btn-primary'); |
| submitBtn.classList.add('bg-green-500'); |
| |
| if (typeof lucide !== 'undefined') { |
| lucide.createIcons(); |
| } |
| |
| setTimeout(() => { |
| submitBtn.innerHTML = originalContent; |
| submitBtn.classList.add('btn-primary'); |
| submitBtn.classList.remove('bg-green-500'); |
| submitBtn.disabled = false; |
| newsletterForm.reset(); |
| if (typeof lucide !== 'undefined') { |
| lucide.createIcons(); |
| } |
| }, 3000); |
| }, 1500); |
| }); |
| } |
|
|
| |
| const counters = document.querySelectorAll('.counter'); |
| if (counters.length > 0) { |
| const animateCounter = (counter) => { |
| const target = parseInt(counter.getAttribute('data-target')); |
| if (isNaN(target)) return; |
| |
| const duration = 2000; |
| const increment = target / (duration / 16); |
| let current = 0; |
| |
| const updateCounter = () => { |
| current += increment; |
| if (current < target) { |
| counter.innerText = Math.floor(current).toLocaleString(); |
| requestAnimationFrame(updateCounter); |
| } else { |
| counter.innerText = target.toLocaleString() + (target === 98 ? '%' : '+'); |
| } |
| }; |
| |
| updateCounter(); |
| }; |
|
|
| const observer = new IntersectionObserver((entries) => { |
| entries.forEach(entry => { |
| if (entry.isIntersecting && entry.target.classList.contains('counter')) { |
| animateCounter(entry.target); |
| observer.unobserve(entry.target); |
| } |
| }); |
| }, { threshold: 0.5 }); |
|
|
| counters.forEach(counter => observer.observe(counter)); |
| } |
|
|
| |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { |
| anchor.addEventListener('click', function (e) { |
| const href = this.getAttribute('href'); |
| if (!href || href === '#') return; |
| |
| const target = document.querySelector(href); |
| if (target) { |
| e.preventDefault(); |
| target.scrollIntoView({ |
| behavior: 'smooth', |
| block: 'start' |
| }); |
| |
| if (mobileMenu && !mobileMenu.classList.contains('hidden')) { |
| mobileMenu.classList.add('hidden'); |
| } |
| } |
| }); |
| }); |
|
|
| |
| const revealElements = document.querySelectorAll('.resource-card'); |
| if (revealElements.length > 0) { |
| const revealObserver = new IntersectionObserver((entries) => { |
| entries.forEach((entry, index) => { |
| if (entry.isIntersecting) { |
| setTimeout(() => { |
| entry.target.style.opacity = '1'; |
| entry.target.style.transform = 'translateY(0)'; |
| }, index * 100); |
| revealObserver.unobserve(entry.target); |
| } |
| }); |
| }, { threshold: 0.1 }); |
|
|
| revealElements.forEach((el) => { |
| el.style.opacity = '0'; |
| el.style.transform = 'translateY(20px)'; |
| el.style.transition = 'all 0.6s ease-out'; |
| revealObserver.observe(el); |
| }); |
| } |
|
|
| |
| const parallaxElements = document.querySelectorAll('.animate-float'); |
| if (parallaxElements.length > 0) { |
| window.addEventListener('scroll', () => { |
| const scrolled = window.pageYOffset; |
| |
| parallaxElements.forEach((el, index) => { |
| const speed = 0.5 + (index * 0.1); |
| el.style.transform = `translateY(${scrolled * speed}px)`; |
| }); |
| }); |
| } |
|
|
| |
| document.querySelectorAll('.glass-card').forEach(card => { |
| card.addEventListener('mousemove', (e) => { |
| const rect = card.getBoundingClientRect(); |
| const x = e.clientX - rect.left; |
| const y = e.clientY - rect.top; |
| |
| card.style.background = `radial-gradient(circle at ${x}px ${y}px, rgba(139, 92, 246, 0.1), rgba(19, 19, 31, 0.6))`; |
| }); |
| |
| card.addEventListener('mouseleave', () => { |
| card.style.background = 'rgba(19, 19, 31, 0.6)'; |
| }); |
| }); |
| })(); |