(function () { const counters = document.querySelectorAll('.counter'); function animateCounter(el) { const target = +el.getAttribute('data-target'); const duration = 1800; const steps = 60; const interval = duration / steps; let step = 0; // easeOutExpo for natural deceleration function easeOutExpo(t) { return t === 1 ? 1 : 1 - Math.pow(2, -10 * t); } const timer = setInterval(() => { step++; const progress = easeOutExpo(step / steps); const current = Math.ceil(progress * target); el.setAttribute('data-display', current + '+'); // update text without breaking shimmer gradient el.textContent = current + '+'; if (step >= steps) { clearInterval(timer); el.textContent = target + '+'; } }, interval); } function resetAndAnimate() { counters.forEach(el => { el.textContent = '0+'; }); setTimeout(() => counters.forEach(animateCounter), 300); } // Intersection Observer — animate on scroll into view const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { counters.forEach(animateCounter); observer.disconnect(); } }); }, { threshold: 0.3 }); const section = document.querySelector('.achieve-section'); if (section) observer.observe(section); // Loop every 8s setInterval(resetAndAnimate, 8000); })();