Sprites were shipped at 512x512 but render at 44-64px in the box grid.
Resizing to 192px halves each file (median 15.5KB -> 7.6KB); a full dex
of artwork drops from 16.6MB to 7.6MB.
The sprite build now also writes static/sprites-small/manifest.json,
listing every sprite (all forms, shiny and female variants) with its
size, so the offline worker can save the complete set and report what
is missing. A unit test keeps it in step with the files on disk.
Each sync created a new artwork cache and re-fetched every sprite with no-cors. Opaque responses are padded to several MB each for storage quota, so a Living Dex grew to tens of GB, syncs never finished, and the offline copy could fail to save.
Artwork now lives in one cache per user that is topped up with only missing sprites, fetched with CORS so they count at their real size, with a per-fetch timeout. The offline copy is committed before any artwork, legacy per-sync artwork caches are removed first, and sprites shown online are cached on first load. Also requests persistent storage.