diff --git a/.beans/vibed-59dh--bit-by-bit-hidden-attribute-defeated-by-css-displa.md b/.beans/vibed-59dh--bit-by-bit-hidden-attribute-defeated-by-css-displa.md
new file mode 100644
index 0000000..8fea5dc
--- /dev/null
+++ b/.beans/vibed-59dh--bit-by-bit-hidden-attribute-defeated-by-css-displa.md
@@ -0,0 +1,29 @@
+---
+# vibed-59dh
+title: 'bit-by-bit: [hidden] attribute defeated by CSS display rules — celebration overlay stuck onscreen'
+status: completed
+type: bug
+priority: normal
+created_at: 2026-07-14T04:30:04Z
+updated_at: 2026-07-14T04:32:45Z
+---
+
+User report: after onboarding, a bare "You did it!" celebration modal covers the app and its buttons appear dead.
+
+Root cause: `.celebration-overlay`, `.onboarding-overlay` set `display:flex` (and `#artworkActive` has inline `display:flex`, `.upload-preview` sets `display:flex`). Author CSS beats the UA stylesheet's `[hidden]{display:none}`, so toggling the `hidden` attribute in JS has no visual effect on these elements. The celebration overlay was therefore visible from page load with placeholder text, and hideCelebration() couldn't hide it. jsdom tests missed it (no layout).
+
+Fix: global `[hidden]{ display:none !important; }` rule (also covers the inline-style case on #artworkActive).
+
+- [x] Apply global [hidden] rule
+- [x] Verify in a real headless browser: celebration hidden on load, onboarding visible on first run, hides after finishing
+
+## Summary of Changes
+
+Added `[hidden]{ display:none !important; }` to the base styles in `bit-by-bit/index.html` (with a comment explaining why). This makes the `hidden` attribute authoritative over author display rules (`.celebration-overlay`/`.onboarding-overlay` flex, `#artworkActive` inline flex, `.upload-preview` flex).
+
+Verified with headless Firefox screenshots (fresh profile each):
+- Fresh load: onboarding wizard visible, no stray celebration modal.
+- Seeded mid-progress state: main app renders, 3/4 pixels · 75%, overlays hidden.
+- Final check-off: image completes to 4/4 · 100%, canvas keeps showing the finished art via the pendingCelebration snapshot, gallery count increments — confirming the celebration flow renders correctly in a real browser.
+
+Lesson recorded: jsdom flow tests check the hidden property, not computed style — visibility bugs need a real-layout browser check.
diff --git a/.beans/vibed-nz22--bit-by-bit-live-favicon-mirrors-the-partially-reve.md b/.beans/vibed-nz22--bit-by-bit-live-favicon-mirrors-the-partially-reve.md
new file mode 100644
index 0000000..0a67950
--- /dev/null
+++ b/.beans/vibed-nz22--bit-by-bit-live-favicon-mirrors-the-partially-reve.md
@@ -0,0 +1,28 @@
+---
+# vibed-nz22
+title: 'Bit-by-bit: live favicon mirrors the partially revealed artwork'
+status: completed
+type: feature
+priority: normal
+created_at: 2026-07-14T20:46:47Z
+updated_at: 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.
+
+- [x] Add placeholder in head
+- [x] Add updateFavicon() offscreen renderer
+- [x] Hook into renderArt() and applyTheme()
+- [x] Verify no external requests / console errors
+
+## Summary of Changes
+
+- `index.html` head: `` + `` 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 via `toDataURL()`.
+- 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) and `applyTheme()` (bg/static tones are theme-dependent).
+- `docs/DESIGN.md` section 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.
diff --git a/.beans/vibed-orml--bit-by-bit-rename-app-to-paint-by-habits-design-cl.md b/.beans/vibed-orml--bit-by-bit-rename-app-to-paint-by-habits-design-cl.md
new file mode 100644
index 0000000..fcbb9da
--- /dev/null
+++ b/.beans/vibed-orml--bit-by-bit-rename-app-to-paint-by-habits-design-cl.md
@@ -0,0 +1,27 @@
+---
+# vibed-orml
+title: 'bit-by-bit: rename app to ''Paint by Habits'' + design cleanup pass'
+status: completed
+type: task
+priority: normal
+created_at: 2026-07-14T18:53:51Z
+updated_at: 2026-07-14T19:06:14Z
+---
+
+User requests:
+1. Rename the app from "Bit by Bit" to "Paint by Habits" (in-app strings, docs). Keep the localStorage key (bitbybit.v1) for backward compatibility with existing user data.
+2. Capture populated screenshots of every view at desktop and mobile sizes (seeding state artificially where needed), then run a design-focused agent pass to clean up the visual design.
+
+- [x] Rename app in index.html (title, header, about, export filename, aria text; storage key kept for compat)
+- [x] Rename in README/docs
+- [x] Screenshot harness: seeded states, 9 views x mobile/desktop incl. celebration modal (sync-timer trick)
+- [x] Design agent pass applied (Fable fork; 18 before/after screenshots)
+- [x] Re-screenshot + re-validate (node --check clean, zero external refs, after-shots verified)
+
+## Summary of Changes
+
+1. **Rename:** app is now "Paint by Habits" — page title, header, About, storage-warning/import/upload error copy, export filename (`paint-by-habits-backup-*.json`), and all project docs. localStorage keys (`bitbybit.v1`) intentionally unchanged for backward compatibility with existing user data.
+2. **Screenshot harness** (scratchpad `design-shots/`): awk-injected config/seed/driver scripts produce 9 seeded views (main light+dark, onboarding 1+2, four settings tabs, celebration modal via synchronous-timer shim) at 390×844 and 1440×900 in headless Firefox.
+3. **Design pass (Fable fork):** two-column desktop layout ≥880px with sticky artwork card; fixed onboarding overflow at 390px; nowrap buttons + visible disabled states; settings tabs no longer clip on mobile; styled `::file-selector-button`; dark-mode progress track visible; clamp()-sized tinted header title; preset label/spacing polish. Verified across all 18 after-shots; `node --check` clean; still zero external references (73.5KB).
+
+Related: `vibed-p2es` (arbitrary emoji input) created as todo, not implemented per user instruction.
diff --git a/.beans/vibed-p2es--bit-by-bit-allow-arbitrary-emoji-for-habits-not-ju.md b/.beans/vibed-p2es--bit-by-bit-allow-arbitrary-emoji-for-habits-not-ju.md
new file mode 100644
index 0000000..4d8bbde
--- /dev/null
+++ b/.beans/vibed-p2es--bit-by-bit-allow-arbitrary-emoji-for-habits-not-ju.md
@@ -0,0 +1,26 @@
+---
+# vibed-p2es
+title: 'bit-by-bit: allow arbitrary emoji for habits, not just the curated list'
+status: todo
+type: feature
+created_at: 2026-07-14T18:53:47Z
+updated_at: 2026-07-14T18:53:47Z
+---
+
+User request: habits should accept any emoji, not only the 24 curated options in the picker.
+
+Current behavior: the emoji picker is a native