Nine preview components on the landing page each carried their own copy of the
same effect: measure the container against the viewport, clamp the ratio to
0..1, keep it in state, and attach passive scroll + resize listeners. Two of
them also duplicated the effect that measures how far a list can travel.
useScrollProgress() and useScrollTranslate() now own that, and the components
just read the progress. welcome.tsx loses 265 lines.
Verified in the browser: all nine previews still animate as the page scrolls
(the eight transform/opacity ones and the cashflow chart, which animates bar
heights). Adds unit coverage for the clamped progress, which nothing tested.