Firefox settles layout more slowly than Safari. The previous rAF-based
settlePoll approach still triggered visible step-wise scroll jumps in
Firefox because each requestAnimationFrame read of scrollHeight caused
an independent reflow that Firefox composited as a visible step.
Replace the multi-rAF polling loop with a ResizeObserver on the
messages container. The observer is notified passively when layout
changes (KaTeX, Mermaid, Prism, images), then a 50ms debounce timer
fires a single final scrollTop write. No intermediate scrollTop writes
means Firefox never paints intermediate positions.
Changes:
- Replace _settlePoll() loop with ResizeObserver in _settleMessageScrollToBottom()
- Add _settleRO and _settleTimer globals for cleanup
- Update _cancelBottomSettle() to disconnect observer and clear timer
- Add 2s safety timeout for static content edge case
Fixes Firefox-specific scroll jump after streaming responses complete.
Safari behavior unchanged (was already smooth).