2.0 KiB
| title | status | type | priority | created_at | updated_at |
|---|---|---|---|---|---|
| Bit-by-bit: live favicon mirrors the partially revealed artwork | completed | feature | normal | 2026-07-14T20:46:47Z | 2026-07-14T20:53:40Z |
Render the current artwork (revealed pixels solid, unrevealed as loading-static) into a 64x64 offscreen canvas and set it as the page favicon via a data URL, updating on reveal and theme change. Stays single-file, no external requests.
- Add placeholder in head
- Add updateFavicon() offscreen renderer
- Hook into renderArt() and applyTheme()
- Verify no external requests / console errors
Summary of Changes
index.htmlhead:<link id="favicon">+<link id="faviconApple">seeded with an inert 1px data URL.- New
updateFavicon()/drawFavicon(): renders the displayed image into a 64x64 offscreen canvas (integer cell size, letterboxed/centred), revealed pixels solid, unrevealed as an alternating static checker, transparent pixels left as canvas background. Falls back to an 8x8 checker placeholder when no artwork is active. Handed to both link tags viatoDataURL(). - Coalesced with a rAF flag so the burst of
renderArt()calls from one check-off repaints the icon once; href only reassigned when the PNG actually differs. - Hooked into
renderArt()(covers reveal, pop, celebration snapshot, empty state) andapplyTheme()(bg/static tones are theme-dependent). docs/DESIGN.mdsection 5 documents the behavior.
Verification
Headless browser automation was unavailable in the sandbox, so drawFavicon and the reveal-order helpers were extracted verbatim from index.html and executed in Node against a recording canvas stub with a content-hashed toDataURL. With a 16x16 sprite at 5 checks x 8 px/check: 40/40 revealed cells painted solid, 116/116 unrevealed painted static, 100 transparent left as background, 0 mismatches; grid fills the full 64x64; href is stable across an unchanged redraw and changes when more pixels reveal. grep confirms no http://, https://, or fetch( in the file.