feat(web): add WebSocket client and context infrastructure
- WsClient class: connect/disconnect/send/on/off/isConnected/clearCallbacks
- connect() derives wss:// from https:// automatically, returns Promise<void>
- on/off typed with Extract<WsServerMessage, { type: T }> for precise
callback narrowing, callbacks stored as Map<string, Set<fn>>
- ws-context.ts: WsContextValue type + WsContext definition
- ws-provider.tsx: WsProvider with module-level wsClient singleton,
owns connection lifecycle (connect/disconnect/isConnected state)
- ws-hooks.ts: useWsClient, useWsConnected, useWsConnect, useWsDisconnect