Stats panel: a persistent spinner marks whichever target is currently
being scanned/reacted to, and jittered waits show a live-ticking
countdown bar instead of a static "waiting Xs" line. Both the status
line and countdown row are always rendered (blank when idle) so their
appearing/disappearing no longer shifts the table's height.
Backlog: channel_scan_state now tracks oldest_covered_at alongside
newest_id_seen. If days_back is widened after a channel already has a
resume checkpoint, the forward-only diff would never look back far
enough to notice — now the newly-exposed gap gets backfilled first.
Split each channel's backlog scan into a find phase (settles the
found count first) and a react phase, so the progress display no
longer grows both numbers in lockstep. Found messages are logged in
a dedicated, message_id-deduped table and recovered across restarts
independent of the resume checkpoint, so nothing found is silently
abandoned if the script stops mid-react.
Also drops the separately-maintained messages_found counter, which
proved prone to drift under repeated interruptions/rescans, in favor
of computing it live from the dedup table - self-healing regardless
of how many times a channel gets rescanned.
--undo only cleared the reactions log, so a subsequent run kept
diffing forward from each channel's last-seen message instead of
honoring days_back, silently skipping everything already undone.
Undo now also clears channel_scan_state so the next run does a
full fresh backlog scan.
React in 1:1 DMs alongside servers/groups, surface the resolved friend
username at startup and in the stats panel, verify reactions actually
stick after adding them (with jump links for manual spot-checking),
and prune stale targets from stats on each run so only the currently
mutual set is shown.