b057795735
Make stick-to-bottom intent the single source of truth in MessageList and drive onAtBottomChange from intent, not raw scroll position. A measurement reflow can no longer flip the intent off (RC1), the second scrollPositions writer no longer persists a drifting topmost index while stuck (RC2), and a pin-on-rows layout effect re-pins through the two-phase data swap (RC3). - scrollController: add tested nextStickIntent() state machine - MessageList: input-event-based unstick (wheel/key/touch + scrollbar drag), reveal after 2 stable frames, tabIndex for keyboard nav, remove debug overlay - ConversationPage: reuse resolveInitialAnchor; harden handleRangeChanged Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>