Chrome Android forces the root URL into PWA installation when required
manifest icon files exist. PWA names come from the manifest and cannot be
edited, which breaks workflows using multiple tracker copies.
Keep required 192/512 icon assets intentionally unavailable by committing
generated files with .png-not suffixes. Removing the manifest link does not
restore root shortcut naming; Chrome still installs the root as a PWA.
Chrome handles /display differently: even with a working manifest it offers
Install app or Create shortcut, and Create shortcut permits renaming. Keep
both manifests intentionally non-installable for consistent user-controlled
shortcut names.
Also add separate player-display favicon/logo artwork and swap /display browser
favicon to player-favicon.ico. Keep generated standard/player logo sources
under renamed inert filenames.
Player display now tracks displayParticipants separately from raw encounter
participants so active->inactive can animate out before removal, and inactive->
active can animate in. This preserves 1-list order, keeps DM display behavior
unchanged, and avoids fading dying/stable participants.
PlayerParticipantCard handles transitions:
- active->inactive: scale/slide/fade out, then parent removes from display list
- inactive->active: scale/slide/fade in
- alive->dead: keep visible with dim/desaturate/red-rim death cue + skull pulse
- dying/stable: full visible, no fade/removal
DisplayView inactive characterization updated to wait for exit animation before
asserting removal. TODO item removed.
- Add status-driven death-save model:
- status: conscious | dying | stable | dead
- deathSaveSuccesses/deathSaveFailures as display counters
- remove old death-save fields as source of truth
- Add death-save actions:
- success, fail, nat1, nat20
- stabilize participant
- revive dead participant to 0 HP, stable, unconscious
- Apply 5e HP transition rules:
- characters and NPCs at 0 HP become dying
- stable/dying participants gain unconscious condition
- healing clears death saves and returns conscious
- massive damage kills
- non-NPC monsters at 0 HP become dead and inactive
- Split NPCs from monsters with type="npc":
- NPCs use death saves like characters
- NPCs remain DM-controlled/monster-colored in UI
- new NPCs no longer persist isNpc flag
- Keep dead PCs/NPCs in encounter and initiative until DM removes or deactivates
- Allow DM active/inactive toggle for dead participants
- Hide inactive participants from player display
- Improve DM and player death-state UI:
- show Dying/Dead/Unconscious states consistently
- add revive button for dead participants
- distinguish dead visual from inactive visual in DM view
- Fix initiative drag/reorder behavior:
- downward drag now changes order instead of no-op
- paused combat can reorder across current turn pointer
- turnOrderIds stay synced to participants order
- Persist campaign collapse state in localStorage
- Update death-save docs and encounter builder docs
- Add/expand tests for:
- death saves and HP transitions
- dead/active/inactive behavior
- NPC death-save behavior
- player display visibility
- drag reorder semantics
- logging expectations
Tests:
- npm run test:all
- app: 94 passed
- shared: 158 passed, 5 skipped
- server: 32 passed
Move all test files out of source dirs into per-workspace tests/:
- shared/tests/ (3 unit test files)
- server/tests/ (1 integration test)
- src/tests/ (8 characterization + scenario tests + testHelpers)
Fix all relative import paths (App, storage, __mocks__, testHelpers).
Fix jest.config testMatch globs in shared/ and server/ (rootDir +
<rootDir>/tests pattern).
Delete scripts/repro-pause-bug.js (debug scratch, superseded by
turn.pause-add.test.js).
Keep scripts/replay-combat.js + scripts/audit-rotation.js as manual
demo/exploratory tools (NOT unit tests, not deterministic).
No logic changes. All green: shared 49 + 1 validated RED, server 23,
FE 62. Scenario test unchanged (240s timeout, pre-existing slow).