/* global React */ // Animated counter row — 480+ / 48+ / <1ms, with thin gold dividers. const useCount = (target, duration = 1400, start = false) => { const [val, setVal] = React.useState(0); React.useEffect(() => { if (!start) return; const t0 = performance.now(); let raf; const tick = (now) => { const p = Math.min(1, (now - t0) / duration); // easeOutCubic const eased = 1 - Math.pow(1 - p, 3); setVal(Math.round(target * eased)); if (p < 1) raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf); }, [target, duration, start]); return val; }; const StatItem = ({ target, prefix = '', suffix = '', label, start }) => { const count = useCount(target, 1400, start); return (
{prefix}{count}{suffix}
{label}
); }; const Stats = () => { const ref = React.useRef(null); const [start, setStart] = React.useState(false); React.useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setStart(true); io.disconnect(); } }, { threshold: 0.3 } ); io.observe(el); return () => io.disconnect(); }, []); const Divider = ({ id }) => (
); return (
); }; window.Stats = Stats;