Hardcoded inline <svg class="ic"> markers used as arrow replacements
(left over from emoji removal) were displayed as raw HTML text where
the consumer used textContent or canvas fillText:
- chemsandbox: csbar-v5 (Продукты cell) used textContent → SVG visible.
Switched to innerHTML for consistency with eq/ionNet cells.
Quiz question (qEl.textContent) and answer also receiving SVG —
cleaned via _csClean at source.
- reactions: modeTxt drawn via canvas fillText — replaced SVG with →.
- ionexchange: REACTIONS data + canvas labels — bulk SVG → Unicode arrows.
- newton: action button labels used textContent → switched to innerHTML;
canvas arrow labels: SVG → Unicode →/↓.
- collision: 'KE сохранена' canvas label — SVG checkmark → ✓.
- projectile: canvas badges + textContent wind label — SVG → Unicode ←/→/↩.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Classroom performance:
- WebSocket server (ws-server.js) for low-latency cursor & stroke preview
Replaces HTTP POST per event → eliminates per-message auth overhead
Session member cache (30s TTL) avoids SQLite query per WS message
Fallback to HTTP POST when WS not connected
- Cursor throttle reduced 100ms → 33ms (~30fps)
- Stroke preview throttle reduced 50ms → 20ms
- whiteboard.js: render() is now rAF-gated (_doRender/_rafPending)
Multiple render() calls within one frame collapse into one repaint
document.hidden check — zero CPU when tab is in background
visibilitychange listener restores canvas on tab focus
Guest board:
- guestClassroom.js route: public token-based read-only access
- guest-board.html: name entry + read-only whiteboard + SSE
- SSE: addGuestClient/removeGuestClient/emitToGuests
Screen share picker:
- Discord-style modal with tab switching (screen/window/tab)
- Live video preview before confirming share
- useExistingScreenStream() in ClassroomRTC
Fullscreen exit overlay:
- #cr-fs-exit-overlay button inside cr-board-wrap
- Visible only via CSS :fullscreen selector (touchpad users)
File sharing from library:
- Teacher picks file from library, sends as styled card in chat
- crDownloadLibraryFile() fetches with Bearer auth
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>