Adds the reactive throttle layer for #360: when a provider rate-limits or
locks us (IMAP `[THROTTLED]`/"too many connections" NO, HTTP 429, auth
lockout), the app now backs off exponentially and pauses the offending
activity instead of hammering the server (which the perf drilldown proved
makes throttling worse — `docs/perf/issue-125-*`).
- ThrottleClassifier: message-text (IMAP/SMTP) + HTTP-status classification of
throttle vs lockout, distinct from ordinary transient errors; conservative
so a wrong password or the #390 "IMAP disabled" state is never misread.
- ThrottleBackoff: pure exponential schedule with equal jitter, a bounded cap,
and Retry-After honoring; a longer window for a lockout (sized to Yahoo's ~1h).
- AccountThrottleGate: per-account backoff state (@Singleton), so one throttled
account never stalls the others; PII-free AppLog breadcrumbs on throttle/clear.
- MailBackfiller: skips an account inside its backoff window and stops paging one
that throttles mid-slice (a degradation, not a moreWork spin) — resumes on a
later slice once the window elapses. Reset on the next successful page.
- MailSyncer: foreground sync feeds the gate but is never blocked by it, so
interactive work keeps priority over background backfill.
Integrates with the existing WorkManager retry (#403) and connection reuse
(#357) rather than duplicating them. Unit tests cover classification (positive
+ negative), the backoff schedule, and the degrade-not-tight-loop behaviour
(virtual time for the timing).
Closes#360