Overall Progress: 65%
Two changes to the Playroom configurator (prototypes/v3/g-playroom.html):
Randomize shipped as variant A · Quick dice (chip + rules popover). The five options remain in prototypes/v3/randomize-lab.html.
In scope:
randomDirs helper + the chosen UI variant in PlayroomOut of scope:
Do not touch:
PRESETS order/ids in story-core.js (Get inspired looks reference them by id)encodeUnit / decodeUnit); a random roll is just another dirs stringstory-v2.js 3D rendererstory-core.js as a pure function next to PRESETS, so it can be tested on its own and other prototypes could reuse it. The UI stays in g-playroom.html.balance() model, the worst case (every shelf facing one way, each loaded to 7 lb) shifts the centre of mass about 2.8″ on Tall and 2.7″ on Standard. The base allows 7.9″. Any random roll is within limits, so this is not a rule the user has to think about.rotate(). Keys are ignored while typing in an input, when the Get inspired drawer is open, or on the Build tab. Handled keys call preventDefault so the pane doesn’t scroll.feature/story-configurator-prototypes. Pushed to https://github.com/xxashleywang/story-bookcase.prototypes/v3/randomize-lab.html with 5 switchable variants: A Quick dice, B Rules card, C Compass, D Lock & roll, E Say it🟩 Step 2: Pick the variant (Ashley): A · Quick dice. Icons only, no emoji (project rule .cursor/rules/icons-not-emoji.mdc).
Story3D.mount(... onSelect): after update(), scrollIntoView({ behavior: 'smooth', block: 'nearest' }) on the Fine-tune block.flash pulse (accent ring, about 1.2s) and a persistent .active outline while sel >= 0keydown listener with the mapping above, plus the guardsrandomDirs(n, { allowed, noRepeat, current }) to story-core.js and exported it (no locks; only variant D needed them)patternName() returns “Random roll” when the pattern matches no preset after a rollstate.dirs → update(). Variant A has no Undo button, so none was added.