- Convert cursor positions to canvas world coordinates (screen→world on
send, world→screen on render) so remote cursors appear at correct
canvas locations regardless of pan/zoom
- Add PresenceManager.setCamera() to reproject cursors on pan/zoom
- Add loading spinner overlay dismissed on first cache hit or sync
- Guard WebSocket open handler with readyState check after async load
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- PresenceManager class tracks remote users' cursors and selections
- SVG cursor with username label and auto-assigned colors
- CommunitySync.sendPresence() broadcasts cursor/selection updates
- Throttled to 50ms to prevent flooding
- Auto-fade after 5s inactivity, auto-remove after 15s
- Selection highlight shows which shape each user has selected
Completes task-7: Real-time presence cursors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>