The mute toggle, the falling-petals toggle and the chosen companion lived in
localStorage, which is a property of the machine. Now that two people can sign
in to one Petal, sharing a laptop would have meant sharing a mascot and one
person's silence muting the other. Each key is namespaced by user id.
The awkward part is timing: sounds.ts and petals.ts read their value the moment
they are imported, long before /api/me can have answered. Rather than block
startup on the network for a mute flag, a read before the answer arrives sees
the old un-namespaced key -- on a single-writer browser, exactly the right
value -- and setPrefsScope then adopts it into that account's namespace and
tells every reader to look again. Adoption moves rather than copies, so the
first account inherits what was set before accounts existed and the second
starts from Petal's defaults.
The personal spelling dictionary moves further than that: onto the server. It
is built from her own writing, so it should not be readable by whoever sits
down at the same browser next -- but merely namespacing it would have split the
list she already has between her laptop and her tablet, which is worse than
where we started. A table keyed (user_id, lang, word) follows her instead. The
lang is the dictionary's, not hers: an English exception must not silence a
pt-PT flag once the second pair ships.
Adding a word takes effect in the editor immediately and persists in the
background, so the underline goes away the instant she asks. A browser still
holding the old list hands it over on first load, and only lets go once the
server has taken it.
Claude-Session: https://claude.ai/code/session_016y6gyuHkQXPiEuW8RGQyua
Replace the synthesized WAV blips with curated mp3 effects:
- error ("haiya") plays on LLM-down/timeout and save failures, debounced
and on-transition-only, with a reassuring bilingual bubble
- milestone (Chinese fanfare) now fires every 100 words
- all other notifications draw from a rotating pop pool that never repeats
the last sound, so batches of suggestions/tips stay lively
playPop() replaces the per-suggestion-type sound map; thread llmDown through
PetalCompanion -> useCompanion for the error cue. Old synth WAVs removed.
Claude-Session: https://claude.ai/code/session_016Yr6jELuRc7hyzYLccQKZd
Add a fixed, GPU-driven petal layer that drifts soft blossoms over the
page (sparse, translucent, paused when hidden, skipped under
prefers-reduced-motion). Add a synthesized cute sound palette — bubble
pop, water droplet, soft bell, sparkle, cheer — generated as embedded
WAV assets (scripts/gen_sounds.py) and played through a quiet Web Audio
bus with soft-clipping and a persisted mute toggle in the status bar.
Sounds fire per suggestion type when fresh advice arrives (staggered,
old pending advice stays silent) and on companion bubbles by tone.
Claude-Session: https://claude.ai/code/session_016Yr6jELuRc7hyzYLccQKZd