6f372d36f8
Fast scrolling on iPhone could still kill the tab after the GIF/video and content-visibility work. Two remaining causes only real iOS exhibits: - iOS Safari fires a resize when its toolbar collapses mid-scroll, and the handler rebuilt both masonry grids (teardown + re-append of 101 cards) during the fling. Masonry columns depend only on width, so the handler now bails when the width is unchanged. - Phones laid out all 79 harness cards (~28k px of live DOM) up front — content-visibility skips paint but the initial masonry measurement still forces layout of every card, and a fling still rasterizes the whole run. Single-column layouts now render the deck in batches of 20 that grow via a sentinel IntersectionObserver (1600px margin) as the user approaches; the mobile deck placeholder shrinks to match. Multi-column desktop masonry still renders the full set so shortest-column balancing is exact. jumpToTool materializes remaining batches before scrolling to a target card; search/filter/sort reset to the first batch. Chromium renderer RSS (390x844@3x fling scenario): load 297MB -> 171MB, peak 807MB -> 380MB vs the original page. Full cross-engine suite passes (WebKit + Chromium, mobile + desktop): batch growth while scrolling, reset-on-search, jumpToTool into late batches, footer reachable at true bottom, video rings, flip lifecycle, no overflow, zero page errors.