Spaces:
Running
Running
| // Initialize animations and interactions | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Animate elements on scroll | |
| const observerOptions = { | |
| threshold: 0.1, | |
| rootMargin: '0px 0px -50px 0px' | |
| }; | |
| const observer = new IntersectionObserver((entries) => { | |
| entries.forEach(entry => { | |
| if (entry.isIntersecting) { | |
| entry.target.style.opacity = '1'; | |
| entry.target.style.transform = 'translateY(0)'; | |
| } | |
| }); | |
| }, observerOptions); | |
| // Observe elements for animation | |
| document.querySelectorAll('.animate-on-scroll').forEach(el => { | |
| el.style.opacity = '0'; | |
| el.style.transform = 'translateY(30px)'; | |
| el.style.transition = 'opacity 0.6s ease, transform 0.6s ease'; | |
| observer.observe(el); | |
| }); | |
| // Add animation classes to elements | |
| document.querySelectorAll('h1').forEach(el => el.classList.add('animate-fade-in-up')); | |
| document.querySelectorAll('h2').forEach(el => el.classList.add('animate-slide-in-left')); | |
| document.querySelectorAll('.grid > div').forEach((el, index) => { | |
| setTimeout(() => { | |
| el.classList.add('animate-fade-in-up'); | |
| }, index * 200); | |
| }); | |
| // Smooth scrolling for anchor links | |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { | |
| anchor.addEventListener('click', function (e) { | |
| e.preventDefault(); | |
| const target = document.querySelector(this.getAttribute('href')); | |
| if (target) { | |
| target.scrollIntoView({ | |
| behavior: 'smooth', | |
| block: 'start' | |
| }); | |
| } | |
| }); | |
| }); | |
| // Add hover effects to cards | |
| document.querySelectorAll('.hover-lift').forEach(card => { | |
| card.addEventListener('mouseenter', function() { | |
| this.style.transform = 'translateY(-5px)'; | |
| }); | |
| card.addEventListener('mouseleave', function() { | |
| this.style.transform = 'translateY(0)'; | |
| }); | |
| }); | |
| // Parallax effect for background sun | |
| window.addEventListener('scroll', () => { | |
| const scrolled = window.pageYOffset; | |
| const sun = document.querySelector('.bg-gradient-to-br'); | |
| if (sun) { | |
| sun.style.transform = `translateY(${scrolled * 0.5}px)`; | |
| } | |
| }); | |
| // Mobile menu toggle | |
| const mobileMenuButton = document.querySelector('[data-feather="menu"]'); | |
| const mobileMenu = document.querySelector('.mobile-menu'); | |
| if (mobileMenuButton && mobileMenu) { | |
| mobileMenuButton.addEventListener('click', () => { | |
| mobileMenu.classList.toggle('hidden'); | |
| }); | |
| } | |
| // Form validation for sign-up forms | |
| document.querySelectorAll('a[href*="sign-up"]').forEach(link => { | |
| link.addEventListener('click', function(e) { | |
| // Add any validation logic here | |
| console.log('Redirecting to sign up...'); | |
| }); | |
| }); | |
| // Image lazy loading | |
| const images = document.querySelectorAll('img[src]'); | |
| const imageObserver = new IntersectionObserver((entries, observer) => { | |
| entries.forEach(entry => { | |
| if (entry.isIntersecting) { | |
| const img = entry.target; | |
| img.style.opacity = '1'; | |
| observer.unobserve(img); | |
| } | |
| }); | |
| }); | |
| images.forEach(img => { | |
| img.style.opacity = '0'; | |
| img.style.transition = 'opacity 0.3s ease'; | |
| imageObserver.observe(img); | |
| }); | |
| // Add loading state to buttons | |
| document.querySelectorAll('a[class*="bg-"]').forEach(button => { | |
| button.addEventListener('click', function(e) { | |
| const originalText = this.textContent; | |
| this.textContent = 'Loading...'; | |
| this.style.pointerEvents = 'none'; | |
| // Reset after a short delay | |
| setTimeout(() => { | |
| this.textContent = originalText; | |
| this.style.pointerEvents = 'auto'; | |
| }, 1000); | |
| }); | |
| }); | |
| // Performance optimization: Debounce scroll events | |
| function debounce(func, wait) { | |
| let timeout; | |
| return function executedFunction(...args) { | |
| const later = () => { | |
| clearTimeout(timeout); | |
| func(...args); | |
| }; | |
| clearTimeout(timeout); | |
| timeout = setTimeout(later, wait); | |
| }; | |
| } | |
| // Apply debounce to scroll handler | |
| const debouncedScrollHandler = debounce(() => { | |
| const scrolled = window.pageYOffset; | |
| const sun = document.querySelector('.bg-gradient-to-br'); | |
| if (sun) { | |
| sun.style.transform = `translateY(${scrolled * 0.5}px)`; | |
| } | |
| }, 10); | |
| window.addEventListener('scroll', debouncedScrollHandler); | |
| console.log('Grok website loaded successfully!'); | |
| }); | |
| // Utility functions | |
| function showNotification(message, type = 'info') { | |
| const notification = document.createElement('div'); | |
| notification.className = `fixed top-4 right-4 p-4 rounded-lg text-white z-50 ${ | |
| type === 'success' ? 'bg-green-500' : | |
| type === 'error' ? 'bg-red-500' : 'bg-blue-500' | |
| }`; | |
| notification.textContent = message; | |
| document.body.appendChild(notification); | |
| setTimeout(() => { | |
| notification.remove(); | |
| }, 3000); | |
| } | |
| // Export functions for external use | |
| window.GrokUtils = { | |
| showNotification | |
| }; |