"use client"; /** * METRICS scoreboard. * - CountUp numbers animate on view (Motion). * - A second ANIMATED-SVG moment: a bar chart whose bars DRAW/grow + a baseline * that draws itself (GSAP DrawSVG) when the section scrolls in. * Reduced-motion: numbers jump to final, bars render at full height (CSS). */ import { useEffect, useRef } from "react"; import { gsap } from "./gsap"; import CountUp from "./CountUp"; import { metrics } from "../content"; const BARS = [38, 56, 72, 64, 88, 96]; // decorative growth bars (0..100) export default function Scoreboard() { const root = useRef(null); useEffect(() => { const el = root.current; if (!el) return; const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches; if (reduce) return; const ctx = gsap.context(() => { const tl = gsap.timeline({ scrollTrigger: { trigger: ".score__chart", start: "top 80%", once: true }, }); tl.from(".score-bar", { scaleY: 0, transformOrigin: "bottom", duration: 0.9, ease: "expo.out", stagger: 0.08, }).from( ".score__baseline", { drawSVG: "0%", duration: 0.9, ease: "power2.out" }, "-=0.7" ); }, el); return () => ctx.revert(); }, []); return (

The scoreboard — sample data

Numbers we report on

{metrics.map((m) => (
{m.label}
))}
{/* decorative animated bar chart */}
); }