// Potbi Landing Page JavaScript document.addEventListener('DOMContentLoaded', function() { // Initialize Feather icons if (typeof feather !== 'undefined') { feather.replace(); } // Demo tabs functionality initDemoTabs(); // Counter animation initCounters(); // Smooth scroll for anchor links initSmoothScroll(); // Intersection Observer for animations initScrollAnimations(); // Navbar scroll effect initNavbarScroll(); }); // Demo Tabs function initDemoTabs() { const tabs = document.querySelectorAll('.demo-tab'); const contents = document.querySelectorAll('.demo-content'); tabs.forEach(tab => { tab.addEventListener('click', () => { const targetId = tab.dataset.tab; // Update tabs tabs.forEach(t => { t.classList.remove('active'); t.classList.add('bg-slate-800/30', 'border-slate-800'); t.classList.remove('bg-slate-800/50', 'border-slate-700'); }); tab.classList.add('active'); tab.classList.remove('bg-slate-800/30', 'border-slate-800'); tab.classList.add('bg-slate-800/50', 'border-slate-700'); // Update contents contents.forEach(content => { content.classList.add('hidden'); content.classList.remove('active'); }); const targetContent = document.getElementById(`demo-${targetId}`); if (targetContent) { targetContent.classList.remove('hidden'); // Small delay to allow display:block to apply before opacity transition setTimeout(() => { targetContent.classList.add('active'); }, 10); } // Re-render icons if (typeof feather !== 'undefined') { feather.replace(); } }); }); } // Counter Animation function initCounters() { const counters = document.querySelectorAll('[data-count]'); const observerOptions = { threshold: 0.5, rootMargin: '0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const counter = entry.target; const target = parseFloat(counter.dataset.count); const isDecimal = target % 1 !== 0; const duration = 2000; const startTime = performance.now(); function updateCounter(currentTime) { const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); // Easing function const easeOutQuart = 1 - Math.pow(1 - progress, 4); const current = target * easeOutQuart; if (isDecimal) { counter.textContent = current.toFixed(1); } else { counter.textContent = Math.floor(current).toLocaleString(); } if (progress < 1) { requestAnimationFrame(updateCounter); } else { if (isDecimal) { counter.textContent = target.toFixed(1); } else { counter.textContent = target.toLocaleString(); } } } requestAnimationFrame(updateCounter); observer.unobserve(counter); } }); }, observerOptions); counters.forEach(counter => observer.observe(counter)); } // Smooth Scroll function initSmoothScroll() { document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function(e) { const href = this.getAttribute('href'); if (href === '#') return; const target = document.querySelector(href); if (target) { e.preventDefault(); const offsetTop = target.offsetTop - 80; // Account for fixed header window.scrollTo({ top: offsetTop, behavior: 'smooth' }); } }); }); } // Scroll Animations function initScrollAnimations() { const animatedElements = document.querySelectorAll('.animate-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.classList.add('animate-in'); observer.unobserve(entry.target); } }); }, observerOptions); animatedElements.forEach(el => observer.observe(el)); } // Navbar Scroll Effect function initNavbarScroll() { const navbar = document.querySelector('potbi-navbar'); if (!navbar) return; let lastScroll = 0; let ticking = false; function updateNavbar() { const currentScroll = window.pageYOffset; if (currentScroll > 100) { navbar.classList.add('scrolled'); } else { navbar.classList.remove('scrolled'); } lastScroll = currentScroll; ticking = false; } window.addEventListener('scroll', () => { if (!ticking) { requestAnimationFrame(updateNavbar); ticking = true; } }, { passive: true }); } // Utility: Debounce function function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Utility: Throttle function function throttle(func, limit) { let inThrottle; return function(...args) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } // Form validation helper function validateEmail(email) { const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return re.test(String(email).toLowerCase()); } // Mobile menu toggle (for components) function toggleMobileMenu() { const menu = document.getElementById('mobile-menu'); if (menu) { menu.classList.toggle('hidden'); menu.classList.toggle('mobile-menu-enter'); } } // Export functions for global access window.Potbi = { toggleMobileMenu, validateEmail, debounce, throttle };