2fb2d638bf
Resume-prompt Option B (smaller scope variant) — closes the "floating MOVE chip" piece flagged as future scope in v0.21.1's replay-overlay punch list. Leaves the multi-session screen- takeover redesign for a future B-2. The existing banner-anchored MOVE chip stays put — it provides the at-a-glance overview. The new floating chip mirrors the same text but renders above the destination pile of the most-recently- applied move, keeping progress at the player's focal point so they don't have to look up at the banner during fast-paced playback. ### Architecture - New `ReplayFloatingProgressChip` marker component on a `Text2d` entity rendered in 2D world space. World-space placement (rather than UI-space + camera projection) keeps the math trivial — the chip uses the same `LayoutResource` pile coordinates that drive every other piece of pile geometry, so it stays correctly positioned through window resizes without any extra wiring. - Lifecycle matches the banner overlay: `spawn_overlay` spawns the chip alongside the banner when a replay starts; `react_to_state_change` despawns it when the replay ends. The chip lives outside the UI tree (because it's world-space) so the despawn needs its own query — added a second `Query<Entity, With<ReplayFloatingProgressChip>>` parameter. - Z = 100 keeps the chip above every card stack (Z_DROP_OVERLAY = 50, Z_STOCK_BADGE = 30, regular tableau cards stack to the low double digits at most). ### Position + visibility logic `update_floating_progress_chip` runs each Update tick: - Resolves the destination pile of the last-applied move (`replay.moves[cursor - 1]`'s `to`). - Hides the chip when `cursor == 0` (no moves applied yet — nowhere meaningful to land) or when the last move was a `StockClick` (no destination pile, and stock-click feedback already lives at the stock pile — letting the chip jitter back to the stock every cycle would be visual noise). - Otherwise positions the chip at `pile_position + (0, card_size.y * 0.6)` — half a card lifts above the pile centre, the extra 10 % is breathing room above the card's top edge so the chip doesn't visually clip. - Updates the chip text via `format_progress(&state)` — shares the same MOVE N/M format with the banner chip. ### Test New `floating_chip_spawns_and_despawns_with_overlay` pins the lifecycle: chip absent on Inactive, exactly one chip on Playing, absent again on return to Inactive. Position correctness needs `LayoutResource` (which the headless fixture doesn't set up); covered via running-game verification rather than a unit test — the system's gate logic is small enough that pixel positioning isn't load-bearing on a test. 1194 passing (+1 from prior 1193). Workspace clippy clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>