Each number counts once, the first time it's on screen, thanks to an IntersectionObserver that stops watching after it fires. font-variant-numeric: tabular-nums gives every digit the same width, so the number doesn't jitter while it counts.
The HTML ships with the final numbers, and the script only resets them to zero once it's running. So if JavaScript fails or loads late, visitors still see the real values, never a row of zeros.
toLocaleString() adds thousands separators in the visitor's own format (1,284 or 1.284). Prefix, suffix and decimals come from data attributes, so one script handles money, percentages and plain counts.
With reduced motion on, the count still runs, just faster (half a second instead of 1.6).