91b3e5c522
Slide: the 40-128ms hitch was a compositor RE-RASTER at transitionend, not JS (longtasks:[], renderMs 2-6ms in the device log). Removed contain:layout paint / isolation:isolate from the .content slide layer and the filter:brightness parallax on .chatcol (both force a full re-raster on teardown); defer the layer demotion two frames past transitionend so it lands off the motion path. Also replaced the fragile length+lastId slide-end skip (it almost never held once a live message grew the cache, so the full innerHTML rebuild kept running at slide-end) with an exact per-message diff. Reopen-at-latest: loadOlder wrote the GROWN thread (100+ msgs) into THREAD_CACHE, so re-opening re-rendered all of it and stranded you mid-history as images shifted the (pre-load) bottom past the 1200px pin guard. Open now renders the latest PAGE only; added _forcePinOpen to glue to the newest through late image loads until the user scrolls. Download hang: <a download> navigated the whole WKWebView away to the raw file (no back, app frozen). Native-only capture-phase interceptor opens downloads in the system browser. Lightbox close/download buttons: solid dark chips so they're visible over bright images. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>