* ⏱️ feat: Show Elapsed Time Under the Streaming Response
A minimalist elapsed-time indicator (5s, then 1m 5s) occupies the footer
slot the hover actions vacate while a response generates, anchored to a
per-index submission-start timestamp so remounts (new-conversation id
hydration, navigation) never reset it. The once-per-second tick is
component-local state, so streaming rows never re-render on its account.
* 🧭 fix: Keep the Original Elapsed Baseline When Reattaching a Stream
Codex round 1: resume-on-load restamped the anchor at reattach time, so
navigating away from a still-streaming conversation and back restarted
the reading at 0s — the exact reset the atom exists to prevent. Resume
paths now leave the anchor alone: a same-session return keeps its ask
baseline, and a reload (atom empty) falls back to the indicator's mount
time, which is what the stamp produced anyway.
* 🪗 fix: Scope the Elapsed Timer to Its Own Generation, Localized and Spoken
Codex round 2, all four findings:
- The anchor is cleared on every terminal path (final, error, abort
fallback), and resume-on-load only fills an empty one — so a run another
client started never inherits a stale baseline, while a same-session
reattach still keeps its original start.
- The indicator additionally requires the newest sibling position:
latestMessageId follows the selected branch, so a settled older sibling
paged to mid-regeneration satisfied the latest+submitting gate and got a
counting timer under settled content.
- Visible digits now come from the shared run-step duration formatter
(Intl.NumberFormat per locale), replacing the raw-number interpolations.
- The compact reading is aria-hidden with a spoken 'N seconds elapsed'
equivalent beside it, per the house duration-label pattern; still no
aria-live, so the tick never announces.