c06caad8f7
Rework per hermes-sweeper review (keep_open, salvageability=medium): - Capture moves out of the render body into the session-switch layout-effect cleanup, so only committed switches persist state (no uncommitted render can write localStorage). - Live state is fed by both scroll events and a ResizeObserver on the content element, so distance-from-bottom stays fresh under async relayout that changes height without a scroll event (the staleness gap #70478's own review threads flagged). - State is distance-from-bottom (or sticky-bottom), not raw scrollTop: the render-budget backfill prepends older turns and main anchors by distance-from-bottom, so an absolute offset no longer identifies the same reading location after the height change. - Restore integrates with main's hasGroups/settle/anchor lifecycle: the settle loop re-applies the remembered target, defers on a clamped offset (content still arriving), hands back locked only for sticky-bottom, and leaves mid-read sessions escaped at their offset. - anchorBeforePrepend no longer records 0 mid-load, which would clobber a restored offset once the backfill lands; the settle loop owns the target every frame until settled. - Storage is scoped per profile with the session.ts .profile.<encoded> key pattern (no cross-profile bleed, #67709 pattern) and LRU-capped at 120 sessions per profile. - Regression tests: state classification, target math, profile isolation, LRU eviction, corrupt/invalid payload handling. Related to #45562 (partial; no automatic closure) (cherry picked from commit 1d79bef93f63d7b190b471bf652b5109b4288a8e)