'use client'; import { useEffect, useRef, useState } from 'react'; import { BookOpen, Clock, Brain, Eye } from 'lucide-react'; function fmt(n) { if (!n) return '0'; if (n >= 1_000_000) return (n / 1_000_000).toFixed(1) + 'M'; if (n >= 1_000) return (n / 1_000).toFixed(1) + 'K'; return Math.round(n).toLocaleString('ru-RU'); } /** Плавный count-up от 0 до value за ~1.2 секунды */ function useCountUp(target, run) { const [val, setVal] = useState(0); useEffect(() => { if (!run || !target) { setVal(target || 0); return; } const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (reduce) { setVal(target); return; } let start = null; const duration = 1200; let raf = 0; const step = (ts) => { if (!start) start = ts; const t = Math.min(1, (ts - start) / duration); // easeOutQuart для приятной кривой const eased = 1 - Math.pow(1 - t, 4); setVal(Math.floor(target * eased)); if (t < 1) raf = requestAnimationFrame(step); else setVal(target); }; raf = requestAnimationFrame(step); return () => cancelAnimationFrame(raf); }, [target, run]); return val; } function StatCard({ icon: Icon, value, label, run }) { const animated = useCountUp(value || 0, run); return (