6118d59c5c
Meeting media flows through LiveKit when the server reports sfu:true; otherwise the P2P mesh is unchanged. Reuses the ENTIRE existing meeting UI + WS control plane (join/host/mute/screen/recording/transcript) and only swaps the transport: - vendored livekit-client 2.20 UMD (lazy-loaded; no build step). - sfuInit() reads /api/meetings/config at boot; sfuConnect() joins the LiveKit room with the minted token after the WS meeting-join. - remote tracks map back to the WS peerId via uid (LiveKit identity = app user id); per-peer stream prefers screen over camera, driving the existing sharing/stage UI. - toggleMic/Cam/Screen publish via LiveKit; local tracks reflected into meetLocalStream so tiles, active-speaker meter, canvas recording and transcript keep working. - meetMakePeer/peer-joined/peer-left/leaveMeeting branch on SFU.on; mesh path intact. Needs a running LiveKit server + live test (phase 3 ops) to exercise end-to-end. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>